From 591829b6fcf095542539e7e5bae1ca0288fc7438 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Wed, 27 May 2020 21:49:18 +0200 Subject: [PATCH 1/9] Add unnamed connector ('ferrule') support proof of concept --- examples/ferrules.yml | 36 +++++++ src/yaml2wireviz.py | 221 +++++++++++++++++++++++++++--------------- 2 files changed, 180 insertions(+), 77 deletions(-) create mode 100644 examples/ferrules.yml diff --git a/examples/ferrules.yml b/examples/ferrules.yml new file mode 100644 index 0000000..9fb8319 --- /dev/null +++ b/examples/ferrules.yml @@ -0,0 +1,36 @@ +nodes: + X1: + type: D-Sub + gender: female + num_pins: 4 + X2: + type: Molex KK 254 + gender: female + num_pins: 3 + +wires: + W1: + mm2: 0.25 + length: 0.2 + color_code: IEC + num_wires: 10 + shield: true + +ferrules: + F_test: + type: crimp + +connections: + - + - X1: [1-3] + - W1: [1-3] + - X2: [1-3] + - + - X1: 4 + - W1: s + - + - F_test + - W1: [4-10] + - + - W1: [10-4] + - F_test diff --git a/src/yaml2wireviz.py b/src/yaml2wireviz.py index 6da74f1..3d6bbc9 100644 --- a/src/yaml2wireviz.py +++ b/src/yaml2wireviz.py @@ -1,7 +1,7 @@ import yaml import wireviz -filename = '../examples/example2.yml' +filename = '../examples/ferrules.yml' def check_designators(what, where): for i,x in enumerate(what): @@ -46,82 +46,149 @@ with open(filename, 'r') as stream: h = wireviz.Harness() # add nodes -for k, o in input['nodes'].items(): - h.add_node(k, type=o.get('type'), - gender=o.get('gender'), - num_pins=o.get('num_pins'), - pinout=o.get('pinout')) -# add wires -for k, o in input['wires'].items(): - h.add_cable(k, mm2=o.get('mm2'), - awg=o.get('awg'), - length=o.get('length'), - num_wires=o.get('num_wires'), - colors=o.get('colors'), - color_code=o.get('color_code'), - shield=o.get('shield')) -# add connections -conlist = input['connections'] -for con in conlist: - 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 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] - 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')) - - if not n_w and not w_n and not n_n: - raise Exception('Wrong designators') - - from_pins = expand(con[0][from_name]) - to_pins = expand(con[1][to_name]) - - if len(from_pins) != len(to_pins): - raise Exception('List length mismatch') - - if n_w == True or w_n == True: - 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 == True: - 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 'nodes' in input and type(input['nodes']) == dict: + if len(input['nodes']) > 0: + for k, o in input['nodes'].items(): + h.add_node(k, type=o.get('type'), + gender=o.get('gender'), + num_pins=o.get('num_pins'), + pinout=o.get('pinout')) else: - raise Exception('Wrong number of connection parameters') + print('Node list empty') +else: + print('No node list found') + input['nodes'] = {} + +# add wires +if 'wires' in input and type(input['wires']) == dict: + if len(input['wires']) > 0: + for k, o in input['wires'].items(): + h.add_cable(k, mm2=o.get('mm2'), + awg=o.get('awg'), + length=o.get('length'), + num_wires=o.get('num_wires'), + colors=o.get('colors'), + color_code=o.get('color_code'), + shield=o.get('shield')) + else: + print('Wire list empty') +else: + print('No wire list found') + input['wires'] = {} + +# add connections +if 'connections' in input: + if len(input['connections']) > 0: + ferrule_counter = 0 + conlist = input['connections'] + for con in conlist: + 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 == True or w_n == True: + 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 == True: + 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 == True or w_f == True: + from_pins = expand(con[0][from_name]) + to_pins = expand(con[1][to_name]) + + if f_w == True: + 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 = 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, type=ferrule.get('type'), + gender=ferrule.get('gender'), + num_pins=ferrule.get('num_pins'), + pinout=ferrule.get('pinout')) + + if f_w == True: + 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') + else: + print('Connection list empty') +else: + print('No connection list found') + input['connections'] = {} h.output(filename='output', format=('png','svg'), view=False) From 71641df39b1405eed42c89eb12494ad144a77739 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Wed, 27 May 2020 22:10:47 +0200 Subject: [PATCH 2/9] Fine-tune wire colors --- src/wireviz.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wireviz.py b/src/wireviz.py index 55b5d0a..fa3dbac 100644 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -8,14 +8,14 @@ COLOR_CODES = {'DIN': ['WH','BN','GN','YE','GY','PK','BU','RD','BK','VT'], # ,'G color_hex = { 'BK': '#000000', 'WH': '#ffffff', - 'GY': '#808080', - 'PK': '#ff80c0', + 'GY': '#999999', + 'PK': '#ff66cc', 'RD': '#ff0000', 'OG': '#ff8000', 'YE': '#ffff00', - 'GN': '#00ff00', + 'GN': '#009900', 'TQ': '#00ffff', - 'BU': '#0000ff', + 'BU': '#0066ff', 'VT': '#8000ff', 'BN': '#666600', } From 07567be3cabeba3a00e11e948485aa8fbde5d567 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 28 May 2020 17:51:30 +0200 Subject: [PATCH 3/9] Clean up code --- src/wireviz.py | 39 ++++++++++++++++++--------------------- src/yaml2wireviz.py | 12 ++++++------ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/wireviz.py b/src/wireviz.py index fa3dbac..4e774ce 100644 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -82,38 +82,36 @@ class Harness: dot.attr('edge', style='bold', fontname=font) # prepare ports on connectors depending on which side they will connect - for k in self.cables: - c = self.cables[k] + for k, c in self.cables.items(): for x in c.connections: if x[1] is not None: # connect to left self.nodes[x[0]].ports_right = True if x[4] is not None: # connect to right self.nodes[x[3]].ports_left = True - for k in self.nodes: - n = self.nodes[k] + for k, n in self.nodes.items(): # a = attributes a = [n.type, n.gender, - '{}-pin'.format(len(n.pinout)) if n.show_num_pins == True else ''] + '{}-pin'.format(len(n.pinout)) if n.show_num_pins else ''] # p = pinout p = [[],[],[]] p[1] = list(n.pinout) - for i,x in enumerate(n.pinout, 1): - if n.ports_left == True: + for i, x in enumerate(n.pinout, 1): + if n.ports_left: p[0].append('{portno}'.format(portno=i)) - if n.ports_right == True: + if n.ports_right: p[2].append('{portno}'.format(portno=i)) # l = label - l = [n.name if n.show_name == True else '', a, p] + l = [n.name if n.show_name else '', a, p] dot.node(k, label=nested(l)) if len(n.loops) > 0: dot.attr('edge',color='#000000') - if n.ports_left == True: + if n.ports_left: loop_side = 'l' loop_dir = 'w' - elif n.ports_right == True: + elif n.ports_right: loop_side = 'r' loop_dir = 'e' else: @@ -122,24 +120,23 @@ class Harness: dot.edge('{name}:p{port_from}{loop_side}:{loop_dir}'.format(name=n.name, port_from=x[0], port_to=x[1], loop_side=loop_side, loop_dir=loop_dir), '{name}:p{port_to}{loop_side}:{loop_dir}'.format(name=n.name, port_from=x[0], port_to=x[1], loop_side=loop_side, loop_dir=loop_dir)) - for k in self.cables: - c = self.cables[k] + for k, c in self.cables.items(): # a = attributes - a = ['{}x'.format(len(c.colors)) if c.show_num_wires == True else '', - '{} mm\u00B2{}'.format(c.mm2, ' ({} AWG)'.format(awg_equiv(c.mm2)) if c.show_equiv == True else '') if c.mm2 is not None else '', + a = ['{}x'.format(len(c.colors)) if c.show_num_wires else '', + '{} mm\u00B2{}'.format(c.mm2, ' ({} AWG)'.format(awg_equiv(c.mm2)) if c.show_equiv else '') if c.mm2 is not None else '', c.awg, - '+ S' if c.shield == True else '', + '+ S' if c.shield else '', '{} m'.format(c.length) if c.length > 0 else ''] # p = pinout p = [[],[],[]] - for i,x in enumerate(c.colors,1): + for i, x in enumerate(c.colors,1): if c.show_pinout: p[0].append('{wireno}'.format(wireno=i)) p[1].append('{wirecolor}'.format(wirecolor=translate_color(x, self.color_mode))) p[2].append('{wireno}'.format(wireno=i)) else: p[1].append('{wirecolor}'.format(wireno=i,wirecolor=translate_color(x, self.color_mode))) - if c.shield == True: + if c.shield: if c.show_pinout: p[0].append('') p[1].append('Shield') @@ -147,7 +144,7 @@ class Harness: else: p[1].append('Shield') # l = label - l = [c.name if c.show_name == True else '', a, p] + l = [c.name if c.show_name else '', a, p] dot.node(k, label=nested(l)) # connections @@ -162,10 +159,10 @@ class Harness: dot.attr('edge',color='#000000') if x[1] is not None: # connect to left dot.edge('{from_name}:p{from_port}r'.format(from_name=x[0],from_port=x[1]), - '{via_name}:w{via_wire}{via_subport}'.format(via_name=c.name, via_wire=x[2], via_subport='i' if c.show_pinout == True else '')) + '{via_name}:w{via_wire}{via_subport}'.format(via_name=c.name, via_wire=x[2], via_subport='i' if c.show_pinout else '')) # self.nodes[x[0]].ports_right = True if x[4] is not None: # connect to right - dot.edge('{via_name}:w{via_wire}{via_subport}'.format(via_name=c.name, via_wire=x[2], via_subport='o' if c.show_pinout == True else ''), + dot.edge('{via_name}:w{via_wire}{via_subport}'.format(via_name=c.name, via_wire=x[2], via_subport='o' if c.show_pinout else ''), '{to_name}:p{to_port}l'.format(to_name=x[3], to_port=x[4])) # self.nodes[x[3]].ports_left = True diff --git a/src/yaml2wireviz.py b/src/yaml2wireviz.py index 3d6bbc9..0f599b6 100644 --- a/src/yaml2wireviz.py +++ b/src/yaml2wireviz.py @@ -4,7 +4,7 @@ import wireviz filename = '../examples/ferrules.yml' def check_designators(what, where): - for i,x in enumerate(what): + for i, x in enumerate(what): # print('Looking for {} in {}'.format(x,where[i])) if x not in input[where[i]]: return False @@ -142,24 +142,24 @@ if 'connections' in input: if len(from_pins) != len(to_pins): raise Exception('List length mismatch') - if n_w == True or w_n == True: + 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 == True: + 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 == True or w_f == True: + if f_w or w_f: from_pins = expand(con[0][from_name]) to_pins = expand(con[1][to_name]) - if f_w == True: + if f_w: ferrule_name = from_name wire_name = to_name wire_pins = to_pins @@ -177,7 +177,7 @@ if 'connections' in input: num_pins=ferrule.get('num_pins'), pinout=ferrule.get('pinout')) - if f_w == True: + 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) From ab922928de2902f2d9119a887726e365f7a58177 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 28 May 2020 18:37:44 +0200 Subject: [PATCH 4/9] Simplify __init__ functions, Pt. I --- examples/example1.yml | 1 - src/wireviz.py | 42 ++++++++++++++++++++++++++++++------------ src/yaml2wireviz.py | 25 ++++++++++++++----------- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/examples/example1.yml b/examples/example1.yml index 05a5877..7398666 100644 --- a/examples/example1.yml +++ b/examples/example1.yml @@ -3,7 +3,6 @@ nodes: type: D-Sub gender: female pinout: [DCD, RX, TX, DTR, GND, DSR, RTS, CTS, RI] - random: yes X2: type: Molex KK 254 gender: female diff --git a/src/wireviz.py b/src/wireviz.py index 4e774ce..db68863 100644 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -57,11 +57,11 @@ class Harness: self.nodes = {} self.cables = {} - def add_node(self, name, type=None, gender=None, show_name=True, num_pins=None, show_num_pins=True, pinout=None, ports_left=False, ports_right=False): - self.nodes[name] = Node(name, type, gender, show_name, num_pins, show_num_pins, pinout, ports_left, ports_right) + def add_node(self, name, *args, **kwargs): + self.nodes[name] = Node(name, *args, **kwargs) - def add_cable(self, name, mm2=None, awg=None, show_equiv=False, length=0, show_name=False, show_pinout=False, num_wires=None, show_num_wires=True, colors=None, color_code=None, shield=False): - self.cables[name] = Cable(name, mm2, awg, show_equiv, length, show_name, show_pinout, num_wires, show_num_wires, colors, color_code, shield) + def add_cable(self, name, *args, **kwargs): + self.cables[name] = Cable(name, *args, **kwargs) def loop(self, node_name, from_pin, to_pin): self.nodes[node_name].loop(from_pin, to_pin) @@ -177,14 +177,22 @@ class Harness: class Node: - def __init__(self, name, type=None, gender=None, show_name=True, num_pins=None, show_num_pins=True, pinout=None, ports_left=False, ports_right=False): + def __init__(self, name, + type=None, + gender=None, + show_name=True, + num_pins=True, + show_num_pins=None, + pinout=None): self.name = name self.type = type self.gender = gender self.show_name = show_name self.show_num_pins = show_num_pins - self.ports_left = ports_left - self.ports_right = ports_right + # self.pinout = [] + + self.ports_left = False + self.ports_right = False self.loops = [] if pinout is None: @@ -193,17 +201,27 @@ class Node: self.pinout = ('',) * num_pins else: if num_pins is None: - if pinout is None: - raise Exception('Must provide num_pins or pinout') - else: - self.pinout = pinout + raise Exception('Must provide num_pins or pinout') + else: + self.pinout = pinout def loop(self, from_pin, to_pin): self.loops.append((from_pin, to_pin)) class Cable: - def __init__(self, name, mm2=None, awg=None, show_equiv=False, length=0, show_name=False, show_pinout=False, num_wires=None, show_num_wires=True, colors=None, color_code=None, shield=False): + def __init__(self, name, + mm2=None, + awg=None, + show_equiv=False, + length=0, + show_name=False, + show_pinout=False, + num_wires=None, + show_num_wires=True, + colors=None, + color_code=None, + shield=False ): self.name = name if mm2 is not None and awg is not None: raise Exception('You cannot define both mm2 and awg!') diff --git a/src/yaml2wireviz.py b/src/yaml2wireviz.py index 0f599b6..f171726 100644 --- a/src/yaml2wireviz.py +++ b/src/yaml2wireviz.py @@ -1,6 +1,8 @@ import yaml import wireviz +filename = '../examples/example1.yml' +filename = '../examples/example2.yml' filename = '../examples/ferrules.yml' def check_designators(what, where): @@ -49,10 +51,7 @@ h = wireviz.Harness() if 'nodes' in input and type(input['nodes']) == dict: if len(input['nodes']) > 0: for k, o in input['nodes'].items(): - h.add_node(k, type=o.get('type'), - gender=o.get('gender'), - num_pins=o.get('num_pins'), - pinout=o.get('pinout')) + h.add_node(name=k, **o) else: print('Node list empty') else: @@ -63,19 +62,22 @@ else: if 'wires' in input and type(input['wires']) == dict: if len(input['wires']) > 0: for k, o in input['wires'].items(): - h.add_cable(k, mm2=o.get('mm2'), - awg=o.get('awg'), - length=o.get('length'), - num_wires=o.get('num_wires'), - colors=o.get('colors'), - color_code=o.get('color_code'), - shield=o.get('shield')) + h.add_cable(name=k, **o) else: print('Wire list empty') else: print('No wire list found') input['wires'] = {} +if 'ferrules' in input and type(input['ferrules']) == dict: + if len(input['wires']) > 0: + pass + else: + print('Ferrule list empty') +else: + print('No ferrule list found') + input['ferrules'] = {} + # add connections if 'connections' in input: if len(input['connections']) > 0: @@ -129,6 +131,7 @@ if 'connections' in input: 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')) From 77a69d23629caebb27098ef50eff29997fafbd0c Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 28 May 2020 18:46:25 +0200 Subject: [PATCH 5/9] Simplify processing input file sections --- src/yaml2wireviz.py | 227 +++++++++++++++++++++----------------------- 1 file changed, 106 insertions(+), 121 deletions(-) diff --git a/src/yaml2wireviz.py b/src/yaml2wireviz.py index f171726..6375ac7 100644 --- a/src/yaml2wireviz.py +++ b/src/yaml2wireviz.py @@ -47,151 +47,136 @@ with open(filename, 'r') as stream: print(exc) h = wireviz.Harness() -# add nodes -if 'nodes' in input and type(input['nodes']) == dict: - if len(input['nodes']) > 0: - for k, o in input['nodes'].items(): - h.add_node(name=k, **o) - else: - print('Node list empty') -else: - print('No node list found') - input['nodes'] = {} -# add wires -if 'wires' in input and type(input['wires']) == dict: - if len(input['wires']) > 0: - for k, o in input['wires'].items(): - h.add_cable(name=k, **o) +# 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('Wire list empty') -else: - print('No wire list found') - input['wires'] = {} - -if 'ferrules' in input and type(input['ferrules']) == dict: - if len(input['wires']) > 0: - pass - else: - print('Ferrule list empty') -else: - print('No ferrule list found') - input['ferrules'] = {} + print('No {} section found'.format(sec)) + if ty == dict: + input[sec] = {} + elif ty == list: + input[sec] = [] # add connections -if 'connections' in input: - if len(input['connections']) > 0: - ferrule_counter = 0 - conlist = input['connections'] - for con in conlist: - if len(con) == 3: # format: connector -- wire -- conector +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') + 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] + 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)') + 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]) + 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') + 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) + 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: + 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') + 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 + # 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] + 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')) + 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')) + 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') + 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]) + 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 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 = 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, type=ferrule.get('type'), - gender=ferrule.get('gender'), - num_pins=ferrule.get('num_pins'), - pinout=ferrule.get('pinout')) - - 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) + 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: - raise Exception('Wrong number of connection parameters') + ferrule_name = to_name + wire_name = from_name + wire_pins = from_pins + + ferrule = 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, type=ferrule.get('type'), + gender=ferrule.get('gender'), + num_pins=ferrule.get('num_pins'), + pinout=ferrule.get('pinout')) + + 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: - print('Connection list empty') -else: - print('No connection list found') - input['connections'] = {} + raise Exception('Wrong number of connection parameters') h.output(filename='output', format=('png','svg'), view=False) From aeda312ffdf58f6311c55ba2c044496b7762ef1d Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 28 May 2020 19:02:30 +0200 Subject: [PATCH 6/9] Simplify __init__ functions, Pt. II --- src/wireviz.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/wireviz.py b/src/wireviz.py index db68863..d068f15 100644 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -180,10 +180,12 @@ class Node: def __init__(self, name, type=None, gender=None, - show_name=True, num_pins=True, + pinout=None, + + show_name=True, show_num_pins=None, - pinout=None): + ): self.name = name self.type = type self.gender = gender @@ -215,13 +217,15 @@ class Cable: awg=None, show_equiv=False, length=0, - show_name=False, - show_pinout=False, num_wires=None, - show_num_wires=True, + shield=False, colors=None, color_code=None, - shield=False ): + + show_name=False, + show_pinout=False, + show_num_wires=True, + ): self.name = name if mm2 is not None and awg is not None: raise Exception('You cannot define both mm2 and awg!') From 516d8c30f44739a554026dcae01e22e90f574652 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 28 May 2020 20:01:13 +0200 Subject: [PATCH 7/9] Simplify __init__ functions, Pt. III: use dataclasses --- src/wireviz.py | 119 ++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 61 deletions(-) diff --git a/src/wireviz.py b/src/wireviz.py index d068f15..a419389 100644 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -1,3 +1,5 @@ +from dataclasses import dataclass, field +from typing import Any, List 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'], @@ -175,94 +177,89 @@ class Harness: d.render(filename=filename, directory=directory, view=view, cleanup=cleanup) d.save(filename='{}.gv'.format(filename), directory=directory) +@dataclass class Node: + name: str + type: str = None + gender: str = None + num_pins: int = None + pinout: List[Any] = field(default_factory=list) + show_name: bool = False + show_num_pins: bool = False - def __init__(self, name, - type=None, - gender=None, - num_pins=True, - pinout=None, - - show_name=True, - show_num_pins=None, - ): - self.name = name - self.type = type - self.gender = gender - self.show_name = show_name - self.show_num_pins = show_num_pins - # self.pinout = [] - + def __post_init__(self): self.ports_left = False self.ports_right = False self.loops = [] - if pinout is None: - if num_pins is None: - num_pins = 1 - self.pinout = ('',) * num_pins + if self.pinout: + if self.num_pins is not None: + raise Exception('You cannot specify both pinout and num_pins') else: - if num_pins is None: - raise Exception('Must provide num_pins or pinout') - else: - self.pinout = pinout + if not self.num_pins: + self.num_pins = 1 + self.pinout = ['',] * self.num_pins def loop(self, from_pin, to_pin): self.loops.append((from_pin, to_pin)) +@dataclass class Cable: + name: str + mm2: float = None + awg: int = None + show_equiv: bool = False + length: float = 0 + num_wires: int = None + shield: bool = False + colors: List[Any] = field(default_factory=list) + color_code: str = None + show_name: bool = False + show_pinout: bool = False + show_num_wires: bool = True - def __init__(self, name, - mm2=None, - awg=None, - show_equiv=False, - length=0, - num_wires=None, - shield=False, - colors=None, - color_code=None, - - show_name=False, - show_pinout=False, - show_num_wires=True, - ): - self.name = name - if mm2 is not None and awg is not None: + def __post_init__(self): + if self.mm2 and self.awg: raise Exception('You cannot define both mm2 and awg!') - self.mm2 = mm2 - self.awg = awg - self.show_equiv = show_equiv - self.length = length - self.show_name = show_name - self.show_pinout = show_pinout - self.show_num_wires = show_num_wires - self.shield = shield self.connections = [] - if color_code is None and colors is None: - self.colors = ('',) * num_wires + + # TODO: fix logic + + # OK: + # only num_wires, no colors + # num_wires + colors + # num_wires + color code + # colors (num_wires implicit) + + # NOK: + # color_code only + # nothing + + if self.color_code is None and self.colors is None: + self.colors = ('',) * self.num_wires else: - if colors is None: # no custom color pallet was specified - if num_wires is None: + if not self.colors: # no custom color pallet was specified + if not self.num_wires: raise Exception('Unknown number of wires') else: - if color_code is None: + if not self.color_code: raise Exception('No color code') # choose color code - if color_code not in COLOR_CODES: + if self.color_code not in COLOR_CODES: raise Exception('Unknown color code') else: - cc = COLOR_CODES[color_code] - n = num_wires + cc = COLOR_CODES[self.color_code] + n = self.num_wires else: # custom color pallet was specified - cc = colors - if num_wires is None: # assume number of wires = number of items in custom pallet + cc = self.colors + if self.num_wires is None: # assume number of wires = number of items in custom pallet n = len(cc) else: # number of wires was specified - n = num_wires + n = self.num_wires cc = tuple(cc) - if n > len(cc): - m = num_wires // len(cc) + 1 + if n > len(cc): # make color code loop around if more wires than colors + m = self.num_wires // len(cc) + 1 cc = cc * int(m) self.colors = cc[:n] From 5867bd50c4a3166dfa8055550dcaec348dd3f465 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 28 May 2020 20:27:54 +0200 Subject: [PATCH 8/9] Clean up wire color assignment logic --- src/wireviz.py | 56 +++++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/src/wireviz.py b/src/wireviz.py index a419389..fa47aea 100644 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -223,45 +223,27 @@ class Cable: raise Exception('You cannot define both mm2 and awg!') self.connections = [] - # TODO: fix logic + if self.num_wires: # number of wires explicitly defined + if self.colors: # use custom color palette (partly or looped if needed) + pass + elif self.color_code: # use standard color palette (partly or looped if needed) + if self.color_code not in COLOR_CODES: + raise Exception('Unknown color code') + self.colors = COLOR_CODES[self.color_code] + else: # no colors defined, add dummy colors + self.colors = [''] * self.num_wires - # OK: - # only num_wires, no colors - # num_wires + colors - # num_wires + color code - # colors (num_wires implicit) + # make color code loop around if more wires than colors + if self.num_wires > len(self.colors): + m = self.num_wires // len(self.colors) + 1 + self.colors = self.colors * int(m) + # cut off excess after looping + self.colors = self.colors[:self.num_wires] - # NOK: - # color_code only - # nothing - - if self.color_code is None and self.colors is None: - self.colors = ('',) * self.num_wires - else: - if not self.colors: # no custom color pallet was specified - if not self.num_wires: - raise Exception('Unknown number of wires') - else: - if not self.color_code: - raise Exception('No color code') - # choose color code - if self.color_code not in COLOR_CODES: - raise Exception('Unknown color code') - else: - cc = COLOR_CODES[self.color_code] - n = self.num_wires - else: # custom color pallet was specified - cc = self.colors - if self.num_wires is None: # assume number of wires = number of items in custom pallet - n = len(cc) - else: # number of wires was specified - n = self.num_wires - - cc = tuple(cc) - if n > len(cc): # make color code loop around if more wires than colors - m = self.num_wires // len(cc) + 1 - cc = cc * int(m) - self.colors = cc[:n] + else: # num_wires implicit in length of color list + if not self.colors: + raise Exception('Unknown number of wires. Must specify num_wires or colors (implicit length)') + self.num_wires = len(self.colors) def connect(self, from_name, from_pin, via_pin, to_name, to_pin): from_pin = int2tuple(from_pin) From 5461cb016d28adc171a5f1eb59d70e5687ea8dae Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 28 May 2020 20:35:35 +0200 Subject: [PATCH 9/9] Simplify ferrule creation --- src/yaml2wireviz.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/yaml2wireviz.py b/src/yaml2wireviz.py index 6375ac7..b922d4e 100644 --- a/src/yaml2wireviz.py +++ b/src/yaml2wireviz.py @@ -161,14 +161,11 @@ for con in input['connections']: wire_name = from_name wire_pins = from_pins - ferrule = input['ferrules'][ferrule_name] + 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, type=ferrule.get('type'), - gender=ferrule.get('gender'), - num_pins=ferrule.get('num_pins'), - pinout=ferrule.get('pinout')) + h.add_node(ferrule_id, **ferrule_params) if f_w: h.connect(ferrule_id, 1, wire_name, wire_pin, None, None)