Skip to content

Commit 6b1ba5a

Browse files
committed
Initial commit
1 parent ec05d69 commit 6b1ba5a

File tree

5 files changed

+503
-66
lines changed

5 files changed

+503
-66
lines changed

src/ansys/aedt/core/emit.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from ansys.aedt.core.emit_core.couplings import CouplingsEmit
3030
from ansys.aedt.core.emit_core.emit_constants import EMIT_VALID_UNITS
3131
from ansys.aedt.core.emit_core.emit_constants import emit_unit_type_string_to_enum
32+
from ansys.aedt.core.emit_core.emit_schematic import EmitSchematic
3233
from ansys.aedt.core.emit_core.results.results import Results
3334
from ansys.aedt.core.generic.general_methods import pyaedt_function_handler
3435
from ansys.aedt.core.modeler.schematic import ModelerEmit
@@ -172,6 +173,7 @@ def __init__(
172173
)
173174
self._modeler = ModelerEmit(self)
174175
self._couplings = CouplingsEmit(self)
176+
self._schematic = EmitSchematic(self)
175177
if self._aedt_version > "2023.1":
176178
# the next 2 lines of code are needed to point
177179
# the EMIT object to the correct EmiApiPython
@@ -210,6 +212,17 @@ def couplings(self):
210212
"""
211213
return self._couplings
212214

215+
@property
216+
def schematic(self):
217+
"""EMIT Schematic.
218+
219+
Returns
220+
-------
221+
:class:`ansys.aedt.core.emit_core.emit_schematic.EmitSchematic`
222+
EMIT schematic.
223+
"""
224+
return self._schematic
225+
213226
@pyaedt_function_handler()
214227
def version(self, detailed=False):
215228
"""
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates.
4+
# SPDX-License-Identifier: MIT
5+
#
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in all
15+
# copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
# SOFTWARE.
24+
25+
26+
from ansys.aedt.core.generic.general_methods import pyaedt_function_handler
27+
28+
29+
class EmitSchematic:
30+
"""Represents the EMIT schematic and provides methods to interact with it."""
31+
32+
def __init__(self, emit_instance):
33+
"""Initialize the EmitSchematic class.
34+
35+
Parameters
36+
----------
37+
emit_instance : Emit
38+
Instance of the Emit class.
39+
"""
40+
self.emit_instance = emit_instance
41+
42+
@property
43+
def _emit_com_module(self):
44+
"""Retrieve the EmitCom module from the Emit instance.
45+
46+
Returns
47+
-------
48+
object
49+
The EmitCom module.
50+
51+
Raises
52+
------
53+
RuntimeError
54+
If the EmitCom module cannot be retrieved.
55+
"""
56+
if not hasattr(self.emit_instance, "_odesign"):
57+
raise RuntimeError("Emit instance does not have a valid '_odesign' attribute.")
58+
try:
59+
return self.emit_instance._odesign.GetModule("EmitCom")
60+
except Exception as e:
61+
raise RuntimeError(f"Failed to retrieve EmitCom module: {e}")
62+
63+
@pyaedt_function_handler
64+
def create_component(self, component_type: str, name: str = None, library: str = None) -> int:
65+
"""Create a component.
66+
67+
Parameters
68+
----------
69+
component_type : str
70+
Type of the component to create.
71+
name : str, optional
72+
Name of the component to create. AEDT defaults used if not provided.
73+
library : str, optional
74+
Name of the component library. Defaults to an empty string if not provided.
75+
76+
Returns
77+
-------
78+
int
79+
The ID of the created component.
80+
81+
Raises
82+
------
83+
ValueError
84+
If the component type is empty or no matching component is found.
85+
RuntimeError
86+
If the component creation fails.
87+
"""
88+
if not component_type:
89+
raise ValueError("The 'component_type' argument is required.")
90+
91+
name = name or ""
92+
library = library or ""
93+
94+
try:
95+
# Retrieve matching components from the catalog
96+
matching_components = self.emit_instance.modeler.components.components_catalog[component_type]
97+
98+
if not matching_components:
99+
self.emit_instance.logger.error(f"No component found for type '{component_type}'.")
100+
raise ValueError(f"No component found for type '{component_type}'.")
101+
102+
if len(matching_components) == 1:
103+
# Use the single matching component
104+
component = matching_components[0]
105+
self.emit_instance.logger.info(
106+
f"Using component '{component.name}' from library '{component.component_library}"
107+
f"' for type '{component_type}'."
108+
)
109+
else:
110+
# Attempt to find an exact match
111+
component = next((comp for comp in matching_components if comp.name == component_type), None)
112+
if not component:
113+
self.emit_instance.logger.error(
114+
f"Multiple components found for type '{component_type}', but no exact match."
115+
" Please specify a unique component."
116+
)
117+
raise ValueError(f"Multiple components found for type '{component_type}', but no exact match.")
118+
self.emit_instance.logger.info(
119+
f"Using exact match component '{component.name}' from library '{component.component_library}"
120+
"' for type '{component_type}'."
121+
)
122+
123+
# Create the component using the EmitCom module
124+
new_component_id = self._emit_com_module.CreateEmitComponent(
125+
name, component.name, component.component_library
126+
)
127+
return new_component_id
128+
except Exception as e:
129+
self.emit_instance.logger.error(f"Failed to create component '{name}' of type '{component_type}': {e}")
130+
raise RuntimeError(f"Failed to create component of type '{component_type}': {e}")
131+
132+
@pyaedt_function_handler
133+
def create_radio_antenna(
134+
self, radio_type: str, radio_name: str = None, antenna_name: str = None, library: str = None
135+
) -> tuple[int, int]:
136+
"""Create a new radio and antenna and connect them.
137+
138+
Parameters
139+
----------
140+
radio_type : str
141+
Type of radio to create. For example, "Bluetooth". Must match
142+
a radio name in the specified library.
143+
radio_name : str, optional
144+
Name to assign to the new radio. If ``None``, then an instance
145+
name is assigned automatically. The default is ``None``.
146+
antenna_name : str, optional
147+
Name to assign to the new antenna. If ``None``, then an instance
148+
name is assigned automatically. The default is ``None``.
149+
library : str, optional
150+
Name of the component library. If ``None``, then the default
151+
library is used. The default is ``None``.
152+
153+
Returns
154+
-------
155+
tuple
156+
A tuple containing the IDs of the created radio and antenna.
157+
158+
Raises
159+
------
160+
RuntimeError
161+
If the radio or antenna creation fails.
162+
"""
163+
radio_name = radio_name or ""
164+
antenna_name = antenna_name or ""
165+
library = library or ""
166+
167+
try:
168+
new_radio_id = self.create_component(radio_type, radio_name, library)
169+
new_antenna_id = self.create_component("Antenna", antenna_name, "Antennas")
170+
if new_radio_id and new_antenna_id:
171+
self.connect_components(new_antenna_id, new_radio_id) # Connect antenna to radio
172+
return new_radio_id, new_antenna_id
173+
except Exception as e:
174+
self.emit_instance.logger.error(f"Failed to create radio of type '{radio_type}' or antenna: {e}")
175+
raise RuntimeError(f"Failed to create radio of type '{radio_type}' or antenna: {e}")
176+
177+
@pyaedt_function_handler
178+
def connect_components(self, component_id_1: int, component_id_2: int):
179+
"""Connect two components in the schematic.
180+
181+
Parameters
182+
----------
183+
component_id_1 : str
184+
ID of the first component.
185+
component_id_2 : str
186+
ID of the second component.
187+
188+
Raises
189+
------
190+
RuntimeError
191+
If the connection fails.
192+
"""
193+
try:
194+
component_name_1 = self.get_component_properties(component_id_1, "Name")
195+
component_name_2 = self.get_component_properties(component_id_2, "Name")
196+
self.emit_instance._oeditor.PlaceComponent(component_name_1, component_name_2)
197+
self.emit_instance.logger.info(
198+
f"Successfully connected components '{component_name_1}' and '{component_name_2}'."
199+
)
200+
except Exception as e:
201+
self.emit_instance.logger.error(
202+
f"Failed to connect components '{component_id_1}' and '{component_id_2}': {e}"
203+
)
204+
raise RuntimeError(f"Failed to connect components '{component_id_1}' and '{component_id_2}': {e}")
205+
206+
@pyaedt_function_handler
207+
def get_component_properties(self, component_id: int, property_key: str = None) -> dict:
208+
"""Get properties of a component.
209+
210+
Parameters
211+
----------
212+
component_id : int
213+
ID of the component.
214+
property_key : str, optional
215+
Specific property key to retrieve. If ``None``, all properties are returned.
216+
217+
Returns
218+
-------
219+
dict or str
220+
Dictionary containing all properties of the component if `property_key` is ``None``.
221+
Otherwise, the value of the specified property key.
222+
223+
Raises
224+
------
225+
KeyError
226+
If the specified property key is not found.
227+
"""
228+
try:
229+
props = self._emit_com_module.GetEmitNodeProperties(0, component_id, True)
230+
props_dict = {prop.split("=", 1)[0]: prop.split("=", 1)[1] for prop in props}
231+
if property_key is None:
232+
return props_dict
233+
if property_key in props_dict:
234+
return props_dict[property_key]
235+
raise KeyError(f"Property key '{property_key}' not found.")
236+
except Exception as e:
237+
self.emit_instance.logger.error(f"Failed to retrieve properties for component '{component_id}': {e}")
238+
raise RuntimeError(f"Failed to retrieve properties for component '{component_id}': {e}")

0 commit comments

Comments
 (0)