From 256a7e90308717b62ff5bd6b5dd7e455ff2b205d Mon Sep 17 00:00:00 2001 From: Samuel Lopez <85613111+Samuelopez-ansys@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:58:31 +0200 Subject: [PATCH] FEAT: Change symbol pin (#4956) Co-authored-by: HaiwenZhang Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- _unittest/test_21_Circuit.py | 13 ++ pyaedt/modeler/circuits/object3dcircuit.py | 144 +++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/_unittest/test_21_Circuit.py b/_unittest/test_21_Circuit.py index b7a7adf1f31..87891b71668 100644 --- a/_unittest/test_21_Circuit.py +++ b/_unittest/test_21_Circuit.py @@ -963,3 +963,16 @@ def test_50_enforce_touchstone_passive(self): assert not nexxim_customization["Reciprocal"] assert "" == nexxim_customization["ModelOption"] assert 2 == nexxim_customization["DataType"] + + def test_51_change_symbol_pin_location(self): + self.aedtapp.insert_design("Pin_location") + self.aedtapp.modeler.schematic_units = "mil" + ts_component = self.aedtapp.modeler.schematic.create_touchstone_component(self.touchstone_file) + pins = ts_component.pins + pin_locations = { + "left": [pins[0].name, pins[1].name, pins[2].name, pins[3].name, pins[4].name], + "right": [pins[5].name], + } + assert ts_component.change_symbol_pin_locations(pin_locations) + pin_locations = {"left": [pins[0].name, pins[1].name, pins[2].name], "right": [pins[5].name]} + assert not ts_component.change_symbol_pin_locations(pin_locations) diff --git a/pyaedt/modeler/circuits/object3dcircuit.py b/pyaedt/modeler/circuits/object3dcircuit.py index 911c78c8ab8..4e5516321f5 100644 --- a/pyaedt/modeler/circuits/object3dcircuit.py +++ b/pyaedt/modeler/circuits/object3dcircuit.py @@ -955,6 +955,150 @@ def enforce_touchstone_model_passive(self): self.model_data.props = props return self.model_data.update() + @pyaedt_function_handler() + def change_symbol_pin_locations(self, pin_locations): + """Change the locations of symbol pins. + + Parameters + ---------- + pin_locations : dict + A dictionary with two keys: "left" and "right", + each containing a list of pin names to be placed on the left and + right sides of the symbol, respectively. + + Returns + ------- + bool + ``True`` if pin locations were successfully changed, ``False`` otherwise. + + References + ---------- + >>> oSymbolManager.EditSymbolAndUpdateComps + + Examples + -------- + >>> from pyaedt import Circuit + >>> cir = Circuit(my_project) + >>> cir.modeler.schematic_units = "mil" + >>> ts_path = os.path.join(current_path, "connector_model.s4p") + >>> ts_component = cir.modeler.schematic.create_touchstone_component(ts_path, show_bitmap=False) + >>> pin_locations = {"left": + ... ['DDR_CH3_DM_DBI0_BGA_BE47', 'DDR_CH3_DM_DBI1_BGA_BJ50','DDR_CH3_DM_DBI1_DIE_12471'], + ... "right": ['DDR_CH3_DM_DBI0_DIE_7976']} + >>> ts_component.change_symbol_pin_locations(pin_locations) + """ + base_spacing = 0.00254 + symbol_pin_name_list = self.model_data.props.get("PortNames", []) + pin_name_str_max_length = max(len(s) for s in symbol_pin_name_list) + + left_pins = pin_locations["left"] + right_pins = pin_locations["right"] + left_pins_length = len(left_pins) + right_pins_length = len(right_pins) + max_pins_length = max(left_pins_length, right_pins_length) + + # Ensure the total number of pins matches the symbol pin names + if (right_pins_length + left_pins_length) != len(symbol_pin_name_list): + self._circuit_components._app.logger.error( + "The number of pins in the input pin_locations does not match the number of pins in the Symbol." + ) + return False + + x_factor = int(pin_name_str_max_length / 3) + + x1 = 0 + x2 = base_spacing * x_factor + y1 = 0 + y2 = base_spacing * (max_pins_length + 1) + + pin_left_x = -base_spacing + pin_left_angle = 0 + pin_right_x = base_spacing * (x_factor + 1) + pin_right_angle = math.pi + + def create_pin_def(pin_name, x, y, angle): + pin_def = [pin_name, x, y, angle, "N", 0, base_spacing * 2, False, 0, True, "", True, False, pin_name, True] + pin_name_rect = [ + 1, + 0, + 0, + 0, + x, + y + 0.00176388888889594 / 2, + 0.00111403508 * len(pin_name), + 0.00176388888889594, + 0, + 0, + 0, + ] + pin_text = [ + x, + y + 0.00176388888889594 / 2, + 0, + 4, + 5, + False, + "Arial", + 0, + pin_name, + False, + False, + "ExtentRect:=", + pin_name_rect, + ] + pin_name_def = [2, 5, 1, "Text:=", pin_text] + props_display_map = ["NAME:PropDisplayMap", "PinName:=", pin_name_def] + return ["NAME:PinDef", "Pin:=", pin_def, props_display_map] + + args = [ + "NAME:{}".format(self.model_name), + "ModTime:=", + int(time.time()), + "Library:=", + "", + "ModSinceLib:=", + False, + "LibLocation:=", + "Project", + "HighestLevel:=", + 1, + "Normalize:=", + False, + "InitialLevels:=", + [0, 1], + ] + terminals_arg = ["NAME:Terminals"] + + yp = base_spacing * max_pins_length + for pin_name in left_pins: + args.append(create_pin_def(pin_name, pin_left_x, yp, pin_left_angle)) + yp -= base_spacing + + yp = base_spacing * max_pins_length + for pin_name in right_pins: + args.append(create_pin_def(pin_name, pin_right_x, yp, pin_right_angle)) + yp -= base_spacing + + args.append( + [ + "NAME:Graphics", + "Rect:=", + [0, 0, 0, 0, (x1 + x2) / 2, (y1 + y2) / 2, x2 - x1, y2 - y1, 0, 0, 0], + "Rect:=", + [0, 1, 0, 0, (x1 + x2) / 2, (y1 + y2) / 2, 0.000423333333333333, 0.000423333333333333, 0, 0, 0], + ] + ) + + for pin_name in self.model_data.props.get("PortNames", []): + terminals_arg.append("TermAttributes:=") + terminals_arg.append([pin_name, pin_name, 0 if pin_name in left_pins else 1, 0, -1, ""]) + + edit_context_arg = ["NAME:EditContext", "RefPinOption:=", 2, "CompName:=", self.model_name, terminals_arg] + + self._circuit_components.o_symbol_manager.EditSymbolAndUpdateComps(self.model_name, args, [], edit_context_arg) + self._circuit_components.oeditor.MovePins(self.composed_name, -0, -0, 0, 0, ["NAME:PinMoveData"]) + return True + class Wire(object): """Creates and manipulates a wire."""