def rename_ports_by_orientation( component: Device, layers_excluded: Tuple[Tuple[int, int], ...] = None, select_ports: Optional[Callable] = None, function=_rename_ports_facing_side, prefix: str = "o", ) -> Device: """Returns Component with port names based on port orientation (E, N, W, S) Args: component: layers_excluded: select_ports: function: to rename ports prefix: to add on each port name .. code:: N0 N1 |___|_ W1 -| |- E1 | | W0 -|______|- E0 | | S0 S1 """ layers_excluded = layers_excluded or [] direction_ports = {x: [] for x in ["E", "N", "W", "S"]} ports = component.ports ports = select_ports(ports) if select_ports else ports ports_on_layer = [p for p in ports.values() if p.layer not in layers_excluded] for p in ports_on_layer: # Make sure we can backtrack the parent component from the port p.parent = component angle = p.orientation % 360 if angle <= 45 or angle >= 315: direction_ports["E"].append(p) elif angle <= 135 and angle >= 45: direction_ports["N"].append(p) elif angle <= 225 and angle >= 135: direction_ports["W"].append(p) else: direction_ports["S"].append(p) function(direction_ports, prefix=prefix) component.ports = {p.name: p for p in component.ports.values()} return component
def auto_rename_ports_layer_orientation( component: Device, function=_rename_ports_facing_side, prefix: str = "", ) -> None: """Renames port names with layer_orientation (1_0_W0) port orientation (E, N, W, S) numbering is clockwise .. code:: N0 N1 |___|_ W1 -| |- E1 | | W0 -|______|- E0 | | S0 S1 """ new_ports = {} ports = component.ports direction_ports = {x: [] for x in ["E", "N", "W", "S"]} layers = {port.layer for port in ports.values()} for layer in layers: ports_on_layer = [p for p in ports.values() if p.layer == layer] for p in ports_on_layer: p.name_original = p.name angle = p.orientation % 360 if angle <= 45 or angle >= 315: direction_ports["E"].append(p) elif angle <= 135 and angle >= 45: direction_ports["N"].append(p) elif angle <= 225 and angle >= 135: direction_ports["W"].append(p) else: direction_ports["S"].append(p) function(direction_ports, prefix=f"{layer[0]}_{layer[1]}_") new_ports.update({p.name: p for p in ports_on_layer}) component.ports = new_ports
def rename_ports_by_orientation( component: Device, layers_excluded: List[Tuple[int, int]] = None) -> Device: """Returns Component with port names based on port orientation (E, N, W, S) .. code:: N0 N1 |___|_ W1 -| |- E1 | | W0 -|______|- E0 | | S0 S1 """ layers_excluded = layers_excluded or [] direction_ports = {x: [] for x in ["E", "N", "W", "S"]} ports_on_process = [ p for p in component.ports.values() if p.layer not in layers_excluded ] for p in ports_on_process: # Make sure we can backtrack the parent component from the port p.parent = component angle = p.orientation % 360 if angle <= 45 or angle >= 315: direction_ports["E"].append(p) elif angle <= 135 and angle >= 45: direction_ports["N"].append(p) elif angle <= 225 and angle >= 135: direction_ports["W"].append(p) else: direction_ports["S"].append(p) _rename_ports_facing_side(direction_ports) component.ports = {p.name: p for p in component.ports.values()} return component
def auto_rename_ports(component: Device) -> Device: """Returns Component with port names based on port orientation (E, N, W, S) .. code:: N0 N1 |___|_ W1 -| |- E1 | | W0 -|______|- E0 | | S0 S1 """ def _counter_clockwise(_direction_ports, prefix=""): east_ports = _direction_ports["E"] east_ports.sort(key=lambda p: p.y) # sort south to north north_ports = _direction_ports["N"] north_ports.sort(key=lambda p: -p.x) # sort east to west west_ports = _direction_ports["W"] west_ports.sort(key=lambda p: -p.y) # sort north to south south_ports = _direction_ports["S"] south_ports.sort(key=lambda p: p.x) # sort west to east ports = east_ports + north_ports + west_ports + south_ports for i, p in enumerate(ports): p.name = "{}{}".format(prefix, i) type_to_ports_naming_functions = { "optical": _rename_ports_facing_side, "heater": lambda _d: _counter_clockwise(_d, "H_"), "dc": lambda _d: _counter_clockwise(_d, "E_"), "superconducting": lambda _d: _counter_clockwise(_d, "SC_"), } type_to_ports = {} for p in component.ports.values(): if p.port_type not in type_to_ports: type_to_ports[p.port_type] = [] type_to_ports[p.port_type] += [p] for port_type, port_group in type_to_ports.items(): if port_type in type_to_ports_naming_functions: _func_name_ports = type_to_ports_naming_functions[port_type] else: raise ValueError( f"Port type <{port_type}> in component {component.name}, port {p} is not valid ", f"valid types = {list(type_to_ports_naming_functions.keys())}", ) direction_ports = {x: [] for x in ["E", "N", "W", "S"]} for p in port_group: p.parent = component angle = p.orientation % 360 if angle <= 45 or angle >= 315: direction_ports["E"].append(p) elif angle <= 135 and angle >= 45: direction_ports["N"].append(p) elif angle <= 225 and angle >= 135: direction_ports["W"].append(p) else: direction_ports["S"].append(p) _func_name_ports(direction_ports) # Set the port dictionnary with the new names component.ports = {p.name: p for p in component.ports.values()} return component