Merge yaml2wireviz into wireviz module

This commit is contained in:
Daniel Rojas 2020-05-30 09:13:50 +02:00
parent 50e3441eaa
commit d99952c4d3
3 changed files with 199 additions and 205 deletions

View File

@ -1,7 +1,7 @@
import yaml2wireviz import wireviz
# TODO: make examples (progressively more complex), batch process all of them # TODO: make examples (progressively more complex), batch process all of them
yaml2wireviz.parse('../examples/example1.yml') wireviz.parse('../examples/example1.yml')
yaml2wireviz.parse('../examples/example2.yml') wireviz.parse('../examples/example2.yml')
yaml2wireviz.parse('../examples/ferrules.yml') wireviz.parse('../examples/ferrules.yml')
yaml2wireviz.parse('../examples/bundles.yml') wireviz.parse('../examples/bundles.yml')

194
src/wireviz.py Normal file → Executable file
View File

@ -1,5 +1,8 @@
#!/usr/bin/env python3
import os
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, List from typing import Any, List
import yaml
from graphviz import Graph from graphviz import Graph
COLOR_CODES = {'DIN': ['WH','BN','GN','YE','GY','PK','BU','RD','BK','VT'], # ,'GYPK','RDBU','WHGN','BNGN','WHYE','YEBN','WHGY','GYBN','WHPK','PKBN'], COLOR_CODES = {'DIN': ['WH','BN','GN','YE','GY','PK','BU','RD','BK','VT'], # ,'GYPK','RDBU','WHGN','BNGN','WHYE','YEBN','WHGY','GYBN','WHPK','PKBN'],
@ -385,3 +388,194 @@ def awg_equiv(mm2):
return awg_equiv_table[k] return awg_equiv_table[k]
else: else:
return None return None
def parse(file_in, file_out=None):
file_in = os.path.abspath(file_in)
if not file_out:
file_out = file_in
pre, ext = os.path.splitext(file_out)
file_out = pre # extension will be added by graphviz output function
file_out = os.path.abspath(file_out)
with open(file_in, 'r') as stream:
try:
input = yaml.safe_load(stream)
except yaml.YAMLError as exc:
print(exc)
def expand(input):
# input can be:
# - a singleton (normally str or int)
# - a list of str or int
# if str is of the format '#-#', it is treated as a range (inclusive) and expanded
output = []
if not isinstance(input, list):
input = [input,]
for e in input:
e = str(e)
if '-' in e: # list of pins
a, b = tuple(map(int, e.split('-')))
if a < b:
for x in range(a,b+1):
output.append(x)
elif a > b:
for x in range(a,b-1,-1):
output.append(x)
elif a == b:
output.append(a)
else:
try:
x = int(e)
except:
x = e
output.append(x)
return output
def check_designators(what, where):
for i, x in enumerate(what):
# print('Looking for {} in {}'.format(x,where[i]))
if x not in input[where[i]]:
return False
return True
h = Harness()
# add items
sections = ['nodes','wires','ferrules','connections']
types = [dict, dict, dict, list]
for sec, ty in zip(sections, types):
if sec in input and type(input[sec]) == ty:
if len(input[sec]) > 0:
if ty == dict:
for k, o in input[sec].items():
if sec == 'nodes':
h.add_node(name=k, **o)
elif sec == 'wires':
h.add_cable(name=k, **o)
elif sec == 'ferrules':
pass
else:
print('{} section empty'.format(sec))
else:
print('No {} section found'.format(sec))
if ty == dict:
input[sec] = {}
elif ty == list:
input[sec] = []
# add connections
ferrule_counter = 0
for con in input['connections']:
if len(con) == 3: # format: connector -- wire -- conector
for c in con:
if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator
raise Exception('Too many keys')
from_name = list(con[0].keys())[0]
via_name = list(con[1].keys())[0]
to_name = list(con[2].keys())[0]
if not check_designators([from_name,via_name,to_name],('nodes','wires','nodes')):
raise Exception('Bad connection definition (3)')
from_pins = expand(con[0][from_name])
via_pins = expand(con[1][via_name])
to_pins = expand(con[2][to_name])
if len(from_pins) != len(via_pins) or len(via_pins) != len(to_pins):
raise Exception('List length mismatch')
for (from_pin, via_pin, to_pin) in zip(from_pins, via_pins, to_pins):
h.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin)
elif len(con) == 2:
for c in con:
if type(c) is dict:
if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator
raise Exception('Too many keys')
# hack to make the format for ferrules compatible with the formats for connectors and wires
if type(con[0]) == str:
name = con[0]
con[0] = {}
con[0][name] = name
if type(con[1]) == str:
name = con[1]
con[1] = {}
con[1][name] = name
from_name = list(con[0].keys())[0]
to_name = list(con[1].keys())[0]
n_w = check_designators([from_name, to_name],('nodes','wires'))
w_n = check_designators([from_name, to_name],('wires','nodes'))
n_n = check_designators([from_name, to_name],('nodes','nodes'))
f_w = check_designators([from_name, to_name],('ferrules','wires'))
w_f = check_designators([from_name, to_name],('wires','ferrules'))
if not n_w and not w_n and not n_n and not f_w and not w_f:
raise Exception('Wrong designators')
from_pins = expand(con[0][from_name])
to_pins = expand(con[1][to_name])
if n_w or w_n or n_n:
if len(from_pins) != len(to_pins):
raise Exception('List length mismatch')
if n_w or w_n:
for (from_pin, to_pin) in zip(from_pins, to_pins):
if n_w:
h.connect(from_name, from_pin, to_name, to_pin, None, None)
else: # w_n
h.connect(None, None, from_name, from_pin, to_name, to_pin)
elif n_n:
con_name = list(con[0].keys())[0]
from_pins = expand(con[0][from_name])
to_pins = expand(con[1][to_name])
for (from_pin, to_pin) in zip(from_pins, to_pins):
h.loop(con_name, from_pin, to_pin)
if f_w or w_f:
from_pins = expand(con[0][from_name])
to_pins = expand(con[1][to_name])
if f_w:
ferrule_name = from_name
wire_name = to_name
wire_pins = to_pins
else:
ferrule_name = to_name
wire_name = from_name
wire_pins = from_pins
ferrule_params = input['ferrules'][ferrule_name]
for wire_pin in wire_pins:
ferrule_counter = ferrule_counter + 1
ferrule_id = 'F{}'.format(ferrule_counter)
h.add_node(ferrule_id, **ferrule_params)
if f_w:
h.connect(ferrule_id, 1, wire_name, wire_pin, None, None)
else:
h.connect(None, None, wire_name, wire_pin, ferrule_id, 1)
else:
raise Exception('Wrong number of connection parameters')
h.output(filename=file_out, format=('png','svg'), view=False)
if __name__ == '__main__':
import argparse
ap = argparse.ArgumentParser()
ap.add_argument('file_input', nargs='?', default='_test/test.yml')
ap.add_argument('file_output', nargs='?', default=None)
args = ap.parse_args()
parse(args.file_input, args.file_output)

View File

@ -1,200 +0,0 @@
#!/usr/bin/env python3
import os
import yaml
import wireviz
def expand(input):
# input can be:
# - a singleton (normally str or int)
# - a list of str or int
# if str is of the format '#-#', it is treated as a range (inclusive) and expanded
output = []
if not isinstance(input, list):
input = [input,]
for e in input:
e = str(e)
if '-' in e: # list of pins
a, b = tuple(map(int, e.split('-')))
if a < b:
for x in range(a,b+1):
output.append(x)
elif a > b:
for x in range(a,b-1,-1):
output.append(x)
elif a == b:
output.append(a)
else:
try:
x = int(e)
except:
x = e
output.append(x)
return output
def _parse(file_in, file_out):
def check_designators(what, where):
for i, x in enumerate(what):
# print('Looking for {} in {}'.format(x,where[i]))
if x not in input[where[i]]:
return False
return True
with open(file_in, 'r') as stream:
try:
input = yaml.safe_load(stream)
except yaml.YAMLError as exc:
print(exc)
h = wireviz.Harness()
# add items
sections = ['nodes','wires','ferrules','connections']
types = [dict, dict, dict, list]
for sec, ty in zip(sections, types):
if sec in input and type(input[sec]) == ty:
if len(input[sec]) > 0:
if ty == dict:
for k, o in input[sec].items():
if sec == 'nodes':
h.add_node(name=k, **o)
elif sec == 'wires':
h.add_cable(name=k, **o)
elif sec == 'ferrules':
pass
else:
print('{} section empty'.format(sec))
else:
print('No {} section found'.format(sec))
if ty == dict:
input[sec] = {}
elif ty == list:
input[sec] = []
# add connections
ferrule_counter = 0
for con in input['connections']:
if len(con) == 3: # format: connector -- wire -- conector
for c in con:
if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator
raise Exception('Too many keys')
from_name = list(con[0].keys())[0]
via_name = list(con[1].keys())[0]
to_name = list(con[2].keys())[0]
if not check_designators([from_name,via_name,to_name],('nodes','wires','nodes')):
raise Exception('Bad connection definition (3)')
from_pins = expand(con[0][from_name])
via_pins = expand(con[1][via_name])
to_pins = expand(con[2][to_name])
if len(from_pins) != len(via_pins) or len(via_pins) != len(to_pins):
raise Exception('List length mismatch')
for (from_pin, via_pin, to_pin) in zip(from_pins, via_pins, to_pins):
h.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin)
elif len(con) == 2:
for c in con:
if type(c) is dict:
if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator
raise Exception('Too many keys')
# hack to make the format for ferrules compatible with the formats for connectors and wires
if type(con[0]) == str:
name = con[0]
con[0] = {}
con[0][name] = name
if type(con[1]) == str:
name = con[1]
con[1] = {}
con[1][name] = name
from_name = list(con[0].keys())[0]
to_name = list(con[1].keys())[0]
n_w = check_designators([from_name, to_name],('nodes','wires'))
w_n = check_designators([from_name, to_name],('wires','nodes'))
n_n = check_designators([from_name, to_name],('nodes','nodes'))
f_w = check_designators([from_name, to_name],('ferrules','wires'))
w_f = check_designators([from_name, to_name],('wires','ferrules'))
if not n_w and not w_n and not n_n and not f_w and not w_f:
raise Exception('Wrong designators')
from_pins = expand(con[0][from_name])
to_pins = expand(con[1][to_name])
if n_w or w_n or n_n:
if len(from_pins) != len(to_pins):
raise Exception('List length mismatch')
if n_w or w_n:
for (from_pin, to_pin) in zip(from_pins, to_pins):
if n_w:
h.connect(from_name, from_pin, to_name, to_pin, None, None)
else: # w_n
h.connect(None, None, from_name, from_pin, to_name, to_pin)
elif n_n:
con_name = list(con[0].keys())[0]
from_pins = expand(con[0][from_name])
to_pins = expand(con[1][to_name])
for (from_pin, to_pin) in zip(from_pins, to_pins):
h.loop(con_name, from_pin, to_pin)
if f_w or w_f:
from_pins = expand(con[0][from_name])
to_pins = expand(con[1][to_name])
if f_w:
ferrule_name = from_name
wire_name = to_name
wire_pins = to_pins
else:
ferrule_name = to_name
wire_name = from_name
wire_pins = from_pins
ferrule_params = input['ferrules'][ferrule_name]
for wire_pin in wire_pins:
ferrule_counter = ferrule_counter + 1
ferrule_id = 'F{}'.format(ferrule_counter)
h.add_node(ferrule_id, **ferrule_params)
if f_w:
h.connect(ferrule_id, 1, wire_name, wire_pin, None, None)
else:
h.connect(None, None, wire_name, wire_pin, ferrule_id, 1)
else:
raise Exception('Wrong number of connection parameters')
h.output(filename=file_out, format=('png','svg'), view=False)
def parse(filename_in, filename_out=None):
fin = os.path.abspath(filename_in)
if filename_out:
fout = filename_out
else:
fout = fin
pre, ext = os.path.splitext(fout)
fout = pre # extension will be added by graphviz output function
fout = os.path.abspath(fout)
_parse(fin, fout)
if __name__ == '__main__':
import argparse
ap = argparse.ArgumentParser()
ap.add_argument('file_input', nargs='?', default='_test/test.yml')
ap.add_argument('file_output', nargs='?', default=None)
args = ap.parse_args()
parse(args.file_input, args.file_output)