From fda0e7a1a271a0f8729cb7d0be09951b028189b9 Mon Sep 17 00:00:00 2001 From: hui-zhou-a Date: Thu, 18 Dec 2025 14:27:00 +0100 Subject: [PATCH 1/3] FEAT: N port component multi --- .../aedt/core/arguments/component_manager.py | 35 +++++++++++++ src/ansys/aedt/core/arguments/editor.py | 51 +++++++++++++++++++ .../modeler/circuits/primitives_circuit.py | 21 ++++++++ 3 files changed, 107 insertions(+) create mode 100644 src/ansys/aedt/core/arguments/component_manager.py create mode 100644 src/ansys/aedt/core/arguments/editor.py diff --git a/src/ansys/aedt/core/arguments/component_manager.py b/src/ansys/aedt/core/arguments/component_manager.py new file mode 100644 index 00000000000..c088ee8d2dc --- /dev/null +++ b/src/ansys/aedt/core/arguments/component_manager.py @@ -0,0 +1,35 @@ +from pydantic import BaseModel, Field + + +class Files(BaseModel): + files: List[str] = Field(..., min_length=1) + + @classmethod + def create(cls, **kwargs): + return cls.model_validate(kwargs) + + def to_aedt_args(self): + args = ["NAME:Files"] + if self.files is not None: args.extend(["Files:=", self.files]) + return args + + +class Options(BaseModel): + num_ports_or_lines: int = Field(..., ge=1) + array_name: str + array_id_name: str + comp_name: str + + @classmethod + def create(cls, **kwargs): + return cls.model_validate(kwargs) + + def to_aedt_args(self): + args = ["NAME:Options"] + if self.num_ports_or_lines is not None: args.extend(["NumPortsOrLines:=", self.num_ports_or_lines]) + args.extend(["CreateArray:=", True]) + if self.array_name is not None: args.extend(["ArrayName:=", self.array_name]) + if self.array_id_name is not None: args.extend(["ArrayIdName:=", self.array_id_name]) + args.extend(["CompType:=", 2]) + if self.comp_name is not None: args.extend(["CompName:=", self.comp_name]) + return args \ No newline at end of file diff --git a/src/ansys/aedt/core/arguments/editor.py b/src/ansys/aedt/core/arguments/editor.py new file mode 100644 index 00000000000..3a6a7fedf7b --- /dev/null +++ b/src/ansys/aedt/core/arguments/editor.py @@ -0,0 +1,51 @@ +from pydantic import BaseModel +from ansys.aedt.core.generic.numbers_utils import Quantity + + +def convert_to_meter(value): + """Convert numbers automatically to mils. + + It is rounded to the nearest 100 mil which is minimum schematic snap unit. + """ + value = Quantity(value, "mil") + + value = value.to("mil") + value.value = round(value.value, -2) + value = value.to("meter") + return value.value + + +class ComponentProps(BaseModel): + name: str + + @classmethod + def create(cls, **kwargs): + return cls.model_validate(kwargs) + + def to_aedt_args(self): + args = ["NAME:ComponentProps"] + if self.name is not None: args.extend(["Name:=", self.name]) + return args + + +class Attributes(BaseModel): + page: int = 1 + x: float + y: float + angle: float = 0.0 + flip: bool = False + + @classmethod + def create(cls, **kwargs): + kwargs["x"] = convert_to_meter(kwargs.pop("x")) + kwargs["y"] = convert_to_meter(kwargs.pop("y")) + return cls.model_validate(kwargs) + + def to_aedt_args(self): + args = ["NAME:Attributes"] + if self.page is not None: args.extend(["Page:=", self.page]) + if self.x is not None: args.extend(["X:=", self.x]) + if self.y is not None: args.extend(["Y:=", self.y]) + if self.angle is not None: args.extend(["Angle:=", self.angle]) + if self.flip is not None: args.extend(["Flip:=", self.flip]) + return args \ No newline at end of file diff --git a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py index 28d4228f037..6fb9aec60e5 100644 --- a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py @@ -1642,6 +1642,27 @@ def create_wire(self, points, name="", page=1): except Exception: return False + @pyaedt_function_handler() + def create_nport_multi(self, + component_name, num_ports_or_lines, array_name, array_id_name, files, + x, y, page=1, angle=0.0, flip=False): + from ansys.aedt.core.arguments.component_manager import Files, Options + from ansys.aedt.core.arguments.editor import ComponentProps, Attributes + + files_args = Files.create(files=files).to_aedt_args() + options_args = Options.create(num_ports_or_lines=num_ports_or_lines, array_name=array_name, + array_id_name=array_id_name, + comp_name=component_name).to_aedt_args() + self.ocomponent_manager.ImportSandWComponent(files_args, options_args) + + props_args = ComponentProps.create(name=component_name).to_aedt_args() + attributes_args = Attributes.create(x=x, y=y, page=page, flip=flip, angle=angle).to_aedt_args() + + comp_name = self.oeditor.CreateComponent(props_args, attributes_args) + comp_id = int(comp_name.split(";")[-1]) + self.add_id_to_component(comp_id, comp_name) + return self.components[comp_id] + class ComponentInfo(PyAedtBase): """Manages Circuit Catalog info.""" From ab70b329e12cb492dac5954a3f0a1a8691a481c1 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Thu, 18 Dec 2025 13:29:44 +0000 Subject: [PATCH 2/3] chore: adding changelog file 7029.added.md [dependabot-skip] --- doc/changelog.d/7029.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/7029.added.md diff --git a/doc/changelog.d/7029.added.md b/doc/changelog.d/7029.added.md new file mode 100644 index 00000000000..1147b7f206e --- /dev/null +++ b/doc/changelog.d/7029.added.md @@ -0,0 +1 @@ +N port component multi From 8acffd6cf2ffa64acc67cc63243f528b47eb1bdc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 13:30:39 +0000 Subject: [PATCH 3/3] CHORE: Auto fixes from pre-commit hooks --- .../aedt/core/arguments/component_manager.py | 44 +++++++++++++++--- src/ansys/aedt/core/arguments/editor.py | 45 ++++++++++++++++--- .../modeler/circuits/primitives_circuit.py | 21 +++++---- 3 files changed, 88 insertions(+), 22 deletions(-) diff --git a/src/ansys/aedt/core/arguments/component_manager.py b/src/ansys/aedt/core/arguments/component_manager.py index c088ee8d2dc..bfcdb66d143 100644 --- a/src/ansys/aedt/core/arguments/component_manager.py +++ b/src/ansys/aedt/core/arguments/component_manager.py @@ -1,4 +1,29 @@ -from pydantic import BaseModel, Field +# -*- coding: utf-8 -*- +# +# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from pydantic import BaseModel +from pydantic import Field class Files(BaseModel): @@ -10,7 +35,8 @@ def create(cls, **kwargs): def to_aedt_args(self): args = ["NAME:Files"] - if self.files is not None: args.extend(["Files:=", self.files]) + if self.files is not None: + args.extend(["Files:=", self.files]) return args @@ -26,10 +52,14 @@ def create(cls, **kwargs): def to_aedt_args(self): args = ["NAME:Options"] - if self.num_ports_or_lines is not None: args.extend(["NumPortsOrLines:=", self.num_ports_or_lines]) + if self.num_ports_or_lines is not None: + args.extend(["NumPortsOrLines:=", self.num_ports_or_lines]) args.extend(["CreateArray:=", True]) - if self.array_name is not None: args.extend(["ArrayName:=", self.array_name]) - if self.array_id_name is not None: args.extend(["ArrayIdName:=", self.array_id_name]) + if self.array_name is not None: + args.extend(["ArrayName:=", self.array_name]) + if self.array_id_name is not None: + args.extend(["ArrayIdName:=", self.array_id_name]) args.extend(["CompType:=", 2]) - if self.comp_name is not None: args.extend(["CompName:=", self.comp_name]) - return args \ No newline at end of file + if self.comp_name is not None: + args.extend(["CompName:=", self.comp_name]) + return args diff --git a/src/ansys/aedt/core/arguments/editor.py b/src/ansys/aedt/core/arguments/editor.py index 3a6a7fedf7b..c911e7c90f2 100644 --- a/src/ansys/aedt/core/arguments/editor.py +++ b/src/ansys/aedt/core/arguments/editor.py @@ -1,4 +1,29 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + from pydantic import BaseModel + from ansys.aedt.core.generic.numbers_utils import Quantity @@ -24,7 +49,8 @@ def create(cls, **kwargs): def to_aedt_args(self): args = ["NAME:ComponentProps"] - if self.name is not None: args.extend(["Name:=", self.name]) + if self.name is not None: + args.extend(["Name:=", self.name]) return args @@ -43,9 +69,14 @@ def create(cls, **kwargs): def to_aedt_args(self): args = ["NAME:Attributes"] - if self.page is not None: args.extend(["Page:=", self.page]) - if self.x is not None: args.extend(["X:=", self.x]) - if self.y is not None: args.extend(["Y:=", self.y]) - if self.angle is not None: args.extend(["Angle:=", self.angle]) - if self.flip is not None: args.extend(["Flip:=", self.flip]) - return args \ No newline at end of file + if self.page is not None: + args.extend(["Page:=", self.page]) + if self.x is not None: + args.extend(["X:=", self.x]) + if self.y is not None: + args.extend(["Y:=", self.y]) + if self.angle is not None: + args.extend(["Angle:=", self.angle]) + if self.flip is not None: + args.extend(["Flip:=", self.flip]) + return args diff --git a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py index 6fb9aec60e5..4c75e890817 100644 --- a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py @@ -1643,16 +1643,21 @@ def create_wire(self, points, name="", page=1): return False @pyaedt_function_handler() - def create_nport_multi(self, - component_name, num_ports_or_lines, array_name, array_id_name, files, - x, y, page=1, angle=0.0, flip=False): - from ansys.aedt.core.arguments.component_manager import Files, Options - from ansys.aedt.core.arguments.editor import ComponentProps, Attributes + def create_nport_multi( + self, component_name, num_ports_or_lines, array_name, array_id_name, files, x, y, page=1, angle=0.0, flip=False + ): + from ansys.aedt.core.arguments.component_manager import Files + from ansys.aedt.core.arguments.component_manager import Options + from ansys.aedt.core.arguments.editor import Attributes + from ansys.aedt.core.arguments.editor import ComponentProps files_args = Files.create(files=files).to_aedt_args() - options_args = Options.create(num_ports_or_lines=num_ports_or_lines, array_name=array_name, - array_id_name=array_id_name, - comp_name=component_name).to_aedt_args() + options_args = Options.create( + num_ports_or_lines=num_ports_or_lines, + array_name=array_name, + array_id_name=array_id_name, + comp_name=component_name, + ).to_aedt_args() self.ocomponent_manager.ImportSandWComponent(files_args, options_args) props_args = ComponentProps.create(name=component_name).to_aedt_args()