From 151f3d46b1fa4e51028af9bf5f1e812b093bddaa Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Wed, 11 Nov 2020 16:13:47 +0100 Subject: [PATCH 1/3] Allow referencing wires by color/label (#169,#193) --- src/wireviz/DataClasses.py | 17 ++++++++--- src/wireviz/Harness.py | 60 ++++++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py index 35003075..7f01ffdf 100644 --- a/src/wireviz/DataClasses.py +++ b/src/wireviz/DataClasses.py @@ -181,9 +181,11 @@ class Cable: image: Optional[Image] = None notes: Optional[MultilineHypertext] = None colors: List[Colors] = field(default_factory=list) + wirelabels: List[Wire] = field(default_factory=list) color_code: Optional[ColorScheme] = None show_name: bool = True show_wirecount: bool = True + show_wirenumbers: Optional[bool] = None ignore_in_bom: bool = False additional_components: List[AdditionalComponent] = field(default_factory=list) @@ -233,6 +235,10 @@ def __post_init__(self) -> None: raise Exception('Unknown number of wires. Must specify wirecount or colors (implicit length)') self.wirecount = len(self.colors) + if self.wirelabels: + if self.shield and 's' in self.wirelabels: + raise Exception('"s" may not be used as a wire label for a shielded cable.') + # if lists of part numbers are provided check this is a bundle and that it matches the wirecount. for idfield in [self.manufacturer, self.mpn, self.pn]: if isinstance(idfield, list): @@ -243,21 +249,24 @@ def __post_init__(self) -> None: else: raise Exception('lists of part data are only supported for bundles') + # by default, show wire numbers for cables, hide for bundles + if not self.show_wirenumbers: + self.show_wirenumbers = self.category != 'bundle' + for i, item in enumerate(self.additional_components): if isinstance(item, dict): self.additional_components[i] = AdditionalComponent(**item) # The *_pin arguments accept a tuple, but it seems not in use with the current code. - def connect(self, from_name: Optional[Designator], from_pin: NoneOrMorePins, via_pin: OneOrMoreWires, + def connect(self, from_name: Optional[Designator], from_pin: NoneOrMorePins, via_wire: OneOrMoreWires, to_name: Optional[Designator], to_pin: NoneOrMorePins) -> None: from_pin = int2tuple(from_pin) - via_pin = int2tuple(via_pin) + via_wire = int2tuple(via_wire) to_pin = int2tuple(to_pin) if len(from_pin) != len(to_pin): raise Exception('from_pin must have the same number of elements as to_pin') for i, _ in enumerate(from_pin): - # self.connections.append((from_name, from_pin[i], via_pin[i], to_name, to_pin[i])) - self.connections.append(Connection(from_name, from_pin[i], via_pin[i], to_name, to_pin[i])) + self.connections.append(Connection(from_name, from_pin[i], via_wire[i], to_name, to_pin[i])) def get_qty_multiplier(self, qty_multiplier: Optional[CableMultiplier]) -> float: if not qty_multiplier: diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index be8cf1a5..42593ab2 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -35,30 +35,46 @@ def add_cable(self, name: str, *args, **kwargs) -> None: def add_bom_item(self, item: dict) -> None: self.additional_bom_items.append(item) - def connect(self, from_name: str, from_pin: (int, str), via_name: str, via_pin: (int, str), to_name: str, to_pin: (int, str)) -> None: - for (name, pin) in zip([from_name, to_name], [from_pin, to_pin]): # check from and to connectors + def connect(self, from_name: str, from_pin: (int, str), via_name: str, via_wire: (int, str), to_name: str, to_pin: (int, str)) -> None: + # check from and to connectors + for (name, pin) in zip([from_name, to_name], [from_pin, to_pin]): if name is not None and name in self.connectors: connector = self.connectors[name] + # check if provided name is ambiguous if pin in connector.pins and pin in connector.pinlabels: - if connector.pins.index(pin) == connector.pinlabels.index(pin): - # TODO: Maybe issue a warning? It's not worthy of an exception if it's unambiguous, but maybe risky? - pass - else: + if connector.pins.index(pin) != connector.pinlabels.index(pin): raise Exception(f'{name}:{pin} is defined both in pinlabels and pins, for different pins.') + # TODO: Maybe issue a warning if present in both lists but referencing the same pin? if pin in connector.pinlabels: if connector.pinlabels.count(pin) > 1: raise Exception(f'{name}:{pin} is defined more than once.') - else: - index = connector.pinlabels.index(pin) - pin = connector.pins[index] # map pin name to pin number - if name == from_name: - from_pin = pin - if name == to_name: - to_pin = pin + index = connector.pinlabels.index(pin) + pin = connector.pins[index] # map pin name to pin number + if name == from_name: + from_pin = pin + if name == to_name: + to_pin = pin if not pin in connector.pins: raise Exception(f'{name}:{pin} not found.') - self.cables[via_name].connect(from_name, from_pin, via_pin, to_name, to_pin) + # check via cable + if via_name in self.cables: + cable = self.cables[via_name] + # check if provided name is ambiguous + if via_wire in cable.colors and via_wire in cable.wirelabels: + if cable.colors.index(via_wire) != cable.wirelabels.index(via_wire): + raise Exception(f'{via_name}:{via_wire} is defined both in colors and wirelabels, for different wires.') + # TODO: Maybe issue a warning if present in both lists but referencing the same wire? + if via_wire in cable.colors: + if cable.colors.count(via_wire) > 1: + raise Exception(f'{via_name}:{via_wire} is used for more than one wire.') + via_wire = cable.colors.index(via_wire) + 1 # list index starts at 0, wire IDs start at 1 + elif via_wire in cable.wirelabels: + if cable.wirelabels.count(via_wire) > 1: + raise Exception(f'{via_name}:{via_wire} is used for more than one wire.') + via_wire = cable.wirelabels.index(via_wire) + 1 # list index starts at 0, wire IDs start at 1 + + self.cables[via_name].connect(from_name, from_pin, via_wire, to_name, to_pin) if from_name in self.connectors: self.connectors[from_name].activate_pin(from_pin) if to_name in self.connectors: @@ -197,10 +213,22 @@ def create_graph(self) -> Graph: wirehtml.append('') # conductor table wirehtml.append(' ') - for i, connection_color in enumerate(cable.colors, 1): + for i, (connection_color, wirelabel) in enumerate(zip_longest(cable.colors, cable.wirelabels), 1): wirehtml.append(' ') wirehtml.append(f' ') - wirehtml.append(f' ') + wirehtml.append(f' ') wirehtml.append(f' ') wirehtml.append(' ') From 357c52667576a5bf306cfb8ddd73eab4c615c50f Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Wed, 11 Nov 2020 16:39:56 +0100 Subject: [PATCH 2/3] Update example 08 to reference wires using colors --- examples/ex08.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ex08.yml b/examples/ex08.yml index eea3976a..a17583f4 100644 --- a/examples/ex08.yml +++ b/examples/ex08.yml @@ -28,7 +28,7 @@ cables: connections: - - Key: [S,R,T] - - W1: [1,2,3] + - W1: [WH,BN,GN] - - Key: S - W1: s From 3ff8e6e016f131523b8790150779b84a81258f94 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Wed, 11 Nov 2020 20:59:27 +0100 Subject: [PATCH 3/3] Show pin labels of adjacent connectors in cable node (#70) --- src/wireviz/Harness.py | 48 +++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index 42593ab2..8973788d 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -282,26 +282,44 @@ def create_graph(self) -> Graph: html = [row.replace('', '\n'.join(wirehtml)) for row in html] # connections - for connection_color in cable.connections: - if isinstance(connection_color.via_port, int): # check if it's an actual wire and not a shield - dot.attr('edge', color=':'.join(['#000000'] + wv_colors.get_color_hex(cable.colors[connection_color.via_port - 1], pad=pad) + ['#000000'])) + for connection in cable.connections: + if isinstance(connection.via_port, int): # check if it's an actual wire and not a shield + dot.attr('edge', color=':'.join(['#000000'] + wv_colors.get_color_hex(cable.colors[connection.via_port - 1], pad=pad) + ['#000000'])) else: # it's a shield connection # shield is shown with specified color and black borders, or as a thin black wire otherwise dot.attr('edge', color=':'.join(['#000000', shield_color_hex, '#000000']) if isinstance(cable.shield, str) else '#000000') - if connection_color.from_port is not None: # connect to left - from_port = f':p{connection_color.from_port}r' if self.connectors[connection_color.from_name].style != 'simple' else '' - code_left_1 = f'{connection_color.from_name}{from_port}:e' - code_left_2 = f'{cable.name}:w{connection_color.via_port}:w' + if connection.from_port is not None: # connect to left + from_connector = self.connectors[connection.from_name] + from_port = f':p{connection.from_port}r' if from_connector.style != 'simple' else '' + code_left_1 = f'{connection.from_name}{from_port}:e' + code_left_2 = f'{cable.name}:w{connection.via_port}:w' dot.edge(code_left_1, code_left_2) - from_string = f'{connection_color.from_name}:{connection_color.from_port}' if self.connectors[connection_color.from_name].show_name else '' - html = [row.replace(f'', from_string) for row in html] - if connection_color.to_port is not None: # connect to right - code_right_1 = f'{cable.name}:w{connection_color.via_port}:e' - to_port = f':p{connection_color.to_port}l' if self.connectors[connection_color.to_name].style != 'simple' else '' - code_right_2 = f'{connection_color.to_name}{to_port}:w' + if from_connector.show_name: + from_info = [str(connection.from_name), str(connection.from_port)] + if from_connector.pinlabels: + pinlabel = from_connector.pinlabels[from_connector.pins.index(connection.from_port)] + if pinlabel != '': + from_info.append(pinlabel) + from_string = ':'.join(from_info) + else: + from_string = '' + html = [row.replace(f'', from_string) for row in html] + if connection.to_port is not None: # connect to right + to_connector = self.connectors[connection.to_name] + code_right_1 = f'{cable.name}:w{connection.via_port}:e' + to_port = f':p{connection.to_port}l' if self.connectors[connection.to_name].style != 'simple' else '' + code_right_2 = f'{connection.to_name}{to_port}:w' dot.edge(code_right_1, code_right_2) - to_string = f'{connection_color.to_name}:{connection_color.to_port}' if self.connectors[connection_color.to_name].show_name else '' - html = [row.replace(f'', to_string) for row in html] + if to_connector.show_name: + to_info = [str(connection.to_name), str(connection.to_port)] + if to_connector.pinlabels: + pinlabel = to_connector.pinlabels[to_connector.pins.index(connection.to_port)] + if pinlabel != '': + to_info.append(pinlabel) + to_string = ':'.join(to_info) + else: + to_string = '' + html = [row.replace(f'', to_string) for row in html] html = '\n'.join(html) dot.node(cable.name, label=f'<\n{html}\n>', shape='box',
 
{wv_colors.translate_color(connection_color, self.color_mode)}') + + wireinfo = [] + if cable.show_wirenumbers: + wireinfo.append(str(i)) + colorstr = wv_colors.translate_color(connection_color, self.color_mode) + if colorstr: + wireinfo.append(colorstr) + if cable.wirelabels: + wireinfo.append(wirelabel if wirelabel is not None else '') + wirehtml.append(f' {":".join(wireinfo)}') + + wirehtml.append(f'