diff --git a/doc/changelog.d/6835.fixed.md b/doc/changelog.d/6835.fixed.md new file mode 100644 index 00000000000..8a72e75c1b0 --- /dev/null +++ b/doc/changelog.d/6835.fixed.md @@ -0,0 +1 @@ +Emit properties cleanup diff --git a/ignore_words.txt b/ignore_words.txt index 77f828a6086..135c28018fe 100644 --- a/ignore_words.txt +++ b/ignore_words.txt @@ -32,4 +32,7 @@ aline COM gRPC Toolkits -Extensions \ No newline at end of file +Extensions +Synopsys +intermodulation +intermod \ No newline at end of file diff --git a/src/ansys/aedt/core/emit_core/emit_schematic.py b/src/ansys/aedt/core/emit_core/emit_schematic.py index bb4b4b3a057..b2b72a22527 100644 --- a/src/ansys/aedt/core/emit_core/emit_schematic.py +++ b/src/ansys/aedt/core/emit_core/emit_schematic.py @@ -182,7 +182,8 @@ def create_radio_antenna( new_antenna = self.create_component("Antenna", antenna_name, "Antennas") if new_radio and new_antenna: self.connect_components(new_antenna.name, new_radio.name) # Connect antenna to radio - return new_radio, new_antenna + return new_radio, new_antenna + raise RuntimeError(f"Failed to create radio of type '{radio_type}' or antenna.") except Exception as e: self.emit_instance.logger.error(f"Failed to create radio of type '{radio_type}' or antenna: {e}") raise RuntimeError(f"Failed to create radio of type '{radio_type}' or antenna: {e}") diff --git a/src/ansys/aedt/core/emit_core/nodes/emit_node.py b/src/ansys/aedt/core/emit_core/nodes/emit_node.py index 23ceb444695..3b304901d11 100644 --- a/src/ansys/aedt/core/emit_core/nodes/emit_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/emit_node.py @@ -91,6 +91,31 @@ def name(self) -> str: """ return self._get_property("Name", True) + @name.setter + def name(self, requested_name: str): + """Renames the node/component. + + Parameters + ---------- + requested_name : str + New name for the node/component. + + Raises + ------ + ValueError + If the node is read-only or cannot be renamed. + """ + if self._result_id > 0: + raise ValueError("This node is read-only for kept results.") + + if self.get_is_component(): + try: + self._emit_obj.oeditor.RenameComponent(self.name, requested_name) + except Exception: + raise ValueError(f"Failed to rename {self.name} to {requested_name}") + else: + _ = self._oRevisionData.RenameEmitNode(self._result_id, self._node_id, requested_name) + @property def _node_type(self) -> str: """Type of the node. @@ -239,7 +264,7 @@ def children(self): child_nodes = [self._get_node(child_id) for child_id in child_ids] return child_nodes - def _get_property(self, prop, skipChecks=False, isTable=False) -> Union[str, List[str]]: + def _get_property(self, prop, skipChecks: bool = False, isTable: bool = False) -> Union[str, List[str]]: """Fetch the value of a given property. Parameters @@ -257,7 +282,7 @@ def _get_property(self, prop, skipChecks=False, isTable=False) -> Union[str, Lis kv_pairs = [prop.split("=") for prop in props] selected_kv_pairs = [kv for kv in kv_pairs if kv[0].rstrip() == prop] if len(selected_kv_pairs) < 1: - return "" + raise ValueError(f"Property {prop} not found or not available for {self._node_type} configuration.") selected_kv_pair = selected_kv_pairs[0] val = selected_kv_pair[1] @@ -276,9 +301,9 @@ def _get_property(self, prop, skipChecks=False, isTable=False) -> Union[str, Lis except Exception: raise self._emit_obj.logger.aedt_messages.error_level[-1] - def _set_property(self, prop, value): + def _set_property(self, prop, value, skipChecks=False): try: - self._oRevisionData.SetEmitNodeProperties(self._result_id, self._node_id, [f"{prop}={value}"], True) + self._oRevisionData.SetEmitNodeProperties(self._result_id, self._node_id, [f"{prop}={value}"], skipChecks) except Exception: error_text = None if len(self._emit_obj.logger.messages.error_level) > 0: @@ -408,6 +433,9 @@ def _delete(self): def _rename(self, requested_name: str) -> str: """Renames the node/component. + .. deprecated: 0.21.3 + Use name property instead + Parameters ---------- requested_name : str @@ -423,15 +451,10 @@ def _rename(self, requested_name: str) -> str: ValueError If the node is read-only and cannot be renamed. """ - if self.get_is_component(): - if self._result_id > 0: - raise ValueError("This node is read-only for kept results.") - self._emit_obj.oeditor.RenameComponent(self.name, requested_name) - new_name = requested_name - else: - new_name = self._oRevisionData.RenameEmitNode(self._result_id, self._node_id, requested_name) + warnings.warn("This property is deprecated in 0.21.3. Use the name property instead.", DeprecationWarning) + self.name = requested_name - return new_name + return self.name def _duplicate(self, new_name): raise NotImplementedError("This method is not implemented yet.") @@ -563,7 +586,7 @@ def _set_table_data(self, table): # with ';' separating rows and '|' separating columns table_key = self._get_property("TableKey", True) data = ";".join("|".join(map(str, row)) for row in table) - self._set_property(table_key, data) + self._set_property(table_key, data, True) except Exception as e: print(f"Failed to set table data for node {self.name}. Error: {e}") diff --git a/src/ansys/aedt/core/emit_core/nodes/emitter_node.py b/src/ansys/aedt/core/emit_core/nodes/emitter_node.py index f6d8c6cd80d..06e145a5a98 100644 --- a/src/ansys/aedt/core/emit_core/nodes/emitter_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/emitter_node.py @@ -51,8 +51,8 @@ class EmitterNode(EmitNode): """ def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True self._radio_node = RadioNode(emit_obj, result_id, node_id) # create_component code provides the radio_id, but we also @@ -66,6 +66,7 @@ def __init__(self, emit_obj, result_id, node_id): ant_id = self._oRevisionData.GetChildNodeID(result_id, scene_node_id, ant) self._antenna_node = AntennaNode(emit_obj, result_id, ant_id) + @property def node_type(self) -> str: """The type of this emit node""" return "EmitterNode" @@ -106,6 +107,7 @@ def get_antenna(self) -> AntennaNode: """ return self._antenna_node + @property def children(self): """Overridden to return the Waveforms diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/amplifier.py b/src/ansys/aedt/core/emit_core/nodes/generated/amplifier.py index 8ce07129130..dcf8f896b42 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/amplifier.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/amplifier.py @@ -23,25 +23,24 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. - from ansys.aedt.core.emit_core.nodes.emit_node import EmitNode class Amplifier(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -64,19 +63,6 @@ def table_data(self): def table_data(self, value): self._set_table_data(value) - @property - def filename(self) -> str: - """Name of file defining the outboard component. - - Value should be a full file path. - """ - val = self._get_property("Filename") - return val - - @filename.setter - def filename(self, value: str): - self._set_property("Filename", f"{value}") - @property def noise_temperature(self) -> float: """System Noise temperature (K) of the component. diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/antenna_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/antenna_node.py index c8d336e364e..f0716e0d929 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/antenna_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/antenna_node.py @@ -30,8 +30,8 @@ class AntennaNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def parent(self): @@ -47,11 +47,11 @@ def add_antenna_passband(self): """Add a New Passband to this Antenna""" return self._add_child_node("Antenna Passband") - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -112,8 +112,8 @@ def relative_position(self, value): self._set_property("Relative Position", f"{value}") class OrientationModeOption(Enum): - ROLL_PITCH_YAW = "Roll-Pitch-Yaw" - AZ_EL_TWIST = "Az-El-Twist" + ROLL_PITCH_YAW = "rpyDeg" + AZ_EL_TWIST = "aetDeg" @property def orientation_mode(self) -> OrientationModeOption: @@ -183,27 +183,27 @@ def antenna_temperature(self, value: float): class TypeOption(Enum): ISOTROPIC = "Isotropic" - BY_FILE = "By File" + BY_FILE = "ByFile" HEMITROPIC = "Hemitropic" - SHORT_DIPOLE = "Short Dipole" - HALF_WAVE_DIPOLE = "Half-wave Dipole" - QUARTER_WAVE_MONOPOLE = "Quarter-wave Monopole" - WIRE_DIPOLE = "Wire Dipole" - WIRE_MONOPOLE = "Wire Monopole" - SMALL_LOOP = "Small Loop" - DIRECTIVE_BEAM = "Directive Beam" - PYRAMIDAL_HORN = "Pyramidal Horn" + SHORT_DIPOLE = "ShortDipole" + HALF_WAVE_DIPOLE = "HalfWaveDipole" + QUARTER_WAVE_MONOPOLE = "QuarterWaveMonopole" + WIRE_DIPOLE = "WireDipole" + WIRE_MONOPOLE = "WireMonopole" + SMALL_LOOP = "SmallLoop" + DIRECTIVE_BEAM = "DirectiveBeam" + PYRAMIDAL_HORN = "PyramidalHorn" @property def type(self) -> TypeOption: """Defines the type of antenna.""" - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def antenna_file(self) -> str: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/antenna_passband.py b/src/ansys/aedt/core/emit_core/nodes/generated/antenna_passband.py index 569ad1763ff..74c80b4e7e7 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/antenna_passband.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/antenna_passband.py @@ -28,8 +28,8 @@ class AntennaPassband(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -41,11 +41,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -56,7 +56,7 @@ def delete(self): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/band.py b/src/ansys/aedt/core/emit_core/nodes/generated/band.py index ffa5753959f..1d5e42689a1 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/band.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/band.py @@ -30,8 +30,8 @@ class Band(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,10 +43,30 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type + def duplicate(self, new_name: str = ""): + """Duplicate this node""" + return self._duplicate(new_name) + + def delete(self): + """Delete this node""" + self._delete() + + def rename(self, new_name: str = ""): + """Rename this node""" + self._rename(new_name) + + def import_rx_measurement(self, file_name): + """Import a Measurement from a File...""" + return self._import(file_name, "RxMeasurement") + + def import_tx_measurement(self, file_name): + """Import a Measurement from a File...""" + return self._import(file_name, "TxMeasurement") + @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): @@ -241,10 +261,10 @@ def freq_deviation(self, value: float | str): class PSKTypeOption(Enum): BPSK = "BPSK" QPSK = "QPSK" - PSK_8 = "PSK-8" - PSK_16 = "PSK-16" - PSK_32 = "PSK-32" - PSK_64 = "PSK-64" + PSK_8 = "8-PSK" + PSK_16 = "16-PSK" + PSK_32 = "32-PSK" + PSK_64 = "64-PSK" @property def psk_type(self) -> PSKTypeOption: @@ -258,9 +278,9 @@ def psk_type(self, value: PSKTypeOption): self._set_property("PSK Type", f"{value.value}") class FSKTypeOption(Enum): - FSK_2 = "FSK-2" - FSK_4 = "FSK-4" - FSK_8 = "FSK-8" + FSK_2 = "2-FSK" + FSK_4 = "4-FSK" + FSK_8 = "8-FSK" @property def fsk_type(self) -> FSKTypeOption: @@ -274,11 +294,11 @@ def fsk_type(self, value: FSKTypeOption): self._set_property("FSK Type", f"{value.value}") class QAMTypeOption(Enum): - QAM_4 = "QAM-4" - QAM_16 = "QAM-16" - QAM_64 = "QAM-64" - QAM_256 = "QAM-256" - QAM_1024 = "QAM-1024" + QAM_4 = "4-QAM" + QAM_16 = "16-QAM" + QAM_64 = "64-QAM" + QAM_256 = "256-QAM" + QAM_1024 = "1024-QAM" @property def qam_type(self) -> QAMTypeOption: @@ -292,11 +312,11 @@ def qam_type(self, value: QAMTypeOption): self._set_property("QAM Type", f"{value.value}") class APSKTypeOption(Enum): - APSK_4 = "APSK-4" - APSK_16 = "APSK-16" - APSK_64 = "APSK-64" - APSK_256 = "APSK-256" - APSK_1024 = "APSK-1024" + APSK_4 = "4-APSK" + APSK_16 = "16-APSK" + APSK_64 = "64-APSK" + APSK_256 = "256-APSK" + APSK_1024 = "1024-APSK" @property def apsk_type(self) -> APSKTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/band_folder.py b/src/ansys/aedt/core/emit_core/nodes/generated/band_folder.py index 79d13474622..030b885266c 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/band_folder.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/band_folder.py @@ -28,8 +28,8 @@ class BandFolder(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -45,11 +45,11 @@ def add_band(self): """Create a New Band""" return self._add_child_node("Band") - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/cable.py b/src/ansys/aedt/core/emit_core/nodes/generated/cable.py index d6908fbf2ab..49979f4e1b7 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/cable.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/cable.py @@ -30,19 +30,19 @@ class Cable(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -87,9 +87,9 @@ def notes(self, value: str): self._set_property("Notes", f"{value}") class TypeOption(Enum): - BY_FILE = "By File" - CONSTANT_LOSS = "Constant Loss" - COAXIAL_CABLE = "Coaxial Cable" + BY_FILE = "ByFile" + CONSTANT_LOSS = "Constant" + COAXIAL_CABLE = "Coaxial" @property def type(self) -> TypeOption: @@ -98,13 +98,13 @@ def type(self) -> TypeOption: Type of cable to use. Options include: By File (measured or simulated), Constant Loss, or Coaxial Cable. """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def length(self) -> float: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/cad_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/cad_node.py index 191a08b32f6..22abbd0a718 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/cad_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/cad_node.py @@ -30,8 +30,8 @@ class CADNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -64,386 +64,6 @@ def file(self) -> str: val = self._get_property("File") return val - class ModelTypeOption(Enum): - PLATE = "Plate" - BOX = "Box" - DIHEDRAL = "Dihedral" - TRIHEDRAL = "Trihedral" - CYLINDER = "Cylinder" - TAPERED_CYLINDER = "Tapered Cylinder" - CONE = "Cone" - SPHERE = "Sphere" - ELLIPSOID = "Ellipsoid" - CIRCULAR_PLATE = "Circular Plate" - PARABOLA = "Parabola" - PRISM = "Prism" - TAPERED_PRISM = "Tapered Prism" - TOPHAT = "Tophat" - - @property - def model_type(self) -> ModelTypeOption: - """Select type of parametric model to create.""" - val = self._get_property("Model Type") - val = self.ModelTypeOption[val.upper()] - return val - - @model_type.setter - def model_type(self, value: ModelTypeOption): - self._set_property("Model Type", f"{value.value}") - - @property - def length(self) -> float: - """Length of the model. - - Value should be greater than 0.000001. - """ - val = self._get_property("Length") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @length.setter - def length(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Length", f"{value}") - - @property - def width(self) -> float: - """Width of the model. - - Value should be greater than 0.000001. - """ - val = self._get_property("Width") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @width.setter - def width(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Width", f"{value}") - - @property - def height(self) -> float: - """Height of the model. - - Value should be greater than 0.000001. - """ - val = self._get_property("Height") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @height.setter - def height(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Height", f"{value}") - - @property - def angle(self) -> float: - """Angle (deg) between the plates. - - Value should be between 0.0 and 360.0. - """ - val = self._get_property("Angle") - return float(val) - - @angle.setter - def angle(self, value: float): - self._set_property("Angle", f"{value}") - - @property - def top_side(self) -> float: - """Side of the top of a equilateral triangular cylinder model. - - Value should be greater than 0.0. - """ - val = self._get_property("Top Side") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @top_side.setter - def top_side(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Top Side", f"{value}") - - @property - def top_radius(self) -> float: - """Radius of the top of a tapered cylinder model. - - Value should be greater than 0.0. - """ - val = self._get_property("Top Radius") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @top_radius.setter - def top_radius(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Top Radius", f"{value}") - - @property - def side(self) -> float: - """Side of the equilateral triangular cylinder. - - Value should be greater than 0.000001. - """ - val = self._get_property("Side") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @side.setter - def side(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Side", f"{value}") - - @property - def radius(self) -> float: - """Radius of the sphere or cylinder. - - Value should be greater than 0.000001. - """ - val = self._get_property("Radius") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @radius.setter - def radius(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Radius", f"{value}") - - @property - def base_radius(self) -> float: - """Radius of the base of a tophat model. - - Value should be greater than 0.000001. - """ - val = self._get_property("Base Radius") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @base_radius.setter - def base_radius(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Base Radius", f"{value}") - - @property - def center_radius(self) -> float: - """Radius of the raised portion of a tophat model. - - Value should be greater than 0.000001. - """ - val = self._get_property("Center Radius") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @center_radius.setter - def center_radius(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Center Radius", f"{value}") - - @property - def x_axis_ellipsoid_radius(self) -> float: - """Ellipsoid semi-principal radius for the X axis. - - Value should be greater than 0.000001. - """ - val = self._get_property("X Axis Ellipsoid Radius") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @x_axis_ellipsoid_radius.setter - def x_axis_ellipsoid_radius(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("X Axis Ellipsoid Radius", f"{value}") - - @property - def y_axis_ellipsoid_radius(self) -> float: - """Ellipsoid semi-principal radius for the Y axis. - - Value should be greater than 0.000001. - """ - val = self._get_property("Y Axis Ellipsoid Radius") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @y_axis_ellipsoid_radius.setter - def y_axis_ellipsoid_radius(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Y Axis Ellipsoid Radius", f"{value}") - - @property - def z_axis_ellipsoid_radius(self) -> float: - """Ellipsoid semi-principal radius for the Z axis. - - Value should be greater than 0.000001. - """ - val = self._get_property("Z Axis Ellipsoid Radius") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @z_axis_ellipsoid_radius.setter - def z_axis_ellipsoid_radius(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Z Axis Ellipsoid Radius", f"{value}") - - @property - def focal_length(self) -> float: - """Focal length of a parabolic reflector (f = 1/4a where y=ax^2). - - Value should be greater than 0.000001. - """ - val = self._get_property("Focal Length") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @focal_length.setter - def focal_length(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Focal Length", f"{value}") - - @property - def offset(self) -> float: - """Offset of parabolic reflector.""" - val = self._get_property("Offset") - val = self._convert_from_internal_units(float(val), "Length") - return float(val) - - @offset.setter - def offset(self, value: float | str): - value = self._convert_to_internal_units(value, "Length") - self._set_property("Offset", f"{value}") - - @property - def x_direction_taper(self) -> float: - """X Direction Taper. - - Amount (%) that the prism tapers in the X dimension from one end to the - other. - - Value should be greater than 0.0. - """ - val = self._get_property("X Direction Taper") - return float(val) - - @x_direction_taper.setter - def x_direction_taper(self, value: float): - self._set_property("X Direction Taper", f"{value}") - - @property - def y_direction_taper(self) -> float: - """Y Direction Taper. - - Amount (%) that the prism tapers in the Y dimension from one end to the - other. - - Value should be greater than 0.0. - """ - val = self._get_property("Y Direction Taper") - return float(val) - - @y_direction_taper.setter - def y_direction_taper(self, value: float): - self._set_property("Y Direction Taper", f"{value}") - - @property - def prism_direction(self): - """Prism Direction. - - Direction vector between the center of the base and center of the top. - - Value should be x/y/z, delimited by spaces. - """ - val = self._get_property("Prism Direction") - return val - - @prism_direction.setter - def prism_direction(self, value): - self._set_property("Prism Direction", f"{value}") - - @property - def closed_top(self) -> bool: - """Control whether the top of the model is closed. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Closed Top") - return val == "true" - - @closed_top.setter - def closed_top(self, value: bool): - self._set_property("Closed Top", f"{str(value).lower()}") - - @property - def closed_base(self) -> bool: - """Control whether the base of the model is closed. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Closed Base") - return val == "true" - - @closed_base.setter - def closed_base(self, value: bool): - self._set_property("Closed Base", f"{str(value).lower()}") - - @property - def mesh_density(self) -> int: - """Mesh Density. - - Unitless mesh density parameter where higher value improves mesh - smoothness. - - Value should be between 1 and 100. - """ - val = self._get_property("Mesh Density") - return int(val) - - @mesh_density.setter - def mesh_density(self, value: int): - self._set_property("Mesh Density", f"{value}") - - @property - def use_symmetric_mesh(self) -> bool: - """Use Symmetric Mesh. - - Convert quads to a symmetric triangle mesh by adding a center point (4 - triangles per quad instead of 2). - - Value should be 'true' or 'false'. - """ - val = self._get_property("Use Symmetric Mesh") - return val == "true" - - @use_symmetric_mesh.setter - def use_symmetric_mesh(self, value: bool): - self._set_property("Use Symmetric Mesh", f"{str(value).lower()}") - - class MeshOptionOption(Enum): - IMPROVED = "Improved" - LEGACY = "Legacy" - - @property - def mesh_option(self) -> MeshOptionOption: - """Select from different meshing options.""" - val = self._get_property("Mesh Option") - val = self.MeshOptionOption[val.upper()] - return val - - @mesh_option.setter - def mesh_option(self, value: MeshOptionOption): - self._set_property("Mesh Option", f"{value.value}") - - @property - def coating_index(self) -> int: - """Coating index for the parametric model primitive. - - Value should be between 0 and 100000. - """ - val = self._get_property("Coating Index") - return int(val) - - @coating_index.setter - def coating_index(self, value: int): - self._set_property("Coating Index", f"{value}") - @property def show_relative_coordinates(self) -> bool: """Show Relative Coordinates. @@ -489,8 +109,8 @@ def relative_position(self, value): self._set_property("Relative Position", f"{value}") class OrientationModeOption(Enum): - ROLL_PITCH_YAW = "Roll-Pitch-Yaw" - AZ_EL_TWIST = "Az-El-Twist" + ROLL_PITCH_YAW = "rpyDeg" + AZ_EL_TWIST = "aetDeg" @property def orientation_mode(self) -> OrientationModeOption: @@ -548,9 +168,9 @@ def visible(self, value: bool): self._set_property("Visible", f"{str(value).lower()}") class RenderModeOption(Enum): - FLAT_SHADED = "Flat-Shaded" - WIRE_FRAME = "Wire-Frame" - HIDDEN_WIRE_FRAME = "Hidden Wire-Frame" + FLAT_SHADED = "Flat-shaded" + WIRE_FRAME = "Wire-frame" + HIDDEN_WIRE_FRAME = "Hidden wire-frame" OUTLINE = "Outline" @property diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/circulator.py b/src/ansys/aedt/core/emit_core/nodes/generated/circulator.py index 551ef188e5c..470c843edf3 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/circulator.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/circulator.py @@ -30,19 +30,19 @@ class Circulator(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -87,7 +87,7 @@ def notes(self, value: str): self._set_property("Notes", f"{value}") class TypeOption(Enum): - BY_FILE = "By File" + BY_FILE = "ByFile" PARAMETRIC = "Parametric" @property @@ -97,13 +97,13 @@ def type(self) -> TypeOption: Type of circulator model to use. Options include: By File (measured or simulated) or Parametric. """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def insertion_loss(self) -> float: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/coupling_link_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/coupling_link_node.py index 4d20ef8b002..75404aca36b 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/coupling_link_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/coupling_link_node.py @@ -28,8 +28,8 @@ class CouplingLinkNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/couplings_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/couplings_node.py index d3110c5f629..40d42a2375f 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/couplings_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/couplings_node.py @@ -28,8 +28,8 @@ class CouplingsNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def node_type(self) -> str: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/custom_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/custom_coupling_node.py index ece0968a02d..55d425ab8a2 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/custom_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/custom_coupling_node.py @@ -28,8 +28,8 @@ class CustomCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -45,11 +45,11 @@ def import_csv_file(self, file_name): """Import a CSV File...""" return self._import(file_name, "Csv") - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -104,39 +104,3 @@ def antenna_b(self) -> EmitNode: @antenna_b.setter def antenna_b(self, value: EmitNode): self._set_property("Antenna B", f"{value}") - - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/emi_plot_marker_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/emi_plot_marker_node.py index d4eeed32bbc..bcce11ac383 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/emi_plot_marker_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/emi_plot_marker_node.py @@ -30,8 +30,8 @@ class EmiPlotMarkerNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,18 +43,6 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): - """Rename this node""" - self._rename(new_name) - - def duplicate(self, new_name: str): - """Duplicate this node""" - return self._duplicate(new_name) - - def delete(self): - """Delete this node""" - self._delete() - @property def visible(self) -> bool: """Toggle (on/off) this marker. @@ -68,20 +56,6 @@ def visible(self) -> bool: def visible(self, value: bool): self._set_property("Visible", f"{str(value).lower()}") - @property - def attached(self): - """Attached. - - Attach marker to a fixed X-Y point on the plot (True), or to a fixed - point on the plot window (False). - """ - val = self._get_property("Attached") - return val - - @attached.setter - def attached(self, value): - self._set_property("Attached", f"{value}") - @property def position_x(self) -> float: """Position of the marker on the X-axis (frequency axis).""" diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/emit_scene_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/emit_scene_node.py index e7a710315c2..34270c1cc27 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/emit_scene_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/emit_scene_node.py @@ -30,18 +30,26 @@ class EmitSceneNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type + def add_emitter(self): + """Add a new emitter""" + return self._add_child_node("Emitter") + def add_group(self): """Add a new scene group""" return self._add_child_node("Group") + def import_cad(self, file_name): + """Add an existing CAD file""" + return self._import(file_name, "CAD") + def add_antenna(self): """Add a new antenna""" return self._add_child_node("Antenna") diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/erceg_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/erceg_coupling_node.py index 65cdaa1b707..84e93905d2a 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/erceg_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/erceg_coupling_node.py @@ -30,8 +30,8 @@ class ErcegCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -88,46 +88,10 @@ def mobile_antenna(self) -> EmitNode: def mobile_antenna(self, value: EmitNode): self._set_property("Mobile Antenna", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - class TerrainCategoryOption(Enum): - TYPE_A = "Type A" - TYPE_B = "Type B" - TYPE_C = "Type C" + TYPE_A = "TypeA" + TYPE_B = "TypeB" + TYPE_C = "TypeC" @property def terrain_category(self) -> TerrainCategoryOption: @@ -189,10 +153,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/filter.py b/src/ansys/aedt/core/emit_core/nodes/generated/filter.py index ae09d819e14..ff911e9a5e6 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/filter.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/filter.py @@ -30,19 +30,19 @@ class Filter(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -87,13 +87,13 @@ def notes(self, value: str): self._set_property("Notes", f"{value}") class TypeOption(Enum): - BY_FILE = "By File" - LOW_PASS = "Low Pass" # nosec - HIGH_PASS = "High Pass" # nosec - BAND_PASS = "Band Pass" # nosec - BAND_STOP = "Band Stop" - TUNABLE_BANDPASS = "Tunable Bandpass" - TUNABLE_BANDSTOP = "Tunable Bandstop" + BY_FILE = "ByFile" + LOW_PASS = "LowPass" # nosec + HIGH_PASS = "HighPass" # nosec + BAND_PASS = "BandPass" # nosec + BAND_STOP = "BandStop" + TUNABLE_BANDPASS = "TunableBandpass" + TUNABLE_BANDSTOP = "TunableBandstop" @property def type(self) -> TypeOption: @@ -102,13 +102,13 @@ def type(self) -> TypeOption: Type of filter to define. The filter can be defined by file (measured or simulated data) or using one of EMIT's parametric models. """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def insertion_loss(self) -> float: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/five_g_channel_model.py b/src/ansys/aedt/core/emit_core/nodes/generated/five_g_channel_model.py index a8bcb16c67f..740363db7e0 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/five_g_channel_model.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/five_g_channel_model.py @@ -30,8 +30,8 @@ class FiveGChannelModel(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -88,46 +88,10 @@ def mobile_antenna(self) -> EmitNode: def mobile_antenna(self, value: EmitNode): self._set_property("Mobile Antenna", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - class EnvironmentOption(Enum): - URBAN_MICROCELL = "Urban Microcell" - URBAN_MACROCELL = "Urban Macrocell" - RURAL_MACROCELL = "Rural Macrocell" + URBAN_MICROCELL = "UrbanMicrocell" + URBAN_MACROCELL = "UrbanMacrocell" + RURAL_MACROCELL = "RuralMacrocell" @property def environment(self) -> EnvironmentOption: @@ -167,8 +131,8 @@ def include_bpl(self, value: bool): self._set_property("Include BPL", f"{str(value).lower()}") class NYUBPLModelOption(Enum): - LOW_LOSS_MODEL = "Low-loss model" - HIGH_LOSS_MODEL = "High-loss model" + LOW_LOSS_MODEL = "LowLossModel" + HIGH_LOSS_MODEL = "HighLossModel" @property def nyu_bpl_model(self) -> NYUBPLModelOption: @@ -230,10 +194,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/hata_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/hata_coupling_node.py index e09216a996d..6c494390311 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/hata_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/hata_coupling_node.py @@ -30,8 +30,8 @@ class HataCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -88,45 +88,9 @@ def mobile_antenna(self) -> EmitNode: def mobile_antenna(self, value: EmitNode): self._set_property("Mobile Antenna", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - class EnvironmentOption(Enum): - LARGE_CITY = "Large City" - SMALLMEDIUM_CITY = "Small/Medium City" + LARGE_CITY = "LargeCity" + SMALLMEDIUM_CITY = "SmallMedCity" SUBURBAN = "Suburban" RURAL = "Rural" @@ -190,10 +154,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/indoor_propagation_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/indoor_propagation_coupling_node.py index 2075210b97a..58e404ed734 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/indoor_propagation_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/indoor_propagation_coupling_node.py @@ -30,8 +30,8 @@ class IndoorPropagationCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -105,48 +105,12 @@ def antenna_b(self) -> EmitNode: def antenna_b(self, value: EmitNode): self._set_property("Antenna B", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - class BuildingTypeOption(Enum): - RESIDENTIAL_APARTMENT = "Residential Apartment" - RESIDENTIAL_HOUSE = "Residential House" - OFFICE_BUILDING = "Office Building" - COMMERCIAL_BUILDING = "Commercial Building" - CUSTOM_BUILDING = "Custom Building" + RESIDENTIAL_APARTMENT = "ResidentialApartment" + RESIDENTIAL_HOUSE = "ResidentialHouse" + OFFICE_BUILDING = "OfficeBuilding" + COMMERCIAL_BUILDING = "CommercialBuilding" + CUSTOM_BUILDING = "CustomBuilding" @property def building_type(self) -> BuildingTypeOption: @@ -221,10 +185,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/isolator.py b/src/ansys/aedt/core/emit_core/nodes/generated/isolator.py index 8bebfe07784..42e80ff8f2f 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/isolator.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/isolator.py @@ -30,19 +30,19 @@ class Isolator(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -87,7 +87,7 @@ def notes(self, value: str): self._set_property("Notes", f"{value}") class TypeOption(Enum): - BY_FILE = "By File" + BY_FILE = "ByFile" PARAMETRIC = "Parametric" @property @@ -97,13 +97,13 @@ def type(self) -> TypeOption: Type of isolator model to use. Options include: By File (measured or simulated) or Parametric. """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def insertion_loss(self) -> float: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/log_distance_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/log_distance_coupling_node.py index 74ab091c297..93e5d3e52c8 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/log_distance_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/log_distance_coupling_node.py @@ -30,8 +30,8 @@ class LogDistanceCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -88,50 +88,14 @@ def antenna_b(self) -> EmitNode: def antenna_b(self, value: EmitNode): self._set_property("Antenna B", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - class EnvironmentOption(Enum): - FREE_SPACE = "Free Space" + FREE_SPACE = "FreeSpace" URBAN = "Urban" - SHADOWED_URBAN = "Shadowed Urban" - BUILDING_LINE_OF_SIGHT = "Building Line of Sight" - BUILDING_OBSTRUCTED = "Building Obstructed" - FACTORY_OBSTRUCTED = "Factory Obstructed" - CUSTOM = "Custom" + SHADOWED_URBAN = "ShadowedUrban" + BUILDING_LINE_OF_SIGHT = "BuildingLineOfSight" + BUILDING_OBSTRUCTED = "BuildingObstructed" + FACTORY_OBSTRUCTED = "FactoryObstructed" + CUSTOM = "CustomExponent" @property def environment(self) -> EnvironmentOption: @@ -206,10 +170,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer.py b/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer.py index 6225e44da75..9823a8abe8b 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer.py @@ -30,8 +30,8 @@ class Multiplexer(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: @@ -42,11 +42,11 @@ def add_multiplexer_pass_band(self): """Add a New Multiplexer Band to this Multiplexer""" return self._add_child_node("Multiplexer Pass Band") - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -91,8 +91,8 @@ def notes(self, value: str): self._set_property("Notes", f"{value}") class TypeOption(Enum): - BY_PASS_BAND = "By Pass Band" # nosec - BY_FILE = "By File" + BY_PASS_BAND = "Parametric" # nosec + BY_FILE = "ByFile" @property def type(self) -> TypeOption: @@ -102,13 +102,13 @@ def type(self) -> TypeOption: simulated file for the device) or By Pass Band (parametric or file-based definition for each pass band). """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def ports(self): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer_band.py b/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer_band.py index 3abe5d6ac34..6b1e2b6ed42 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer_band.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/multiplexer_band.py @@ -30,8 +30,8 @@ class MultiplexerBand(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -56,10 +56,10 @@ def delete(self): self._delete() class TypeOption(Enum): - BY_FILE = "By File" - LOW_PASS = "Low Pass" # nosec - HIGH_PASS = "High Pass" # nosec - BAND_PASS = "Band Pass" # nosec + BY_FILE = "ByFile" + LOW_PASS = "LowPass" # nosec + HIGH_PASS = "HighPass" # nosec + BAND_PASS = "BandPass" # nosec @property def type(self) -> TypeOption: @@ -69,13 +69,13 @@ def type(self) -> TypeOption: file (measured or simulated data) or using one of EMIT's parametric models. """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def filename(self) -> str: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/power_divider.py b/src/ansys/aedt/core/emit_core/nodes/generated/power_divider.py index db5d90afb57..bc1c07d1f1a 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/power_divider.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/power_divider.py @@ -30,19 +30,19 @@ class PowerDivider(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -87,8 +87,8 @@ def notes(self, value: str): self._set_property("Notes", f"{value}") class TypeOption(Enum): - BY_FILE = "By File" - P3_DB = "P3 dB" + BY_FILE = "ByFile" + P3_DB = "3dB" RESISTIVE = "Resistive" @property @@ -98,13 +98,13 @@ def type(self) -> TypeOption: Type of Power Divider model to use. Options include: By File (measured or simulated), 3 dB (parametric), and Resistive (parametric). """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def insertion_loss_above_ideal(self) -> float: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/propagation_loss_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/propagation_loss_coupling_node.py index fe0da4f548b..ef25a244772 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/propagation_loss_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/propagation_loss_coupling_node.py @@ -30,8 +30,8 @@ class PropagationLossCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -88,42 +88,6 @@ def antenna_b(self) -> EmitNode: def antenna_b(self, value: EmitNode): self._set_property("Antenna B", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - @property def custom_fading_margin(self) -> float: """Custom Fading Margin. @@ -173,10 +137,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/radio_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/radio_node.py index 792beaea636..01dc44e02e0 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/radio_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/radio_node.py @@ -28,13 +28,8 @@ class RadioNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) - - @property - def parent(self): - """The parent of this emit node.""" - return self._parent + self._is_component = True @property def node_type(self) -> str: @@ -49,11 +44,11 @@ def add_folder(self): """Create a New Folder to Organize Bands""" return self._add_child_node("Band Folder") - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/result_plot_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/result_plot_node.py index 0d7bb2264b6..73ae376a2ed 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/result_plot_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/result_plot_node.py @@ -30,22 +30,14 @@ class ResultPlotNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def add_marker(self): - """Add an icon and/or label to this plot""" - return self._add_child_node("Plot Marker") - - def export_model(self, file_name): - """Save this data to a file""" - return self._export_model(file_name) - @property def title(self) -> str: """Enter title at the top of the plot, room will be made for it.""" @@ -108,58 +100,6 @@ def show_emi_thresholds(self) -> bool: def show_emi_thresholds(self, value: bool): self._set_property("Show EMI Thresholds", f"{str(value).lower()}") - @property - def display_cad_overlay(self) -> bool: - """Toggle on/off overlay of CAD model in plot. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Display CAD Overlay") - return val == "true" - - @display_cad_overlay.setter - def display_cad_overlay(self, value: bool): - self._set_property("Display CAD Overlay", f"{str(value).lower()}") - - @property - def opacity(self) -> float: - """Adjust opacity of CAD model overlay: 0 Transparent - 1 Opaque. - - Value should be between 0 and 100. - """ - val = self._get_property("Opacity") - return float(val) - - @opacity.setter - def opacity(self, value: float): - self._set_property("Opacity", f"{value}") - - @property - def vertical_offset(self) -> float: - """Adjust vertical position of CAD model overlay.""" - val = self._get_property("Vertical Offset") - return float(val) - - @vertical_offset.setter - def vertical_offset(self, value: float): - self._set_property("Vertical Offset", f"{value}") - - @property - def range_axis_rotation(self) -> float: - """Range Axis Rotation. - - Adjust view angle for CAD model overlay by rotating it about plot - horizontal axis. - - Value should be between -180 and 180. - """ - val = self._get_property("Range Axis Rotation") - return float(val) - - @range_axis_rotation.setter - def range_axis_rotation(self, value: float): - self._set_property("Range Axis Rotation", f"{value}") - @property def lock_axes(self) -> bool: """Lock Axes. @@ -216,22 +156,6 @@ def y_axis_max(self) -> float: def y_axis_max(self, value: float): self._set_property("Y-axis Max", f"{value}") - @property - def y_axis_range(self) -> float: - """Y-axis Range. - - Adjust dB span of vertical axis, makes corresponding adjustment in - Y-axis Min. - - Value should be greater than 0. - """ - val = self._get_property("Y-axis Range") - return float(val) - - @y_axis_range.setter - def y_axis_range(self, value: float): - self._set_property("Y-axis Range", f"{value}") - @property def max_major_ticks_x(self) -> int: """Max Major Ticks X. diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/rx_meas_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/rx_meas_node.py index c476adf41be..fd78442d48a 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/rx_meas_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/rx_meas_node.py @@ -23,15 +23,14 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from enum import Enum from ansys.aedt.core.emit_core.nodes.emit_node import EmitNode class RxMeasNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,7 +42,7 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) @@ -60,15 +59,6 @@ def file(self) -> str: val = self._get_property("File") return val - @property - def source_file(self) -> str: - """Name of the measurement source. - - Value should be a full file path. - """ - val = self._get_property("Source File") - return val - @property def receive_frequency(self) -> float: """Channel associated with the measurement file.""" @@ -76,249 +66,6 @@ def receive_frequency(self) -> float: val = self._convert_from_internal_units(float(val), "Freq") return float(val) - class MeasurementModeOption(Enum): - AUDIO_SINAD = "Audio SINAD" - DIGITAL_BER = "Digital BER" - GPS_CNR = "GPS CNR" - - @property - def measurement_mode(self) -> MeasurementModeOption: - """Defines the mode for the receiver measurement.""" - val = self._get_property("Measurement Mode") - val = self.MeasurementModeOption[val.upper()] - return val - - @measurement_mode.setter - def measurement_mode(self, value: MeasurementModeOption): - self._set_property("Measurement Mode", f"{value.value}") - - @property - def sinad_threshold(self) -> float: - """SINAD Threshold used for the receiver measurements. - - Value should be between 5 and 20. - """ - val = self._get_property("SINAD Threshold") - return float(val) - - @sinad_threshold.setter - def sinad_threshold(self, value: float): - self._set_property("SINAD Threshold", f"{value}") - - @property - def gps_cnr_threshold(self) -> float: - """GPS CNR Threshold used for the receiver measurements. - - Value should be between 15 and 30. - """ - val = self._get_property("GPS CNR Threshold") - return float(val) - - @gps_cnr_threshold.setter - def gps_cnr_threshold(self, value: float): - self._set_property("GPS CNR Threshold", f"{value}") - - @property - def ber_threshold(self) -> float: - """BER Threshold used for the receiver measurements. - - Value should be between -12 and -1. - """ - val = self._get_property("BER Threshold") - return float(val) - - @ber_threshold.setter - def ber_threshold(self, value: float): - self._set_property("BER Threshold", f"{value}") - - @property - def default_intended_power(self) -> bool: - """Specify the intended signal. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Default Intended Power") - return val == "true" - - @default_intended_power.setter - def default_intended_power(self, value: bool): - self._set_property("Default Intended Power", f"{str(value).lower()}") - - @property - def intended_signal_power(self) -> float: - """Specify the power level of the intended signal. - - Value should be between -140 and -50. - """ - val = self._get_property("Intended Signal Power") - return float(val) - - @intended_signal_power.setter - def intended_signal_power(self, value: float): - self._set_property("Intended Signal Power", f"{value}") - - @property - def freq_deviation(self) -> float: - """Specify the frequency deviation of the intended signal. - - Value should be between 1000 and 200000. - """ - val = self._get_property("Freq. Deviation") - val = self._convert_from_internal_units(float(val), "Freq") - return float(val) - - @freq_deviation.setter - def freq_deviation(self, value: float | str): - value = self._convert_to_internal_units(value, "Freq") - self._set_property("Freq. Deviation", f"{value}") - - @property - def modulation_depth(self) -> float: - """Specify the modulation depth of the intended signal. - - Value should be between 10 and 100. - """ - val = self._get_property("Modulation Depth") - return float(val) - - @modulation_depth.setter - def modulation_depth(self, value: float): - self._set_property("Modulation Depth", f"{value}") - - @property - def measure_selectivity(self) -> bool: - """Enable/disable the measurement of the receiver's selectivity. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Measure Selectivity") - return val == "true" - - @measure_selectivity.setter - def measure_selectivity(self, value: bool): - self._set_property("Measure Selectivity", f"{str(value).lower()}") - - @property - def measure_mixer_products(self) -> bool: - """Enable/disable the measurement of the receiver's mixer products. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Measure Mixer Products") - return val == "true" - - @measure_mixer_products.setter - def measure_mixer_products(self, value: bool): - self._set_property("Measure Mixer Products", f"{str(value).lower()}") - - @property - def max_rf_order(self) -> int: - """Max RF Order of the mixer products to measure. - - Value should be greater than 1. - """ - val = self._get_property("Max RF Order") - return int(val) - - @max_rf_order.setter - def max_rf_order(self, value: int): - self._set_property("Max RF Order", f"{value}") - - @property - def max_lo_order(self) -> int: - """Max LO Order of the mixer products to measure. - - Value should be greater than 1. - """ - val = self._get_property("Max LO Order") - return int(val) - - @max_lo_order.setter - def max_lo_order(self, value: int): - self._set_property("Max LO Order", f"{value}") - - @property - def include_if(self) -> bool: - """Enable/disable the measurement of the IF channel. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Include IF") - return val == "true" - - @include_if.setter - def include_if(self, value: bool): - self._set_property("Include IF", f"{str(value).lower()}") - - @property - def measure_saturation(self) -> bool: - """Enable/disable measurement of the receiver's saturation level. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Measure Saturation") - return val == "true" - - @measure_saturation.setter - def measure_saturation(self, value: bool): - self._set_property("Measure Saturation", f"{str(value).lower()}") - - @property - def use_ams_limits(self) -> bool: - """Allow AMS to determine the limits for measuring saturation. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Use AMS Limits") - return val == "true" - - @use_ams_limits.setter - def use_ams_limits(self, value: bool): - self._set_property("Use AMS Limits", f"{str(value).lower()}") - - @property - def start_frequency(self) -> float: - """Starting frequency for the measurement sweep. - - Value should be greater than 1e6. - """ - val = self._get_property("Start Frequency") - val = self._convert_from_internal_units(float(val), "Freq") - return float(val) - - @start_frequency.setter - def start_frequency(self, value: float | str): - value = self._convert_to_internal_units(value, "Freq") - self._set_property("Start Frequency", f"{value}") - - @property - def stop_frequency(self) -> float: - """Stopping frequency for the measurement sweep. - - Value should be less than 6e9. - """ - val = self._get_property("Stop Frequency") - val = self._convert_from_internal_units(float(val), "Freq") - return float(val) - - @stop_frequency.setter - def stop_frequency(self, value: float | str): - value = self._convert_to_internal_units(value, "Freq") - self._set_property("Stop Frequency", f"{value}") - - @property - def samples(self) -> int: - """Number of measurement samples for each frequency. - - Value should be between 2 and 100. - """ - val = self._get_property("Samples") - return int(val) - - @samples.setter - def samples(self, value: int): - self._set_property("Samples", f"{value}") - @property def exclude_mixer_products_below_noise(self) -> bool: """Include/Exclude Mixer Products below the noise. @@ -335,7 +82,7 @@ def exclude_mixer_products_below_noise(self, value: bool): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/rx_mixer_product_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/rx_mixer_product_node.py index 73ac87b3bd7..97057cc4c5b 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/rx_mixer_product_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/rx_mixer_product_node.py @@ -30,8 +30,8 @@ class RxMixerProductNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -71,7 +71,7 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): @@ -236,9 +236,9 @@ def maximum_lo_harmonic_order(self, value: int): self._set_property("Maximum LO Harmonic Order", f"{value}") class MixingModeOption(Enum): - LO_ABOVE_TUNED_RF_FREQUENCY = "LO Above Tuned (RF) Frequency" - LO_BELOW_TUNED_RF_FREQUENCY = "LO Below Tuned (RF) Frequency" - LO_ABOVEBELOW_TUNED_RF_FREQUENCY = "LO Above/Below Tuned (RF) Frequency" + LO_ABOVE_TUNED_RF_FREQUENCY = "AboveTunedFrequency" + LO_BELOW_TUNED_RF_FREQUENCY = "BelowTunedFrequency" + LO_ABOVEBELOW_TUNED_RF_FREQUENCY = "BothTunedFrequencies" @property def mixing_mode(self) -> MixingModeOption: @@ -277,8 +277,8 @@ def rf_transition_frequency(self, value: float | str): self._set_property("RF Transition Frequency", f"{value}") class UseHighLOOption(Enum): - ABOVE_TRANSITION_FREQUENCY = "Above Transition Frequency" - BELOW_TRANSITION_FREQUENCY = "Below Transition Frequency" + ABOVE_TRANSITION_FREQUENCY = "AboveTransition" + BELOW_TRANSITION_FREQUENCY = "BelowTransition" @property def use_high_lo(self) -> UseHighLOOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/rx_saturation_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/rx_saturation_node.py index a84a5965a7d..9185ee21183 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/rx_saturation_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/rx_saturation_node.py @@ -28,8 +28,8 @@ class RxSaturationNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -67,7 +67,7 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/rx_selectivity_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/rx_selectivity_node.py index 9c8ea1d3380..fdcd20e19d3 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/rx_selectivity_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/rx_selectivity_node.py @@ -28,8 +28,8 @@ class RxSelectivityNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -67,7 +67,7 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/rx_spur_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/rx_spur_node.py index 2c14267787d..c98417b6b87 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/rx_spur_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/rx_spur_node.py @@ -30,8 +30,8 @@ class RxSpurNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -71,7 +71,7 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/rx_susceptibility_prof_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/rx_susceptibility_prof_node.py index 5fb206bbc06..d1675bcbb3b 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/rx_susceptibility_prof_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/rx_susceptibility_prof_node.py @@ -30,8 +30,8 @@ class RxSusceptibilityProfNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -62,7 +62,7 @@ def add_spurious_responses(self): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/sampling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/sampling_node.py index 701de81f7bd..2bf087add9a 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/sampling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/sampling_node.py @@ -30,8 +30,8 @@ class SamplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -59,9 +59,9 @@ def table_data(self, value): self._set_table_data(value) class SamplingTypeOption(Enum): - SAMPLE_ALL_CHANNELS_IN_RANGES = "Sample All Channels in Range(s)" - RANDOM_SAMPLING = "Random Sampling" - UNIFORM_SAMPLING = "Uniform Sampling" + SAMPLE_ALL_CHANNELS_IN_RANGES = "SampleAllChannels" + RANDOM_SAMPLING = "RandomSampling" + UNIFORM_SAMPLING = "UniformSampling" @property def sampling_type(self) -> SamplingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/scene_group_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/scene_group_node.py index d7dcb056527..93f98d62ba7 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/scene_group_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/scene_group_node.py @@ -30,8 +30,8 @@ class SceneGroupNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,19 +43,27 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type + def add_emitter(self): + """Add a new emitter""" + return self._add_child_node("Emitter") + def add_group(self): """Add a new scene group""" return self._add_child_node("Group") + def import_cad(self, file_name): + """Add an existing CAD file""" + return self._import(file_name, "CAD") + def add_antenna(self): """Add a new antenna""" return self._add_child_node("Antenna") - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -106,8 +114,8 @@ def relative_position(self, value): self._set_property("Relative Position", f"{value}") class OrientationModeOption(Enum): - ROLL_PITCH_YAW = "Roll-Pitch-Yaw" - AZ_EL_TWIST = "Az-El-Twist" + ROLL_PITCH_YAW = "rpyDeg" + AZ_EL_TWIST = "aetDeg" @property def orientation_mode(self) -> OrientationModeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/solution_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/solution_coupling_node.py index a48305d4a97..c19cdfde96c 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/solution_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/solution_coupling_node.py @@ -28,8 +28,8 @@ class SolutionCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -56,39 +56,3 @@ def enabled(self) -> bool: @enabled.setter def enabled(self, value: bool): self._set_property("Enabled", f"{str(value).lower()}") - - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/solutions_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/solutions_node.py index 4daea0ded85..9c5dd677c51 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/solutions_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/solutions_node.py @@ -28,8 +28,8 @@ class SolutionsNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/terminator.py b/src/ansys/aedt/core/emit_core/nodes/generated/terminator.py index 2e37e3f2ae8..63ab0b80cd9 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/terminator.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/terminator.py @@ -30,19 +30,19 @@ class Terminator(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -104,7 +104,7 @@ def notes(self, value: str): self._set_property("Notes", f"{value}") class TypeOption(Enum): - BY_FILE = "By File" + BY_FILE = "ByFile" PARAMETRIC = "Parametric" @property @@ -114,13 +114,13 @@ def type(self) -> TypeOption: Type of terminator model to use. Options include: By File (measured or simulated) or Parametric. """ - val = self._get_property("Type") - val = self.TypeOption[val.upper()] + val = self._get_property("Type", True) + val = self.TypeOption(val) return val @type.setter def type(self, value: TypeOption): - self._set_property("Type", f"{value.value}") + self._set_property("SubType", f"{value.value}", True) @property def vswr(self) -> float: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/touchstone_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/touchstone_coupling_node.py index 51de0fff4ab..fa7d564bd17 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/touchstone_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/touchstone_coupling_node.py @@ -28,8 +28,8 @@ class TouchstoneCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -41,11 +41,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -66,42 +66,6 @@ def enabled(self) -> bool: def enabled(self, value: bool): self._set_property("Enabled", f"{str(value).lower()}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - @property def filename(self) -> str: """Name of file with coupling data. diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tr_switch.py b/src/ansys/aedt/core/emit_core/nodes/generated/tr_switch.py index 70fed7d32cc..aebb7a3a389 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tr_switch.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tr_switch.py @@ -23,25 +23,24 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. - from ansys.aedt.core.emit_core.nodes.emit_node import EmitNode class TR_Switch(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = True EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = True @property def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -49,19 +48,6 @@ def delete(self): """Delete this node""" self._delete() - @property - def filename(self) -> str: - """Name of file defining the outboard component. - - Value should be a full file path. - """ - val = self._get_property("Filename") - return val - - @filename.setter - def filename(self, value: str): - self._set_property("Filename", f"{value}") - @property def noise_temperature(self) -> float: """System Noise temperature (K) of the component. diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/two_ray_path_loss_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/two_ray_path_loss_coupling_node.py index adc080cc4f4..74da198aa22 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/two_ray_path_loss_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/two_ray_path_loss_coupling_node.py @@ -30,8 +30,8 @@ class TwoRayPathLossCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -88,42 +88,6 @@ def antenna_b(self) -> EmitNode: def antenna_b(self, value: EmitNode): self._set_property("Antenna B", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - @property def ground_reflection_coeff(self) -> float: """The ground reflection coefficient. @@ -201,10 +165,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tx_bb_emission_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/tx_bb_emission_node.py index 3db2f83ed5c..0354894fb76 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tx_bb_emission_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tx_bb_emission_node.py @@ -30,8 +30,8 @@ class TxBbEmissionNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -69,7 +69,7 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): @@ -77,9 +77,9 @@ def enabled(self, value: bool): class NoiseBehaviorOption(Enum): ABSOLUTE = "Absolute" - RELATIVE_BANDWIDTH = "Relative (Bandwidth)" - RELATIVE_OFFSET = "Relative (Offset)" - EQUATION = "Equation" + RELATIVE_BANDWIDTH = "RelativeBandwidth" + RELATIVE_OFFSET = "RelativeOffset" + EQUATION = "BroadbandEquation" @property def noise_behavior(self) -> NoiseBehaviorOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tx_harmonic_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/tx_harmonic_node.py index d5b24df5a79..32873818482 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tx_harmonic_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tx_harmonic_node.py @@ -30,8 +30,8 @@ class TxHarmonicNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -69,7 +69,7 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tx_meas_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/tx_meas_node.py index fac7bbb4036..0180dc8752a 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tx_meas_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tx_meas_node.py @@ -28,8 +28,8 @@ class TxMeasNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -41,7 +41,7 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) @@ -58,15 +58,6 @@ def file(self) -> str: val = self._get_property("File") return val - @property - def source_file(self) -> str: - """Name of the measurement source. - - Value should be a full file path. - """ - val = self._get_property("Source File") - return val - @property def transmit_frequency(self) -> float: """Channel associated with the measurement file.""" @@ -74,49 +65,6 @@ def transmit_frequency(self) -> float: val = self._convert_from_internal_units(float(val), "Freq") return float(val) - @property - def use_ams_limits(self) -> bool: - """Allow AMS to define the frequency limits for the measurements. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Use AMS Limits") - return val == "true" - - @use_ams_limits.setter - def use_ams_limits(self, value: bool): - self._set_property("Use AMS Limits", f"{str(value).lower()}") - - @property - def start_frequency(self) -> float: - """Starting frequency for the measurement sweep. - - Value should be greater than 1e6. - """ - val = self._get_property("Start Frequency") - val = self._convert_from_internal_units(float(val), "Freq") - return float(val) - - @start_frequency.setter - def start_frequency(self, value: float | str): - value = self._convert_to_internal_units(value, "Freq") - self._set_property("Start Frequency", f"{value}") - - @property - def stop_frequency(self) -> float: - """Stopping frequency for the measurement sweep. - - Value should be less than 6e9. - """ - val = self._get_property("Stop Frequency") - val = self._convert_from_internal_units(float(val), "Freq") - return float(val) - - @stop_frequency.setter - def stop_frequency(self, value: float | str): - value = self._convert_to_internal_units(value, "Freq") - self._set_property("Stop Frequency", f"{value}") - @property def exclude_harmonics_below_noise(self) -> bool: """Include/Exclude Harmonics below the noise. @@ -133,7 +81,7 @@ def exclude_harmonics_below_noise(self, value: bool): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tx_nb_emission_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/tx_nb_emission_node.py index 3888c2f9ec6..2432210e454 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tx_nb_emission_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tx_nb_emission_node.py @@ -30,8 +30,8 @@ class TxNbEmissionNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -69,15 +69,15 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): self._set_property("Enabled", f"{str(value).lower()}") class NarrowbandBehaviorOption(Enum): - ABSOLUTE_FREQS_AND_POWER = "Absolute Freqs and Power" - RELATIVE_FREQS_AND_ATTENUATION = "Relative Freqs and Attenuation" + ABSOLUTE_FREQS_AND_POWER = "Absolute" + RELATIVE_FREQS_AND_ATTENUATION = "RelativeBandwidth" @property def narrowband_behavior(self) -> NarrowbandBehaviorOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_emitter_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_emitter_node.py index 4af0ba79bcd..32b334fd173 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_emitter_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_emitter_node.py @@ -28,8 +28,8 @@ class TxSpectralProfEmitterNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -41,10 +41,26 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type + def add_narrowband_emissions_mask(self): + """Add a Transmitter Narrowband Emission Profile""" + return self._add_child_node("Narrowband Emissions Mask") + + def add_tx_broadband_noise_profile(self): + """Add a Transmitter Broadband Emission Profile""" + return self._add_child_node("Tx Broadband Noise Profile") + + def add_custom_tx_harmonics(self): + """Add Custom Tx Harmonics""" + return self._add_child_node("Custom Tx Harmonics") + + def add_spurious_emissions(self): + """Add Transmitter Spurs""" + return self._add_child_node("Spurious Emissions") + @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): @@ -88,6 +104,19 @@ def tx_broadband_noise(self) -> float: def tx_broadband_noise(self, value: float): self._set_property("Tx Broadband Noise", f"{value}") + @property + def number_of_harmonics(self) -> int: + """Maximum number of harmonics modeled. + + Value should be between 1 and 1000. + """ + val = self._get_property("Number of Harmonics") + return int(val) + + @number_of_harmonics.setter + def number_of_harmonics(self, value: int): + self._set_property("Number of Harmonics", f"{value}") + @property def perform_tx_intermod_analysis(self) -> bool: """Performs a non-linear intermod analysis for the Tx. diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_node.py index 0db4e9ac4de..ff0d37e219b 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tx_spectral_prof_node.py @@ -30,8 +30,8 @@ class TxSpectralProfNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -62,15 +62,15 @@ def add_spurious_emissions(self): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): self._set_property("Enabled", f"{str(value).lower()}") class SpectrumTypeOption(Enum): - NARROWBAND_AND_BROADBAND = "Narrowband & Broadband" - BROADBAND_ONLY = "Broadband Only" + NARROWBAND_AND_BROADBAND = "Both" + BROADBAND_ONLY = "BroadbandOnly" @property def spectrum_type(self) -> SpectrumTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/tx_spur_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/tx_spur_node.py index a40a55ea351..2a1eb086363 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/tx_spur_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/tx_spur_node.py @@ -30,8 +30,8 @@ class TxSpurNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -71,7 +71,7 @@ def table_data(self, value): @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/walfisch_coupling_node.py b/src/ansys/aedt/core/emit_core/nodes/generated/walfisch_coupling_node.py index cb8f0251201..e9ea98963d7 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/walfisch_coupling_node.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/walfisch_coupling_node.py @@ -30,8 +30,8 @@ class WalfischCouplingNode(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,11 +43,11 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type - def rename(self, new_name: str): + def rename(self, new_name: str = ""): """Rename this node""" self._rename(new_name) - def duplicate(self, new_name: str): + def duplicate(self, new_name: str = ""): """Duplicate this node""" return self._duplicate(new_name) @@ -88,45 +88,9 @@ def mobile_antenna(self) -> EmitNode: def mobile_antenna(self, value: EmitNode): self._set_property("Mobile Antenna", f"{value}") - @property - def enable_refinement(self) -> bool: - """Enables/disables refined sampling of the frequency domain. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Enable Refinement") - return val == "true" - - @enable_refinement.setter - def enable_refinement(self, value: bool): - self._set_property("Enable Refinement", f"{str(value).lower()}") - - @property - def adaptive_sampling(self) -> bool: - """Enables/disables adaptive refinement the frequency domain sampling. - - Value should be 'true' or 'false'. - """ - val = self._get_property("Adaptive Sampling") - return val == "true" - - @adaptive_sampling.setter - def adaptive_sampling(self, value: bool): - self._set_property("Adaptive Sampling", f"{str(value).lower()}") - - @property - def refinement_domain(self): - """Points to use when refining the frequency domain.""" - val = self._get_property("Refinement Domain") - return val - - @refinement_domain.setter - def refinement_domain(self, value): - self._set_property("Refinement Domain", f"{value}") - class PathLossTypeOption(Enum): - LOS_URBAN_CANYON = "LOS (Urban Canyon)" - NLOS = "NLOS" + LOS_URBAN_CANYON = "WalfischLOS" + NLOS = "WalfischNLOS" @property def path_loss_type(self) -> PathLossTypeOption: @@ -140,8 +104,8 @@ def path_loss_type(self, value: PathLossTypeOption): self._set_property("Path Loss Type", f"{value.value}") class EnvironmentOption(Enum): - DENSE_METRO = "Dense Metro" - SMALLMEDIUM_CITY_OR_SUBURBAN = "Small/Medium City or Suburban" + DENSE_METRO = "DenseMetroArea" + SMALLMEDIUM_CITY_OR_SUBURBAN = "SmallUrbanOrSuburban" @property def environment(self) -> EnvironmentOption: @@ -261,10 +225,10 @@ def pointing_error_loss(self, value: float): self._set_property("Pointing Error Loss", f"{value}") class FadingTypeOption(Enum): - NONE = "None" - FAST_FADING_ONLY = "Fast Fading Only" - SHADOWING_ONLY = "Shadowing Only" - FAST_FADING_AND_SHADOWING = "Fast Fading and Shadowing" + NONE = "NoFading" + FAST_FADING_ONLY = "FastFadingOnly" + SHADOWING_ONLY = "ShadowingOnly" + FAST_FADING_AND_SHADOWING = "ShadowingAndFastFading" @property def fading_type(self) -> FadingTypeOption: diff --git a/src/ansys/aedt/core/emit_core/nodes/generated/waveform.py b/src/ansys/aedt/core/emit_core/nodes/generated/waveform.py index b9e3354c6a5..1b0d450f66b 100644 --- a/src/ansys/aedt/core/emit_core/nodes/generated/waveform.py +++ b/src/ansys/aedt/core/emit_core/nodes/generated/waveform.py @@ -30,8 +30,8 @@ class Waveform(EmitNode): def __init__(self, emit_obj, result_id, node_id): - self._is_component = False EmitNode.__init__(self, emit_obj, result_id, node_id) + self._is_component = False @property def parent(self): @@ -43,10 +43,26 @@ def node_type(self) -> str: """The type of this emit node.""" return self._node_type + def duplicate(self, new_name: str = ""): + """Duplicate this node""" + return self._duplicate(new_name) + + def delete(self): + """Delete this node""" + self._delete() + + def rename(self, new_name: str = ""): + """Rename this node""" + self._rename(new_name) + + def import_tx_measurement(self, file_name): + """Import a Measurement from a File...""" + return self._import(file_name, "TxMeasurement") + @property def enabled(self) -> bool: """Enabled state for this node.""" - return self._get_property("Enabled") + return self._get_property("Enabled") == "true" @enabled.setter def enabled(self, value: bool): @@ -54,7 +70,7 @@ def enabled(self, value: bool): class WaveformOption(Enum): PERIODIC_CLOCK = "Periodic Clock" - SPREAD_SPECTRUM_CLOCK = "Spread Spectrum Clock" + SPREAD_SPECTRUM_CLOCK = "Spread Spectrum" PRBS = "PRBS" PRBS_PERIODIC = "PRBS (Periodic)" IMPORTED = "Imported" @@ -85,36 +101,6 @@ def start_frequency(self, value: float | str): value = self._convert_to_internal_units(value, "Freq") self._set_property("Start Frequency", f"{value}") - @property - def stop_frequency(self) -> float: - """Last frequency for this band. - - Value should be between 1 and 100e9. - """ - val = self._get_property("Stop Frequency") - val = self._convert_from_internal_units(float(val), "Freq") - return float(val) - - @stop_frequency.setter - def stop_frequency(self, value: float | str): - value = self._convert_to_internal_units(value, "Freq") - self._set_property("Stop Frequency", f"{value}") - - @property - def channel_spacing(self) -> float: - """Spacing between channels within this band. - - Value should be between 1 and 100e9. - """ - val = self._get_property("Channel Spacing") - val = self._convert_from_internal_units(float(val), "Freq") - return float(val) - - @channel_spacing.setter - def channel_spacing(self, value: float | str): - value = self._convert_to_internal_units(value, "Freq") - self._set_property("Channel Spacing", f"{value}") - @property def clock_duty_cycle(self) -> float: """Clock signals duty cycle. @@ -418,18 +404,3 @@ def min_ptsnull(self) -> int: @min_ptsnull.setter def min_ptsnull(self, value: int): self._set_property("Min Pts/Null", f"{value}") - - @property - def delay_skew(self) -> float: - """Delay Skew of the differential signal pairs. - - Value should be greater than 0.0. - """ - val = self._get_property("Delay Skew") - val = self._convert_from_internal_units(float(val), "Time") - return float(val) - - @delay_skew.setter - def delay_skew(self, value: float | str): - value = self._convert_to_internal_units(value, "Time") - self._set_property("Delay Skew", f"{value}") diff --git a/src/ansys/aedt/core/emit_core/results/revision.py b/src/ansys/aedt/core/emit_core/results/revision.py index 9f59b5c8a55..3a5e9795218 100644 --- a/src/ansys/aedt/core/emit_core/results/revision.py +++ b/src/ansys/aedt/core/emit_core/results/revision.py @@ -31,10 +31,14 @@ from ansys.aedt.core.emit_core.nodes import generated from ansys.aedt.core.emit_core.nodes.emit_node import EmitNode from ansys.aedt.core.emit_core.nodes.emitter_node import EmitterNode +from ansys.aedt.core.emit_core.nodes.generated import Band +from ansys.aedt.core.emit_core.nodes.generated import BandFolder from ansys.aedt.core.emit_core.nodes.generated import CouplingsNode from ansys.aedt.core.emit_core.nodes.generated import EmitSceneNode +from ansys.aedt.core.emit_core.nodes.generated import RadioNode from ansys.aedt.core.emit_core.nodes.generated import ResultPlotNode from ansys.aedt.core.emit_core.nodes.generated import Waveform +from ansys.aedt.core.generic.general_methods import deprecate_argument from ansys.aedt.core.generic.general_methods import pyaedt_function_handler from ansys.aedt.core.internal.checks import min_aedt_version @@ -289,6 +293,98 @@ def get_instance_count(self, domain): engine = self.emit_project._emit_api.get_engine() return engine.get_instance_count(domain) + @pyaedt_function_handler() + def get_all_band_nodes( + self, radio: RadioNode, tx_rx_mode: TxRxMode = None, enabled_only: bool = False + ) -> list[Band]: + """ + Returns all the Bands within a Radio + + Parameters + ---------- + radio: RadioNode + The radio to iterate through. + + tx_rx_mode : :class:`emit_constants.TxRxMode`, optional + Specifies whether to get ``tx`` or ``rx`` band names. The default + is ``None``, in which case the names of all enabled bands are returned. + + enabled_only : bool + If True, only returns Band nodes that are enabled, otherwise + it returns all Band nodes. + + Returns + ------- + bands: list[Band] + List of all Band (nodes) in a radio. + """ + radio_children = radio.children + bands = [] + for radio_child in radio_children: + if isinstance(radio_child, Band): + if enabled_only and not radio_child.enabled: + # Skip disabled Bands if caller doesn't want all Bands + continue + if tx_rx_mode == TxRxMode.RX: + if "true" in radio_child._get_property("RxEnabled", True): + bands.append(radio_child) + elif tx_rx_mode == TxRxMode.TX: + if "true" in radio_child._get_property("TxEnabled", True): + bands.append(radio_child) + else: + bands.append(radio_child) + elif isinstance(radio_child, BandFolder): + folder_children = radio_child.children + for folder_child in folder_children: + if enabled_only and not folder_child.enabled: + # Skip disabled Bands if caller doesn't want all Bands + continue + if tx_rx_mode == TxRxMode.RX: + if "true" in folder_child._get_property("RxEnabled", True): + bands.append(folder_child) + elif tx_rx_mode == TxRxMode.TX: + if "true" in folder_child._get_property("TxEnabled", True): + bands.append(folder_child) + else: + bands.append(folder_child) + return bands + + @pyaedt_function_handler() + def _is_receiver(self, radio: RadioNode): + """ + Check if a given radio is a receiver. + + Parameters + ---------- + radio: RadioNode + The radio to check. + + Returns + ------- + is_rx: bool + True if the Radio can receive, False otherwise. + """ + bands = self.get_all_band_nodes(radio=radio, tx_rx_mode=TxRxMode.RX, enabled_only=True) + return len(bands) > 0 + + @pyaedt_function_handler() + def _is_transmitter(self, radio: RadioNode): + """ + Check if a given radio is a transmitter. + + Parameters + ---------- + radio: RadioNode + The radio to check. + + Returns + ------- + is_tx: bool + True if the Radio can transmit, False otherwise. + """ + bands = self.get_all_band_nodes(radio=radio, tx_rx_mode=TxRxMode.TX, enabled_only=True) + return len(bands) > 0 + @pyaedt_function_handler() def get_receiver_names(self): """ @@ -307,16 +403,20 @@ def get_receiver_names(self): -------- >>> rxs = aedtapp.results.current_revision.get_reciver_names() """ + receivers = [] if self.revision_loaded: - radios = self.emit_project._emit_api.get_radio_names(TxRxMode.RX, InterfererType.TRANSMITTERS_AND_EMITTERS) + radios = self.get_all_radio_nodes() + for radio in radios: + radio: RadioNode + if self._is_receiver(radio): + receivers.append(radio.name) else: - radios = None err_msg = self.result_mode_error() warnings.warn(err_msg) - return radios - if len(radios) == 0: + return None + if len(receivers) == 0: warnings.warn("No valid receivers in the project.") - return radios + return receivers @pyaedt_function_handler() def get_interferer_names(self, interferer_type=None): @@ -343,35 +443,55 @@ def get_interferer_names(self, interferer_type=None): >>> emitters = aedtapp.results.current_revision.get_interferer_names(InterfererType.EMITTERS) >>> both = aedtapp.results.current_revision.get_interferer_names(InterfererType.TRANSMITTERS_AND_EMITTERS) """ + transmitters = [] if interferer_type is None: interferer_type = InterfererType.TRANSMITTERS_AND_EMITTERS if self.revision_loaded: - radios = self.emit_project._emit_api.get_radio_names(TxRxMode.TX, interferer_type) + radios = [] + if interferer_type == InterfererType.TRANSMITTERS: + radios = self.get_all_radio_nodes(include_emitters=False) + elif interferer_type == InterfererType.EMITTERS: + radios = self.get_all_emitter_radios() + else: + radios = self.get_all_radio_nodes(include_emitters=True) + for radio in radios: + radio: RadioNode + if self._is_transmitter(radio): + transmitters.append(radio.name) else: - radios = None err_msg = self.result_mode_error() warnings.warn(err_msg) - return radios - if len(radios) == 0: + return None + if len(transmitters) == 0: warnings.warn("No valid radios or emitters in the project.") return None - return radios + return transmitters @pyaedt_function_handler() - def get_band_names(self, radio_name, tx_rx_mode=None): - """Get a list of all ``tx`` or ``rx`` bands (or waveforms) in a given radio/emitter. + @deprecate_argument( + arg_name="radio_name", + message=( + "The ''radio_name'' argument will be removed in future versions. Use the ''radio_node'' argument instead." + ), + ) + def get_band_names( + self, radio_node: RadioNode = None, radio_name: str = "", tx_rx_mode: TxRxMode = None + ) -> list[str]: + """Get a list of all enabled ``tx`` or ``rx`` bands (or waveforms) in a given radio/emitter. Parameters ---------- radio_name : str - Name of the radio/emitter. + The name of the radio/emitter + radio_node : RadioNode + The radio/emitter. tx_rx_mode : :class:`emit_constants.TxRxMode`, optional Specifies whether to get ``tx`` or ``rx`` band names. The default is ``None``, in which case the names of all enabled bands are returned. Returns ------- - bands:class:`list of str` + bands: list[str] List of ``tx`` or ``rx`` band/waveform names. Examples @@ -379,17 +499,24 @@ def get_band_names(self, radio_name, tx_rx_mode=None): >>> bands = aedtapp.results.current_revision.get_band_names("Bluetooth", TxRxMode.RX) >>> waveforms = aedtapp.results.current_revision.get_band_names("USB_3.x", TxRxMode.TX) """ - if tx_rx_mode is None: - tx_rx_mode = TxRxMode.BOTH + band_names = [] if self.revision_loaded: - bands = self.emit_project._emit_api.get_band_names(radio_name, tx_rx_mode) + if radio_node is None: + if radio_name == "": + raise ValueError("A radio_node or radio_name must be specified.") + radio_node = self.get_component_node(radio_name) + bands = self.get_all_band_nodes(radio=radio_node, enabled_only=True, tx_rx_mode=tx_rx_mode) + for band in bands: + band_names.append(band.name) else: - bands = None self.result_mode_error() err_msg = self.result_mode_error() warnings.warn(err_msg) - return bands - return bands + return None + if len(band_names) == 0: + warnings.warn("No valid radios or emitters in the project.") + return None + return band_names @pyaedt_function_handler() def get_active_frequencies(self, radio_name, band_name, tx_rx_mode, units=""): @@ -480,7 +607,13 @@ def n_to_1_limit(self, max_instances): engine.n_to_1_limit = max_instances @pyaedt_function_handler() - def interference_type_classification(self, domain, use_filter=False, filter_list=None): # pragma: no cover + def interference_type_classification( + self, + domain, + interferer_type: InterfererType = InterfererType.TRANSMITTERS, + use_filter: bool = False, + filter_list: list[str] = None, + ): # pragma: no cover """Classify interference type as according to inband/inband, out of band/in band, inband/out of band, and out of band/out of band. @@ -488,9 +621,11 @@ def interference_type_classification(self, domain, use_filter=False, filter_list ---------- domain : ``InteractionDomain`` object for constraining the analysis parameters. + interferer_type : TxRxMode, optional + Specifies whether to analyze all interferers, radios only, or emitters only. use_filter : bool, optional Whether filtering is being used. The default is ``False``. - filter_list : list, optional + filter_list : list[str], optional List of filter values selected by the user via the GUI if filtering is in use. Returns @@ -498,7 +633,7 @@ def interference_type_classification(self, domain, use_filter=False, filter_list power_matrix : list List of worst case interference power at Rx. all_colors : list - List of color classification of interference types. + Color classification of interference types. Examples -------- @@ -508,20 +643,27 @@ def interference_type_classification(self, domain, use_filter=False, filter_list all_colors = [] # Get project results and radios - modeRx = TxRxMode.RX - modeTx = TxRxMode.TX - tx_interferer = InterfererType().TRANSMITTERS - rx_radios = self.get_receiver_names() - tx_radios = self.get_interferer_names(tx_interferer) - radios = self.emit_project.modeler.components.get_radios() + mode_rx = TxRxMode.RX + mode_tx = TxRxMode.TX + rx_radios = self.get_all_radio_nodes(tx_rx_mode=mode_rx) + if interferer_type == InterfererType.TRANSMITTERS: + tx_radios = self.get_all_radio_nodes(tx_rx_mode=mode_tx) + elif interferer_type == InterfererType.TRANSMITTERS_AND_EMITTERS: + tx_radios = self.get_all_radio_nodes(tx_rx_mode=mode_tx, include_emitters=True) + else: + tx_radios = self.get_all_emitter_radios() + + if tx_radios is None: + raise ValueError("No interferers defined in the analysis.") + if rx_radios is None: + raise ValueError("No receivers defined in the analysis.") for tx_radio in tx_radios: rx_powers = [] rx_colors = [] for rx_radio in rx_radios: + rx_radio: RadioNode # powerAtRx is the same for all Rx bands, so just use first one - rx_bands = self.get_band_names(rx_radio, modeRx) - rx_band_objects = radios[rx_radio].bands() if tx_radio == rx_radio: # skip self-interaction rx_powers.append("N/A") @@ -529,43 +671,48 @@ def interference_type_classification(self, domain, use_filter=False, filter_list continue max_power = -200 - tx_bands = self.get_band_names(tx_radio, modeTx) + rx_band_nodes = self.get_all_band_nodes(radio=rx_radio, enabled_only=True, tx_rx_mode=mode_rx) + tx_band_nodes = self.get_all_band_nodes(radio=tx_radio, enabled_only=True, tx_rx_mode=mode_tx) - for i, rx_band in enumerate(rx_bands): + for rx_band in rx_band_nodes: # Find the highest power level at the Rx input due to each Tx Radio. # Can look at any Rx freq since susceptibility won't impact # powerAtRx, but need to look at all tx channels since coupling # can change over a transmitter's bandwidth - rx_freq = self.get_active_frequencies(rx_radio, rx_band, modeRx)[0] + rx_band: Band + rx_freq = self.get_active_frequencies(rx_radio.name, rx_band.name, mode_rx)[0] # The start and stop frequencies define the Band's extents, # while the active frequencies are a subset of the Band's frequencies # being used for this specific project as defined in the Radio's Sampling. - rx_start_freq = radios[rx_radio].band_start_frequency(rx_band_objects[i], "MHz") - rx_stop_freq = radios[rx_radio].band_stop_frequency(rx_band_objects[i], "MHz") - rx_channel_bandwidth = radios[rx_radio].band_channel_bandwidth(rx_band_objects[i], "MHz") - - for tx_band in tx_bands: - domain.set_receiver(rx_radio, rx_band) - domain.set_interferer(tx_radio, tx_band) + # Values are returned in default units, so convert to MHz + hz_to_mhz = 1e-6 + rx_start_freq = rx_band.start_frequency * hz_to_mhz + rx_stop_freq = rx_band.stop_frequency * hz_to_mhz + rx_channel_bandwidth = rx_band.channel_bandwidth * hz_to_mhz + + for tx_band in tx_band_nodes: + tx_band: Band + domain.set_receiver(rx_radio.name, rx_band.name) + domain.set_interferer(tx_radio.name, tx_band.name) interaction = self.run(domain) # check for valid interaction, this would catch any disabled radio pairs if not interaction.is_valid(): continue - domain.set_receiver(rx_radio, rx_band, rx_freq) - tx_freqs = self.get_active_frequencies(tx_radio, tx_band, modeTx) + domain.set_receiver(rx_radio.name, rx_band.name, rx_freq) + tx_freqs = self.get_active_frequencies(tx_radio.name, tx_band.name, mode_tx) for tx_freq in tx_freqs: - domain.set_interferer(tx_radio, tx_band, tx_freq) + domain.set_interferer(tx_radio.name, tx_band.name, tx_freq) instance = interaction.get_instance(domain) if not instance.has_valid_values(): # check for saturation somewhere in the chain - # set power so its flagged as strong interference + # set power=200 to flag it as strong interference if instance.get_result_warning() == "An amplifier was saturated.": max_power = 200 else: # other warnings (e.g. no path from Tx to Rx, - # no power received, error in configuration, etc) + # no power received, error in configuration, etc.) # should just be skipped continue else: @@ -618,11 +765,12 @@ def interference_type_classification(self, domain, use_filter=False, filter_list def protection_level_classification( self, domain, - global_protection_level=True, - global_levels=None, - protection_levels=None, - use_filter=False, - filter_list=None, + interferer_type: InterfererType = InterfererType.TRANSMITTERS, + global_protection_level: bool = True, + global_levels: list = None, + protection_levels: dict = None, + use_filter: bool = False, + filter_list: list[str] = None, ): # pragma: no cover """ Classify worst-case power at each Rx radio according to interference type. @@ -634,6 +782,8 @@ def protection_level_classification( ---------- domain : ``InteractionDomain`` object for constraining the analysis parameters. + interferer_type : TxRxMode, optional + Specifies whether to analyze all interferers, radios only, or emitters only. global_protection_level : bool, optional Whether to use the same protection levels for all radios. The default is ``True``. global_levels : list, optional @@ -648,9 +798,9 @@ def protection_level_classification( Returns ------- power_matrix : list - List of worst case interference according to power at each Rx radio. + Worst case interference according to power at each Rx radio. all_colors : list - List of color classification of protection level. + Color classification of protection level. Examples -------- @@ -660,12 +810,21 @@ def protection_level_classification( all_colors = [] # Get project results and radios - modeRx = TxRxMode.RX - modeTx = TxRxMode.TX + mode_rx = TxRxMode.RX + mode_tx = TxRxMode.TX mode_power = ResultType.POWER_AT_RX - tx_interferer = InterfererType().TRANSMITTERS - rx_radios = self.get_receiver_names() - tx_radios = self.get_interferer_names(tx_interferer) + rx_radios = self.get_all_radio_nodes(tx_rx_mode=mode_rx) + if interferer_type == InterfererType.TRANSMITTERS: + tx_radios = self.get_all_radio_nodes(tx_rx_mode=mode_tx) + elif interferer_type == InterfererType.TRANSMITTERS_AND_EMITTERS: + tx_radios = self.get_all_radio_nodes(tx_rx_mode=mode_tx, include_emitters=True) + else: + tx_radios = self.get_all_emitter_radios() + + if tx_radios is None: + raise ValueError("No interferers defined in the analysis.") + if rx_radios is None: + raise ValueError("No receivers defined in the analysis.") if global_protection_level and global_levels is None: damage_threshold = 30 @@ -682,12 +841,12 @@ def protection_level_classification( for rx_radio in rx_radios: # powerAtRx is the same for all Rx bands, so just # use the first one - if not (global_protection_level): - damage_threshold = protection_levels[rx_radio][0] - overload_threshold = protection_levels[rx_radio][1] - intermod_threshold = protection_levels[rx_radio][2] + if not global_protection_level: + damage_threshold = protection_levels[rx_radio.name][0] + overload_threshold = protection_levels[rx_radio.name][1] + intermod_threshold = protection_levels[rx_radio.name][2] - rx_band = self.get_band_names(rx_radio, modeRx)[0] + rx_band_name = self.get_band_names(radio_node=rx_radio, tx_rx_mode=mode_rx)[0] if tx_radio == rx_radio: # skip self-interaction rx_powers.append("N/A") @@ -695,36 +854,36 @@ def protection_level_classification( continue max_power = -200 - tx_bands = self.get_band_names(tx_radio, modeTx) + tx_band_names = self.get_band_names(radio_node=tx_radio, tx_rx_mode=mode_tx) - for tx_band in tx_bands: + for tx_band_name in tx_band_names: # Find the highest power level at the Rx input due to each Tx Radio. # Can look at any Rx freq since susceptibility won't impact # powerAtRx, but need to look at all tx channels since coupling # can change over a transmitter's bandwidth - rx_freq = self.get_active_frequencies(rx_radio, rx_band, modeRx)[0] - domain.set_receiver(rx_radio, rx_band) - domain.set_interferer(tx_radio, tx_band) + rx_freq = self.get_active_frequencies(rx_radio.name, rx_band_name, mode_rx)[0] + domain.set_receiver(rx_radio.name, rx_band_name) + domain.set_interferer(tx_radio.name, tx_band_name) interaction = self.run(domain) # check for valid interaction, this would catch any disabled radio pairs if not interaction.is_valid(): continue - domain.set_receiver(rx_radio, rx_band, rx_freq) - tx_freqs = self.get_active_frequencies(tx_radio, tx_band, modeTx) + domain.set_receiver(rx_radio.name, rx_band_name, rx_freq) + tx_freqs = self.get_active_frequencies(tx_radio.name, tx_band_name, mode_tx) power_list = [] for tx_freq in tx_freqs: - domain.set_interferer(tx_radio, tx_band, tx_freq) + domain.set_interferer(tx_radio.name, tx_band_name, tx_freq) instance = interaction.get_instance(domain) if not instance.has_valid_values(): # check for saturation somewhere in the chain - # set power so its flagged as "damage threshold" + # set power=200 to flag it as "damage threshold" if instance.get_result_warning() == "An amplifier was saturated.": max_power = 200 else: # other warnings (e.g. no path from Tx to Rx, - # no power received, error in configuration, etc) + # no power received, error in configuration, etc.) # should just be skipped continue else: @@ -921,6 +1080,72 @@ def get_all_component_nodes(self) -> list[EmitNode]: component_nodes = [self._get_node(node_id) for node_id in component_node_ids] return component_nodes + @pyaedt_function_handler + @min_aedt_version("2025.2") + def get_all_radio_nodes(self, tx_rx_mode: TxRxMode = None, include_emitters: bool = False) -> list[RadioNode]: + """Gets all Radio nodes from this revision. + + Parameters + ---------- + tx_rx_mode: TxRxMode + Specifies the type (Tx, Rx, or Both) of Radios to include. + + include_emitters: bool + Includes Emitters if True. + + Returns + ------- + radio_nodes: list + List of radio nodes. + + Examples + -------- + >>> radios = revision.get_all_radio_nodes() + """ + comp_nodes: EmitNode = self.get_all_component_nodes() + radio_nodes = [] + for comp in comp_nodes: + if include_emitters and isinstance(comp, EmitterNode): + comp: EmitterNode + radio_nodes.append(comp.get_radio()) + elif isinstance(comp, RadioNode): + if tx_rx_mode == TxRxMode.TX and self._is_transmitter(comp): + radio_nodes.append(comp) + elif tx_rx_mode == TxRxMode.RX and self._is_receiver(comp): + radio_nodes.append(comp) + elif tx_rx_mode == TxRxMode.BOTH or tx_rx_mode is None: + radio_nodes.append(comp) + + if len(radio_nodes) == 0: + warnings.warn("No valid radios in the project.") + return None + return radio_nodes + + @pyaedt_function_handler + @min_aedt_version("2025.2") + def get_all_emitter_radios(self) -> list[RadioNode]: + """Gets all Emitter Radio nodes from this revision. + + Returns + ------- + radio_nodes: list + List of radio nodes belonging to Emitters. + + Examples + -------- + >>> radios = revision.get_all_radio_nodes() + """ + comp_nodes: EmitNode = self.get_all_component_nodes() + radio_nodes = [] + for comp in comp_nodes: + if isinstance(comp, EmitterNode): + comp: EmitterNode + radio_nodes.append(comp.get_radio()) + if len(radio_nodes) == 0: + warnings.warn("No valid emitters in the project.") + return None + return radio_nodes + @pyaedt_function_handler @min_aedt_version("2025.2") def get_component_node(self, component_name) -> EmitNode: diff --git a/tests/system/emit/test_emit.py b/tests/system/emit/test_emit.py index 6de9f343ca2..48ffa7cb4d9 100644 --- a/tests/system/emit/test_emit.py +++ b/tests/system/emit/test_emit.py @@ -25,19 +25,23 @@ from enum import Enum import inspect import os +import random import sys import tempfile import types # Import required modules from typing import cast +from typing import get_args from unittest.mock import MagicMock +import warnings import pytest import ansys.aedt.core from ansys.aedt.core.generic import constants as consts from ansys.aedt.core.generic.general_methods import is_linux +from ansys.aedt.core.internal.errors import GrpcApiError from tests import TESTS_EMIT_PATH from tests.conftest import config @@ -243,9 +247,13 @@ def test_create_radio_antenna(self, emit_app): new_radio, new_antenna = emit_app.schematic.create_radio_antenna("MICS", "Radio", "Antenna") assert isinstance(new_radio, EmitNode) assert isinstance(new_antenna, EmitNode) - with pytest.raises(RuntimeError) as e: + with pytest.raises(Exception) as e: emit_app.schematic.create_radio_antenna("WrongComponent", "Radio", "Antenna") - assert "Failed to create radio of type 'WrongComponent'" in str(e.value) + assert str(e.value) == ( + "Failed to create radio of type 'WrongComponent' or antenna: " + "Failed to create component of type 'WrongComponent': " + "No component found for type 'WrongComponent'." + ) @pytest.mark.skipif(config["desktopVersion"] < "2025.2", reason="Skipped on versions earlier than 2025 R2.") def test_30_connect_components(self, emit_app): @@ -519,7 +527,7 @@ def test_revision_generation_2024(self, emit_app): assert receivers is None transmitters = rev2.get_interferer_names() assert transmitters is None - bands = rev2.get_band_names(rad5) + bands = rev2.get_band_names(radio_name=rad5) assert bands is None freqs = rev2.get_active_frequencies(rad5, "Band", TxRxMode.TX) assert freqs is None @@ -610,7 +618,7 @@ def get_sampling_node(rad_name): radios_rx = rev.get_receiver_names() assert radios_rx[0] == "Bluetooth" assert radios_rx[1] == "Bluetooth 2" - bands_rx = rev.get_band_names(radios_rx[0], mode_rx) + bands_rx = rev.get_band_names(radio_name=radios_rx[0], tx_rx_mode=mode_rx) assert bands_rx[0] == "Rx - Base Data Rate" assert bands_rx[1] == "Rx - Enhanced Data Rate" rx_frequencies = rev.get_active_frequencies(radios_rx[0], bands_rx[0], mode_rx, "MHz") @@ -627,7 +635,7 @@ def get_sampling_node(rad_name): assert rx_frequencies[1] == 2403000000.0 # Test set_sampling - bands_rx = rev.get_band_names(radios_rx[1], mode_rx) + bands_rx = rev.get_band_names(radio_name=radios_rx[1], tx_rx_mode=mode_rx) rx_frequencies = rev.get_active_frequencies(radios_rx[1], bands_rx[0], mode_rx) assert len(rx_frequencies) == 20 @@ -723,7 +731,7 @@ def enable_all_bands(revision, radio_name): assert radios == ["Radio", "Bluetooth Low Energy (LE)", "WiFi - 802.11-2012", "WiFi 6"] # Get the Bands - bands = rev.get_band_names(radios[0], TxRxMode.RX) + bands = rev.get_band_names(radio_name=radios[0], tx_rx_mode=TxRxMode.RX) assert bands == ["Band"] # Get the Freqs @@ -739,35 +747,35 @@ def enable_all_bands(revision, radio_name): assert exception_raised # Get WiFi 2012 Rx Bands - bands = rev.get_band_names(radios[2], TxRxMode.RX) + bands = rev.get_band_names(radio_name=radios[2], tx_rx_mode=TxRxMode.RX) assert len(bands) == 16 # Get WiFi 2012 Tx Bands - bands = rev.get_band_names(radios[2], TxRxMode.TX) + bands = rev.get_band_names(radio_name=radios[2], tx_rx_mode=TxRxMode.TX) assert len(bands) == 16 # Get WiFi 2012 All Bands - bands = rev.get_band_names(radios[2], TxRxMode.BOTH) + bands = rev.get_band_names(radio_name=radios[2], tx_rx_mode=TxRxMode.BOTH) assert len(bands) == 32 # Get WiFi 2012 All Bands (default args) - bands = rev.get_band_names(radios[2]) + bands = rev.get_band_names(radio_name=radios[2]) assert len(bands) == 32 # Get WiFi 6 All Bands (default args) - bands = rev.get_band_names(radios[3]) + bands = rev.get_band_names(radio_name=radios[3]) assert len(bands) == 192 # Get WiFi 6 Rx Bands - bands = rev.get_band_names(radios[3], TxRxMode.RX) + bands = rev.get_band_names(radio_name=radios[3], tx_rx_mode=TxRxMode.RX) assert len(bands) == 192 # Get WiFi 6 Tx Bands - bands = rev.get_band_names(radios[3], TxRxMode.TX) + bands = rev.get_band_names(radio_name=radios[3], tx_rx_mode=TxRxMode.TX) assert len(bands) == 192 # Get WiFi 6 All Bands - bands = rev.get_band_names(radios[3], TxRxMode.BOTH) + bands = rev.get_band_names(radio_name=radios[3], tx_rx_mode=TxRxMode.BOTH) assert len(bands) == 192 # Add an emitter @@ -987,7 +995,7 @@ def test_optimal_n_to_1_feature(self, emit_app): rev = emit_app.results.analyze() assert len(emit_app.results.revisions) == 1 radiosRX = rev.get_receiver_names() - bandsRX = rev.get_band_names(radiosRX[0], TxRxMode.RX) + bandsRX = rev.get_band_names(radio_name=radiosRX[0], tx_rx_mode=TxRxMode.RX) radiosTX = rev.get_interferer_names() domain = emit_app.results.interaction_domain() domain.set_receiver(radiosRX[0], bandsRX[0]) @@ -1049,17 +1057,17 @@ def test_availability_1_to_1(self, emit_app): assert len(emit_app.results.revisions) == 2 domain = emit_app.results.interaction_domain() radiosRX = rev2.get_receiver_names() - bandsRX = rev2.get_band_names(radiosRX[0], TxRxMode.RX) + bandsRX = rev2.get_band_names(radio_name=radiosRX[0], tx_rx_mode=TxRxMode.RX) domain.set_receiver(radiosRX[0], bandsRX[0]) radiosTX = rev2.get_interferer_names(InterfererType.TRANSMITTERS) - bandsTX = rev2.get_band_names(radiosTX[0], TxRxMode.TX) + bandsTX = rev2.get_band_names(radio_name=radiosTX[0], tx_rx_mode=TxRxMode.TX) domain.set_interferer(radiosTX[0], bandsTX[0]) assert len(emit_app.results.revisions) == 2 radiosRX = rev2.get_receiver_names() - bandsRX = rev2.get_band_names(radiosRX[0], TxRxMode.RX) + bandsRX = rev2.get_band_names(radio_name=radiosRX[0], tx_rx_mode=TxRxMode.RX) domain.set_receiver(radiosRX[0], bandsRX[0]) radiosTX = rev2.get_interferer_names(InterfererType.TRANSMITTERS) - bandsTX = rev2.get_band_names(radiosTX[0], TxRxMode.TX) + bandsTX = rev2.get_band_names(radio_name=radiosTX[0], tx_rx_mode=TxRxMode.TX) domain.set_interferer(radiosTX[0], bandsTX[0]) assert domain.receiver_name == "MD400C" assert domain.receiver_band_name == "Rx" @@ -1100,25 +1108,38 @@ def test_interference_scripts_no_filter(self, interference): rev = interference.results.analyze() # Test with no filtering - expected_interference_colors = [["white", "green", "yellow"], ["red", "green", "white"]] + expected_interference_colors = [["white", "green", "red"], ["red", "green", "white"]] expected_interference_power = [["N/A", 16.64, 56.0], [60.0, 16.64, "N/A"]] expected_protection_colors = [["white", "yellow", "yellow"], ["yellow", "yellow", "white"]] expected_protection_power = [["N/A", -20.0, -20.0], [-20.0, -20.0, "N/A"]] domain = interference.results.interaction_domain() - interference_colors = [] - interference_power_matrix = [] - protection_colors = [] - protection_power_matrix = [] - interference_colors, interference_power_matrix = rev.interference_type_classification(domain) - protection_colors, protection_power_matrix = rev.protection_level_classification( - domain, global_protection_level=True, global_levels=[30, -4, -30, -104] + with pytest.raises(ValueError) as e: + _, _ = rev.interference_type_classification(domain, InterfererType.EMITTERS) + assert str(e.value) == "No interferers defined in the analysis." + with pytest.raises(ValueError) as e: + _, _ = rev.protection_level_classification( + domain, + interferer_type=InterfererType.EMITTERS, + global_protection_level=True, + global_levels=[30, -4, -30, -104], + ) + assert str(e.value) == "No interferers defined in the analysis." + + int_colors, int_power_matrix = rev.interference_type_classification( + domain, interferer_type=InterfererType.TRANSMITTERS_AND_EMITTERS + ) + pro_colors, pro_power_matrix = rev.protection_level_classification( + domain, + interferer_type=InterfererType.TRANSMITTERS, + global_protection_level=True, + global_levels=[30, -4, -30, -104], ) - assert interference_colors == expected_interference_colors - assert interference_power_matrix == expected_interference_power - assert protection_colors == expected_protection_colors - assert protection_power_matrix == expected_protection_power + assert int_colors == expected_interference_colors + assert int_power_matrix == expected_interference_power + assert pro_colors == expected_protection_colors + assert pro_power_matrix == expected_protection_power def test_radio_protection_levels(self, interference): # Generate a revision @@ -1138,7 +1159,10 @@ def test_radio_protection_levels(self, interference): protection_colors = [] protection_power_matrix = [] protection_colors, protection_power_matrix = rev.protection_level_classification( - domain, global_protection_level=False, protection_levels=protection_levels + domain, + interferer_type=InterfererType.TRANSMITTERS, + global_protection_level=False, + protection_levels=protection_levels, ) assert protection_colors == expected_protection_colors @@ -1157,15 +1181,15 @@ def test_interference_filtering(self, interference): interference_colors = [] interference_power_matrix = [] all_interference_colors = [ - [["white", "green", "yellow"], ["orange", "green", "white"]], - [["white", "green", "yellow"], ["red", "green", "white"]], - [["white", "green", "green"], ["red", "green", "white"]], - [["white", "white", "yellow"], ["red", "white", "white"]], + [["white", "green", "orange"], ["orange", "green", "white"]], + [["white", "green", "red"], ["red", "green", "white"]], + [["white", "green", "red"], ["red", "green", "white"]], + [["white", "white", "red"], ["red", "white", "white"]], ] all_interference_power = [ - [["N/A", 16.64, 56.0], [-3.96, 16.64, "N/A"]], + [["N/A", 16.64, 2.45], [-3.96, 16.64, "N/A"]], + [["N/A", 16.64, 56.0], [60.0, 16.64, "N/A"]], [["N/A", 16.64, 56.0], [60.0, 16.64, "N/A"]], - [["N/A", 16.64, 2.45], [60.0, 16.64, "N/A"]], [["N/A", "<= -200", 56.0], [60.0, "<= -200", "N/A"]], ] interference_filters = [ @@ -1181,7 +1205,7 @@ def test_interference_filtering(self, interference): interference_filter = interference_filters[:ind] + interference_filters[ind + 1 :] interference_colors, interference_power_matrix = rev.interference_type_classification( - domain, use_filter=True, filter_list=interference_filter + domain, interferer_type=InterfererType.TRANSMITTERS, use_filter=True, filter_list=interference_filter ) assert interference_colors == expected_interference_colors @@ -1216,6 +1240,7 @@ def test_protection_filtering(self, interference): protection_colors, protection_power_matrix = rev.protection_level_classification( domain, + interferer_type=InterfererType.TRANSMITTERS_AND_EMITTERS, global_protection_level=True, global_levels=[30, -4, -30, -104], use_filter=True, @@ -1442,9 +1467,17 @@ def test_emit_nodes(self, interference): assert scene_node == scene_node + # @profile @pytest.mark.skipif(config["desktopVersion"] < "2025.2", reason="Skipped on versions earlier than 2025 R2.") - @pytest.mark.skipif(config["desktopVersion"] <= "2026.1", reason="Not stable test") - def test_all_generated_emit_node_properties(self, interference): + def test_all_generated_emit_node_properties(self, emit_app): + # change this to limit the number of iterations for each node + # if None, each node will iterate over all bool and enum combos + # to verify that every property can be set + max_inner_loop_iterations = 2 + + # used to give nodes a unique name on rename commands + self.next_int = 0 + # Define enum for result types class Result(Enum): SKIPPED = 0 @@ -1452,49 +1485,70 @@ class Result(Enum): EXCEPTION = 2 NEEDS_PARAMETERS = 3 - def get_value_for_parameter(arg_type, docstring): - value = None - - if arg_type in (int, float): - value = 0 + def parse_docstring(docstring, is_int): + if "Value should be between" in docstring: + range_part = docstring.split("Value should be between")[1] + min_val = float(range_part.split("and")[0].strip()) + max_val = float(range_part.split("and")[1].split(".")[0].strip()) + if is_int: + return round(random.randint(min_val, max_val), 3) # nosec + return round(random.uniform(min_val, max_val), 3) # nosec + elif "Value should be less than" in docstring: + max_val = float(docstring.split("Value should be less than")[1].split(".")[0].strip()) + if is_int: + return round(max_val, 3) + return max_val + elif "Value should be greater than" in docstring: + min_val = float(docstring.split("Value should be greater than")[1].split(".")[0].strip()) + if is_int: + return round(min_val, 3) + return min_val + if is_int: + return 0 + return 0.0 + + def get_value_for_parameter(parameter, docstring): + param_value = None + + # if arg_type in (int, float): + if isinstance(parameter, int) or isinstance(parameter, float): + param_value = 0 # If there's a min or max in the docstring, use it. if docstring: - if "Value should be between" in docstring: - range_part = docstring.split("Value should be between")[1] - min_val = float(range_part.split("and")[0].strip()) - max_val = float(range_part.split("and")[1].split(".")[0].strip()) - value = min_val - elif "Value should be less than" in docstring: - max_val = float(docstring.split("Value should be less than")[1].split(".")[0].strip()) - value = max_val - elif "Value should be greater than" in docstring: - min_val = float(docstring.split("Value should be greater than")[1].split(".")[0].strip()) - value = min_val - elif isinstance(arg_type, str): - value = "TestString" - elif isinstance(arg_type, bool): - value = True - elif isinstance(arg_type, type) and issubclass(arg_type, Enum): + param_value = parse_docstring(docstring, isinstance(parameter, int)) + elif isinstance(parameter, str): + param_value = f"TestString{self.next_int}" + self.next_int = self.next_int + 1 + elif isinstance(parameter, bool): + param_value = True + elif isinstance(parameter, type) and issubclass(parameter, Enum): # Type is an Enum + arg_type = type(parameter) first_enum_value = list(arg_type.__members__.values())[0] - value = first_enum_value - elif isinstance(arg_type, types.UnionType): + param_value = first_enum_value + elif isinstance(parameter, types.UnionType): # Type is a Union - possible_arg_types = arg_type.__args__ + possible_arg_types = get_args(parameter) if int in possible_arg_types or float in possible_arg_types: - value = 0 + param_value = 0 + # If there's a min or max in the docstring, use it. + if docstring: + param_value = parse_docstring(docstring, int in possible_arg_types) - return value + return param_value - def test_all_members(node, results, results_of_get_props): + def test_all_members(node, max_iterations=None): # Dynamically get list of properties and methods members = dir(node) + mem_results = {} + node_enums = {} + node_bools = {} # Initialize property map property_value_map = {} for member in members: - key = f"{type(node).__name__}.{member}" + mem_key = f"{type(node).__name__}.{member}" if member.startswith("_"): continue @@ -1505,6 +1559,12 @@ def test_all_members(node, results, results_of_get_props): if member.startswith("rename"): continue + if member.startswith("props_to_dict"): + continue + + if member.startswith("properties"): + continue + class_attr = getattr(node.__class__, member) if isinstance(class_attr, property): has_fget = class_attr.fget is not None @@ -1518,143 +1578,235 @@ def test_all_members(node, results, results_of_get_props): value_index = 0 value_count = 1 - if isinstance(arg_type, bool): - value_count = 2 + if isinstance(arg_type, type) and issubclass(arg_type, bool): + node_bools[member] = [True, False] + continue elif isinstance(arg_type, type) and issubclass(arg_type, Enum): - value_count = len(list(arg_type.__members__.values())) + node_enums[member] = list(arg_type.__members__.values()) + continue - value = { + mem_value = { "value_index": value_index, "value_count": value_count, "arg_type": arg_type, } - property_value_map[key] = value - - anything_was_set = True - while anything_was_set: - anything_was_set = False - for member in members: - key = f"{type(node).__name__}.{member}" - + property_value_map[mem_key] = mem_value + + # We want to iterate over each parameter for each enum type + # We can skip the parameter, if it's already been set successfully + # during a previous iteration. This allows us to check that each + # property is set, since only properties visible can be set. For + # example, you can only set the PSK type (4PSK, 16PSK, etc) if the + # modulation_type = PSK. + node_iterations = 0 + for enum_key in node_enums or {None: None}: + if enum_key is None: + enum_vals = [] + else: + enum_vals = node_enums[enum_key] + for enum_val in enum_vals or [None]: try: - if member.startswith("_"): - results[key] = (Result.SKIPPED, "Skipping private member") - continue - - if member.startswith("delete"): - results[key] = (Result.SKIPPED, "Skipping delete method") - continue - - if member.startswith("rename"): - results[key] = (Result.SKIPPED, "Skipping rename method") - continue - - class_attr = getattr(node.__class__, member) - if isinstance(class_attr, property): - # Member is a property + if enum_val is not None: + class_attr = getattr(node.__class__, enum_key) + class_attr.fset(node, enum_val) + except BaseException: + pass + for bool_key in node_bools or {None: None}: + if bool_key is None: + bool_vals = [] + else: + bool_vals = node_bools[bool_key] + for bool_val in bool_vals or [None]: + node_iterations = node_iterations + 1 + try: + if bool_val is not None: + class_attr = getattr(node.__class__, bool_key) + class_attr.fset(node, bool_val) + except BaseException: + pass + if max_iterations is not None and node_iterations > max_iterations: + break + + for member in members: + # skip type since it's set by the enum above + if member == "type": + continue + + # skip if member is an enum or bool (handled by loops) + if member in node_bools or member in node_enums: + continue + + mem_key = f"{type(node).__name__}.{member}" + + # skip if property successfully set + if mem_key in mem_results: + current_val = mem_results[mem_key] + if current_val[0] == Result.SKIPPED or current_val[0] == Result.VALUE: + continue - has_fget = class_attr.fget is not None - has_fset = class_attr.fset is not None + try: + if member.startswith("__"): + # ignore python built-ins to avoid cluttering results + continue - if has_fget and has_fset: - property_value_map_record = property_value_map[key] + if member.startswith("_"): + mem_results[mem_key] = (Result.SKIPPED, "Skipping private member") + continue - arg_type = property_value_map_record["arg_type"] - docstring = class_attr.fget.__doc__ + if member.startswith("props_to_dict"): + mem_results[mem_key] = (Result.SKIPPED, "Skipping global member") + continue - value = None - value_index = property_value_map_record["value_index"] - value_count = property_value_map_record["value_count"] - if isinstance(arg_type, bool): - if value_index == 0: - value = False - elif value_index == 1: - value = True - else: - # We've already used both bool values, skip. + if member.startswith("properties"): + mem_results[mem_key] = (Result.SKIPPED, "Skipping global member") continue - elif isinstance(arg_type, type) and issubclass(arg_type, Enum): - if value_index < value_count: - value = list(arg_type.__members__.values())[ - property_value_map_record["value_index"] - ] - else: - # We've already used all enum values, skip. + + if member.startswith("delete"): + mem_results[mem_key] = (Result.SKIPPED, "Skipping delete method") continue - else: - if value_index == 0: - value = get_value_for_parameter(arg_type, docstring) - else: - # We've already used a value, skip. + + if member.startswith("rename") or member.startswith("name"): + if "RadioNode" in f"{type(node).__name__}": + # skip Radio rename since it's children are already cached + continue + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + + attr = getattr(node, member) + values = [f"TestString{self.next_int}"] + self.next_int = self.next_int + 1 + result = attr(*values) + if w: + mem_results[mem_key] = (Result.VALUE, node.name) + assert ( + str(w[0].message) == "This property is deprecated in 0.21.3. " + "Use the name property instead." + ) continue - exception = None + if member.startswith("duplicate"): + with pytest.raises(NotImplementedError) as e: + attr = getattr(node, member) + values = [f"TestString{self.next_int}"] + self.next_int = self.next_int + 1 + result = attr(*values) + mem_results[mem_key] = (Result.VALUE, str(e.value)) + continue - # If value is None here, we failed to find a suitable value to call the setter with. - # Just call the getter, and put that in the results. - try: - if value is not None: - class_attr.fset(node, value) - except Exception as e: - exception = e + # TODO: Skip Pyramidal Horn params due to warning popup that freezes the test + if ( + member.startswith("mouth_width") + or member.startswith("mouth_height") + or member.startswith("waveguide_width") + or member.startswith("width_flare_half_angle") + or member.startswith("height_flare_half_angle") + ): + mem_results[mem_key] = (Result.SKIPPED, "Skipping pyramidal horn params") + continue - try: - result = class_attr.fget(node) + class_attr = getattr(node.__class__, member) + if isinstance(class_attr, property): + # Member is a property + has_fget = class_attr.fget is not None + has_fset = class_attr.fset is not None + + if has_fget and has_fset: + property_value_map_record = property_value_map[mem_key] + + arg_type = property_value_map_record["arg_type"] + docstring = class_attr.fget.__doc__ + + value_index = property_value_map_record["value_index"] + if isinstance(arg_type, type) and issubclass(arg_type, bool): + if value_index == 0: + mem_value = False + elif value_index == 1: + mem_value = True + else: + # We've already used both bool values, skip. + continue + else: + if value_index == 0: + mem_value = get_value_for_parameter(arg_type, docstring) + else: + # We've already used a value, skip. + continue + + exception = None + + # If value is None here, we failed to find a suitable value to + # call the setter with. Just call the getter, and put that in the results. + try: + if mem_value is not None: + class_attr.fset(node, mem_value) + except Exception as e: + exception = e + + try: + result = class_attr.fget(node) + except Exception as e: + exception = e + + if exception: + raise exception + + if mem_value: + assert mem_value == result + + # We successfully set the current value. Next iteration, try the next value + property_value_map_record["value_index"] += 1 + mem_results[mem_key] = (Result.VALUE, result) + elif has_fget: + result = class_attr.fget(node) + mem_results[mem_key] = (Result.VALUE, result) + else: + attr = getattr(node, member) + + if inspect.ismethod(attr) or inspect.isfunction(attr): + # Member is a function + signature = inspect.signature(attr) + + values = [] + bad_param = None + for parameter in signature.parameters: + docstring = attr.__doc__ + + mem_value = get_value_for_parameter(parameter, docstring) + if mem_value is not None: + values.append(mem_value) + else: + bad_param = parameter + break + + if len(values) == len(signature.parameters): + result = attr(*values) + mem_results[mem_key] = (Result.VALUE, result) + else: + mem_results[mem_key] = ( + Result.NEEDS_PARAMETERS, + f'Could not find valid value for parameter "{bad_param}".', + ) + else: + mem_results[mem_key] = (Result.VALUE, attr) except Exception as e: - exception = e + mem_results[mem_key] = (Result.EXCEPTION, f"{e}") + return mem_results - if exception: - raise exception - - if value: - assert value == result - - # We successfully set the current value. Next iteration, try the next value - property_value_map_record["value_index"] += 1 - anything_was_set = True - - results[key] = (Result.VALUE, result) - results_of_get_props[class_attr] = result - elif has_fget: - result = class_attr.fget(node) - results[key] = (Result.VALUE, result) - results_of_get_props[class_attr] = result - else: - attr = getattr(node, member) - - if inspect.ismethod(attr) or inspect.isfunction(attr): - # Member is a function - signature = inspect.signature(attr) + def test_nodes_from_top_level(nodes, add_untested_children=True, max_node_iterations=None): + # Test every method on every node, but add node children to list while iterating + nodes_tested = [] + node_types = [] + for node in nodes: + if type(node).__name__ not in node_types: + node_types.append(type(node).__name__) - values = [] - bad_param = None - for parameter in signature.parameters: - arg_type = type(parameter) - docstring = attr.__doc__ + results_dict = {} - value = get_value_for_parameter(arg_type, docstring) - if value is not None: - values.append(value) - else: - bad_param = parameter - break - - if len(values) == len(signature.parameters): - result = attr(*values) - results[key] = (Result.VALUE, result) - else: - results[key] = ( - Result.NEEDS_PARAMETERS, - f'Could not find valid value for parameter "{bad_param}".', - ) - else: - results[key] = (Result.VALUE, attr) - except Exception as e: - results[key] = (Result.EXCEPTION, f"{e}") - - def test_nodes_from_top_level(nodes, nodes_tested, results, results_of_get_props, add_untested_children=True): - # Test every method on every node, but add node children to list while iterating + # skip some nodes unless Developer env var set + # these nodes take the bulk of the run time + dev_only = os.getenv("EMIT_PYAEDT_LONG") + nodes_to_skip = ["Waveform", "Band", "ResultPlotNode", "EmiPlotMarketNode"] child_node_add_exceptions = {} for node in nodes: node_type = type(node).__name__ @@ -1678,49 +1830,57 @@ def test_nodes_from_top_level(nodes, nodes_tested, results, results_of_get_props # Add this node's children to the list of nodes to test try: - nodes.extend(node.children) + node_children = node.children + for node_child in node_children: + child_node_type = type(node_child).__name__ + if child_node_type not in node_types: + node_types.append(child_node_type) + nodes.append(node_child) except Exception as e: exception = e if exception: child_node_add_exceptions[node_type] = exception - test_all_members(node, results, results_of_get_props) + if max_node_iterations is None and dev_only and node_type in nodes_to_skip: + continue + node_results = test_all_members(node, max_node_iterations) + results_dict.update(node_results) + return nodes_tested, results_dict # Add some components - interference.modeler.components.create_component("Antenna", "TestAntenna") - interference.modeler.components.create_component("New Emitter", "TestEmitter") - interference.modeler.components.create_component("Amplifier", "TestAmplifier") - interference.modeler.components.create_component("Cable", "TestCable") - interference.modeler.components.create_component("Circulator", "TestCirculator") - interference.modeler.components.create_component("Divider", "TestDivider") - interference.modeler.components.create_component("Band Pass", "TestBPF") - interference.modeler.components.create_component("Band Stop", "TestBSF") - interference.modeler.components.create_component("File-based", "TestFilterByFile") - interference.modeler.components.create_component("High Pass", "TestHPF") - interference.modeler.components.create_component("Low Pass", "TestLPF") - interference.modeler.components.create_component("Tunable Band Pass", "TestTBPF") - interference.modeler.components.create_component("Tunable Band Stop", "TestTBSF") - interference.modeler.components.create_component("Isolator", "TestIsolator") - interference.modeler.components.create_component("TR Switch", "TestSwitch") - interference.modeler.components.create_component("Terminator", "TestTerminator") - interference.modeler.components.create_component("3 Port", "Test3port") + emit_app.schematic.create_radio_antenna( + radio_type="New Radio", radio_name="TestRadio", antenna_name="TestAntenna" + ) + emit_app.schematic.create_component("New Emitter", "TestEmitter") + emit_app.schematic.create_component("Amplifier", "TestAmplifier") + emit_app.schematic.create_component("Cable", "TestCable") + emit_app.schematic.create_component("Circulator", "TestCirculator") + emit_app.schematic.create_component("Divider", "TestDivider") + emit_app.schematic.create_component("Band Pass", "TestBPF") + emit_app.schematic.create_component("Isolator", "TestIsolator") + emit_app.schematic.create_component("TR Switch", "TestSwitch") + emit_app.schematic.create_component("Terminator", "TestTerminator") + emit_app.schematic.create_component("3 Port", "Test3port") # Generate and run a revision - results = interference.results - revision = interference.results.analyze() + results = emit_app.results + revision = emit_app.results.analyze() domain = results.interaction_domain() revision.run(domain) - results_dict = {} - results_of_get_props = {} - nodes_tested = [] - # Test all nodes of the current revision current_revision_all_nodes = revision.get_all_nodes() - test_nodes_from_top_level(current_revision_all_nodes, nodes_tested, results_dict, results_of_get_props) + # profiler = cProfile.Profile() + # all_nodes_tested, member_results, prop_results = profiler.runcall(test_nodes_from_top_level, + # current_revision_all_nodes) + # profiler.print_stats() + # profiler.dump_stats("profile.prof") + all_nodes_tested, member_results = test_nodes_from_top_level( + current_revision_all_nodes, True, max_inner_loop_iterations + ) # Keep the current revision, then test all nodes of the kept result # kept_result_name = interference.odesign.KeepResult() @@ -1734,14 +1894,21 @@ def test_nodes_from_top_level(nodes, nodes_tested, results, results_of_get_props # Categorize results from all node member calls results_by_type = {Result.SKIPPED: {}, Result.VALUE: {}, Result.EXCEPTION: {}, Result.NEEDS_PARAMETERS: {}} - for key, value in results_dict.items(): + for key, value in member_results.items(): results_by_type[value[0]][key] = value[1] # Verify we tested most of the generated nodes all_nodes = [node for node in generated.__all__ if ("ReadOnly" not in node)] - nodes_untested = [node for node in all_nodes if (node not in nodes_tested)] + nodes_untested = [node for node in all_nodes if (node not in all_nodes_tested)] + + if os.getenv("EMIT_PYAEDT_LONG"): + with open("results_by_type.txt", "w") as f: + for k, v in results_by_type.items(): + for kk, vv in v.items(): + f.write(f"{k}={kk}={vv}\n") + f.write(f"Nodes tested {len(all_nodes_tested)}: {all_nodes_tested}") - assert len(nodes_tested) > len(nodes_untested) + assert len(all_nodes_tested) > len(nodes_untested) @pytest.mark.skipif(config["desktopVersion"] < "2025.2", reason="Skipped on versions earlier than 2025 R2.") def test_bp_bs_filters(self, emit_app): @@ -1889,6 +2056,10 @@ def test_tables(self, emit_app): @pytest.mark.skipif(config["desktopVersion"] < "2025.2", reason="Skipped on versions earlier than 2025 R2.") def test_emitters_radios(self, emit_app): + rev = emit_app.results.analyze() + emitter_radio_nodes = rev.get_all_emitter_radios() + assert emitter_radio_nodes is None + emitter_name = "Test Emitter" emitter_node: EmitterNode = emit_app.schematic.create_component( name=emitter_name, component_type="New Emitter", library="Emitters" @@ -1898,13 +2069,16 @@ def test_emitters_radios(self, emit_app): emitter_radio: RadioNode = emitter_node.get_radio() assert isinstance(emitter_radio, RadioNode) + emitter_radio_nodes = rev.get_all_emitter_radios() + assert emitter_radio_nodes[0] == emitter_radio + emitter_ant: AntennaNode = emitter_node.get_antenna() assert isinstance(emitter_ant, AntennaNode) emitter_band: Waveform = emitter_node.get_waveforms()[0] assert emitter_band.warnings == "" - assert emitter_node.children() == emitter_node.get_waveforms() + assert emitter_node.children == emitter_node.get_waveforms() emitter_band.waveform = Waveform.WaveformOption.PRBS assert emitter_band.waveform == Waveform.WaveformOption.PRBS @@ -1914,9 +2088,46 @@ def test_emitters_radios(self, emit_app): radio_node: RadioNode = emit_app.schematic.create_component("New Radio", "Radios") + # test deprecated rename + radio_node.rename("Ansys") + assert radio_node.name == "Ansys" + + # rename the radio + radio_node.name = "Synopsys" + assert radio_node.name == "Synopsys" + + # try renaming the Emitter to an invalid value + # TODO: the next line is only needed for 25.2, which had + # some instability in maintaining the node_ids + emitter_node = rev.get_component_node(emitter_name) + with pytest.raises(GrpcApiError) as exc_info: + emitter_node.name = "Synopsys" + assert "Failed to execute gRPC AEDT command: RenameComponent" in str(exc_info.value) + + # get the radio's band band: Band = radio_node.children[0] assert isinstance(band, Band) + # rename a node + band.name = "Test" + assert band.name == "Test" + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + + band.rename("Test 2") + if w: + assert str(w[0].message) == "This property is deprecated in 0.21.3. Use the name property instead." + assert band.name == "Test 2" + + # Add a Band + radio_node.add_band() + bands: Band = radio_node.children + assert len(bands) == 3 # 2 Bands + 1 SamplingNode + bands[1].delete() + bands = radio_node.children + assert len(bands) == 2 # 1 Band + 1 SamplingNode + radio_tx_spec: TxSpectralProfNode = band.children[0] assert isinstance(radio_tx_spec, TxSpectralProfNode) @@ -1959,7 +2170,7 @@ def test_emitters_radios(self, emit_app): # Test deleting components emit_app.schematic.delete_component(radio_node.name) - # the next two lines are only needed for 25.2, which had + # TODO: the next two lines are only needed for 25.2, which had # some instability in maintaining the node_ids rev = emit_app.results.analyze() emitter_node = rev.get_component_node(emitter_name) @@ -1971,7 +2182,7 @@ def test_emitters_radios(self, emit_app): print("Invalid component can't be deleted.") @pytest.mark.skipif(config["desktopVersion"] < "2025.2", reason="Skipped on versions earlier than 2025 R2.") - def test_exceptions(self, emit_app): + def test_exceptions_bad_values(self, emit_app): radio: RadioNode = emit_app.schematic.create_component("New Radio", "Radios") try: @@ -1984,10 +2195,8 @@ def test_exceptions(self, emit_app): except Exception as e: print(f"Error: {e}") - try: - radio._get_property("Bad Prop") - except Exception as e: - print(f"Error: {e}") + val = radio._get_property("Bad Prop") + assert val == "" band: Band = radio.children[0] try: @@ -2082,7 +2291,6 @@ def test_27_components_catalog(self, emit_app): emit_app.schematic.connect_components(comp_added.name, default_antenna.name) # Delete the component - print(comp_added.name) emit_app.schematic.delete_component(comp_added.name) except Exception as e: @@ -2090,4 +2298,6 @@ def test_27_components_catalog(self, emit_app): rev = emit_app.results.analyze() comps_in_schematic = rev.get_all_component_nodes() + for comp in comps_in_schematic: + print(comp.name) assert len(comps_in_schematic) == 2 # default antenna/radio should remain