diff --git a/src/pyedb/edb.py b/src/pyedb/edb.py new file mode 100644 index 0000000000..5211fd10ab --- /dev/null +++ b/src/pyedb/edb.py @@ -0,0 +1,3545 @@ +"""This module contains the ``Edb`` class. + +This module is implicitily loaded in HFSS 3D Layout when launched. + +""" +from itertools import combinations +import os +import shutil +import sys +import tempfile +import time +import traceback +import warnings +import ansys.edb + + + +from pyaedt.application.Variables import decompose_variable_value +from pyaedt.edb_core.components import Components +from pyedb.edb_core.dotnet.database import Database +from pyaedt.edb_core.dotnet.layout import LayoutDotNet +from pyaedt.edb_core.edb_data.control_file import ControlFile +from pyaedt.edb_core.edb_data.control_file import convert_technology_file +from pyaedt.edb_core.edb_data.design_options import EdbDesignOptions +from pyaedt.edb_core.edb_data.edbvalue import EdbValue +from pyaedt.edb_core.edb_data.hfss_simulation_setup_data import HfssSimulationSetup +from pyaedt.edb_core.edb_data.ports import BundleWavePort +from pyaedt.edb_core.edb_data.ports import CoaxPort +from pyaedt.edb_core.edb_data.ports import ExcitationProbes +from pyaedt.edb_core.edb_data.ports import ExcitationSources +from pyaedt.edb_core.edb_data.ports import GapPort +from pyaedt.edb_core.edb_data.ports import WavePort +from pyaedt.edb_core.edb_data.simulation_configuration import SimulationConfiguration +from pyaedt.edb_core.edb_data.siwave_simulation_setup_data import SiwaveDCSimulationSetup +from pyaedt.edb_core.edb_data.siwave_simulation_setup_data import SiwaveSYZSimulationSetup +from pyaedt.edb_core.edb_data.sources import SourceType +from pyaedt.edb_core.edb_data.terminals import BundleTerminal +from pyaedt.edb_core.edb_data.terminals import EdgeTerminal +from pyaedt.edb_core.edb_data.terminals import PadstackInstanceTerminal +from pyaedt.edb_core.edb_data.terminals import Terminal +from pyaedt.edb_core.edb_data.variables import Variable +from pyaedt.edb_core.general import TerminalType +from pyaedt.edb_core.general import convert_py_list_to_net_list +from pyaedt.edb_core.hfss import EdbHfss +from pyaedt.edb_core.ipc2581.ipc2581 import Ipc2581 +from pyaedt.edb_core.layout import EdbLayout +from pyaedt.edb_core.materials import Materials +from pyaedt.edb_core.net_class import EdbDifferentialPairs +from pyaedt.edb_core.net_class import EdbExtendedNets +from pyaedt.edb_core.net_class import EdbNetClasses +from pyaedt.edb_core.nets import EdbNets +from pyaedt.edb_core.padstack import EdbPadstacks +from pyaedt.edb_core.siwave import EdbSiwave +from pyaedt.edb_core.stackup import Stackup +from pyaedt.generic.constants import AEDT_UNITS +from pyaedt.generic.constants import SolverType +from pyaedt.generic.general_methods import generate_unique_name +from pyaedt.generic.general_methods import get_string_version +from pyaedt.generic.general_methods import inside_desktop +from pyaedt.generic.general_methods import is_ironpython +from pyaedt.generic.general_methods import is_linux +from pyaedt.generic.general_methods import is_windows +from pyaedt.generic.general_methods import pyaedt_function_handler +from pyaedt.generic.process import SiwaveSolve +from pyaedt.modeler.geometry_operators import GeometryOperators + +if is_linux and is_ironpython: + import subprocessdotnet as subprocess +else: + import subprocess + + +class Edb(Database): + """Provides the EDB application interface. + + This module inherits all objects that belong to EDB. + + Parameters + ---------- + edbpath : str, optional + Full path to the ``aedb`` folder. The variable can also contain + the path to a layout to import. Allowed formats are BRD, MCM, + XML (IPC2581), GDS, and DXF. The default is ``None``. + For GDS import, the Ansys control file (also XML) should have the same + name as the GDS file. Only the file extension differs. + cellname : str, optional + Name of the cell to select. The default is ``None``. + isreadonly : bool, optional + Whether to open EBD in read-only mode when it is + owned by HFSS 3D Layout. The default is ``False``. + edbversion : str, int, float, optional + Version of EDB to use. The default is ``None``. + Examples of input values are ``232``, ``23.2``,``2023.2``,``"2023.2"``. + isaedtowned : bool, optional + Whether to launch EDB from HFSS 3D Layout. The + default is ``False``. + oproject : optional + Reference to the AEDT project object. + student_version : bool, optional + Whether to open the AEDT student version. The default is ``False.`` + technology_file : str, optional + Full path to technology file to be converted to xml before importing or xml. Supported by GDS format only. + + Examples + -------- + Create an ``Edb`` object and a new EDB cell. + + >>> from pyaedt import Edb + >>> app = Edb() + + Add a new variable named "s1" to the ``Edb`` instance. + + >>> app['s1'] = "0.25 mm" + >>> app['s1'].tofloat + >>> 0.00025 + >>> app['s1'].tostring + >>> "0.25mm" + + or add a new parameter with description: + + >>> app['s2'] = ["20um", "Spacing between traces"] + >>> app['s2'].value + >>> 1.9999999999999998e-05 + >>> app['s2'].description + >>> 'Spacing between traces' + + + Create an ``Edb`` object and open the specified project. + + >>> app = Edb("myfile.aedb") + + Create an ``Edb`` object from GDS and control files. + The XML control file resides in the same directory as the GDS file: (myfile.xml). + + >>> app = Edb("/path/to/file/myfile.gds") + + """ + + def __init__( + self, + edbpath=None, + cellname=None, + isreadonly=False, + edbversion=None, + isaedtowned=False, + oproject=None, + student_version=False, + use_ppe=False, + technology_file=None, + ): + edbversion = get_string_version(edbversion) + self._clean_variables() + Database.__init__(self, edbversion=edbversion, student_version=student_version) + self.standalone = True + self.oproject = oproject + self._main = sys.modules["__main__"] + self.edbversion = edbversion + self.isaedtowned = isaedtowned + self.isreadonly = isreadonly + self.cellname = cellname + if not edbpath: + if is_windows: + edbpath = os.getenv("USERPROFILE") + if not edbpath: + edbpath = os.path.expanduser("~") + edbpath = os.path.join(edbpath, "Documents", generate_unique_name("layout") + ".aedb") + else: + edbpath = os.getenv("HOME") + if not edbpath: + edbpath = os.path.expanduser("~") + edbpath = os.path.join(edbpath, generate_unique_name("layout") + ".aedb") + self.logger.info("No EDB is provided. Creating a new EDB {}.".format(edbpath)) + self.edbpath = edbpath + self.log_name = None + if edbpath: + self.log_name = os.path.join( + os.path.dirname(edbpath), "pyaedt_" + os.path.splitext(os.path.split(edbpath)[-1])[0] + ".log" + ) + + if isaedtowned and (inside_desktop or settings.remote_api or settings.remote_rpc_session): + self.open_edb_inside_aedt() + elif edbpath[-3:] in ["brd", "mcm", "gds", "xml", "dxf", "tgz"]: + self.edbpath = edbpath[:-4] + ".aedb" + working_dir = os.path.dirname(edbpath) + control_file = None + if technology_file: + if os.path.splitext(technology_file)[1] == ".xml": + control_file = technology_file + else: + control_file = convert_technology_file(technology_file, edbversion=edbversion) + self.import_layout_pcb(edbpath, working_dir, use_ppe=use_ppe, control_file=control_file) + if settings.enable_local_log_file and self.log_name: + self._logger = self._global_logger.add_file_logger(self.log_name, "Edb") + self.logger.info("EDB %s was created correctly from %s file.", self.edbpath, edbpath[-2:]) + elif edbpath.endswith("edb.def"): + self.edbpath = os.path.dirname(edbpath) + if settings.enable_local_log_file and self.log_name: + self._logger = self._global_logger.add_file_logger(self.log_name, "Edb") + self.open_edb() + elif not os.path.exists(os.path.join(self.edbpath, "edb.def")): + self.create_edb() + if settings.enable_local_log_file and self.log_name: + self._logger = self._global_logger.add_file_logger(self.log_name, "Edb") + self.logger.info("EDB %s created correctly.", self.edbpath) + elif ".aedb" in edbpath: + self.edbpath = edbpath + if settings.enable_local_log_file and self.log_name: + self._logger = self._global_logger.add_file_logger(self.log_name, "Edb") + self.open_edb() + if self.active_cell: + self.logger.info("EDB initialized.") + else: + self.logger.info("Failed to initialize DLLs.") + + def __enter__(self): + return self + + def __exit__(self, ex_type, ex_value, ex_traceback): + if ex_type: + self.edb_exception(ex_value, ex_traceback) + + @pyaedt_function_handler() + def __getitem__(self, variable_name): + """Get or Set a variable to the Edb project. The variable can be project using ``$`` prefix or + it can be a design variable, in which case the ``$`` is omitted. + + Parameters + ---------- + variable_name : str + + Returns + ------- + :class:`pyaedt.edb_core.edb_data.variables.Variable` + + """ + if self.variable_exists(variable_name)[0]: + return self.variables[variable_name] + return + + @pyaedt_function_handler() + def __setitem__(self, variable_name, variable_value): + type_error_message = "Allowed values are str, numeric or two-item list with variable description." + if type(variable_value) in [list, tuple]: # Two-item list or tuple. 2nd argument is a str description. + if len(variable_value) == 2: + if type(variable_value[1]) is str: + description = variable_value[1] if len(variable_value[1]) > 0 else None + else: + description = None + pyaedt.edb_core.general.logger.warning("Invalid type for Edb variable desciprtion is ignored.") + val = variable_value[0] + else: + raise TypeError(type_error_message) + else: + description = None + val = variable_value + if self.variable_exists(variable_name)[0]: + self.change_design_variable_value(variable_name, val) + else: + self.add_design_variable(variable_name, val) + if description: # Add the variable description if a two-item list is passed for variable_value. + self.__getitem__(variable_name).description = description + + def _clean_variables(self): + """Initialize internal variables and perform garbage collection.""" + self._materials = None + self._components = None + self._core_primitives = None + self._stackup = None + self._stackup2 = None + self._padstack = None + self._siwave = None + self._hfss = None + self._nets = None + self._setups = {} + self._layout_instance = None + self._variables = None + self._active_cell = None + self._layout = None + # time.sleep(2) + # gc.collect() + + @pyaedt_function_handler() + def _init_objects(self): + self._components = Components(self) + self._stackup = Stackup(self) + self._padstack = EdbPadstacks(self) + self._siwave = EdbSiwave(self) + self._hfss = EdbHfss(self) + self._nets = EdbNets(self) + self._core_primitives = EdbLayout(self) + self._stackup2 = self._stackup + self._materials = Materials(self) + + @property + def cell_names(self): + """Cell name container. + Returns + ------- + list of str, cell names. + """ + names = [] + for cell in self.circuit_cells: + names.append(cell.GetName()) + return names + + @property + def design_variables(self): + """Get all edb design variables. + + Returns + ------- + Dict[str, :class:`pyaedt.edb_core.edb_data.variables.Variable`] + """ + d_var = dict() + for i in self.active_cell.GetVariableServer().GetAllVariableNames(): + d_var[i] = Variable(self, i) + return d_var + + @property + def project_variables(self): + """Get all project variables. + + Returns + ------- + Dict[str, :class:`pyaedt.edb_core.edb_data.variables.Variable`] + + """ + p_var = dict() + for i in self.active_db.GetVariableServer().GetAllVariableNames(): + p_var[i] = Variable(self, i) + return p_var + + @property + def variables(self): + """Get all Edb variables. + + Returns + ------- + Dict[str, :class:`pyaedt.edb_core.edb_data.variables.Variable`] + + """ + all_vars = dict() + for i, j in self.project_variables.items(): + all_vars[i] = j + for i, j in self.design_variables.items(): + all_vars[i] = j + return all_vars + + @property + def terminals(self): + """Get terminals belonging to active layout.""" + temp = {} + for i in self.layout.terminals: + terminal_type = i.ToString().split(".")[-1] + if terminal_type == TerminalType.EdgeTerminal.name: + ter = EdgeTerminal(self, i) + elif terminal_type == TerminalType.BundleTerminal.name: + ter = BundleTerminal(self, i) + elif terminal_type == TerminalType.PadstackInstanceTerminal.name: + ter = PadstackInstanceTerminal(self, i) + else: + ter = Terminal(self, i) + temp[ter.name] = ter + + return temp + + @property + def excitations(self): + """Get all layout excitations.""" + terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) == 0] + temp = {} + for ter in terms: + if "BundleTerminal" in ter.GetType().ToString(): + temp[ter.GetName()] = BundleWavePort(self, ter) + else: + temp[ter.GetName()] = GapPort(self, ter) + return temp + + @property + def ports(self): + """Get all ports. + + Returns + ------- + Dict[str, [:class:`pyaedt.edb_core.edb_data.ports.GapPort`, + :class:`pyaedt.edb_core.edb_data.ports.WavePort`,]] + + """ + temp = [term for term in self.layout.terminals if not term.IsReferenceTerminal()] + + ports = {} + for t in temp: + t2 = Terminal(self, t) + if t2.terminal_type == TerminalType.BundleTerminal.name: + bundle_ter = BundleWavePort(self, t) + ports[bundle_ter.name] = bundle_ter + elif t2.hfss_type == "Wave": + ports[t2.name] = WavePort(self, t) + elif t2.terminal_type == TerminalType.PadstackInstanceTerminal.name: + ports[t2.name] = CoaxPort(self, t) + else: + ports[t2.name] = GapPort(self, t) + return ports + + @property + def excitations_nets(self): + """Get all excitations net names.""" + names = list(set([i.GetNet().GetName() for i in self.layout.terminals])) + names = [i for i in names if i] + return names + + @property + def sources(self): + """Get all layout sources.""" + terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [3, 4, 7]] + return {ter.GetName(): ExcitationSources(self, ter) for ter in terms} + + @property + def probes(self): + """Get all layout sources.""" + terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [8]] + return {ter.GetName(): ExcitationProbes(self, ter) for ter in terms} + + @pyaedt_function_handler() + def open_edb(self): + """Open EDB. + + Returns + ------- + + """ + # self.logger.info("EDB Path is %s", self.edbpath) + # self.logger.info("EDB Version is %s", self.edbversion) + # if self.edbversion > "2023.1": + # self.standalone = False + + self.run_as_standalone(self.standalone) + + # self.logger.info("EDB Standalone %s", self.standalone) + try: + self.open(self.edbpath, self.isreadonly) + except Exception as e: + self.logger.error("Builder is not Initialized.") + if not self.active_db: + self.logger.warning("Error Opening db") + self._active_cell = None + return None + self.logger.info("Database {} Opened in {}".format(os.path.split(self.edbpath)[-1], self.edbversion)) + + self._active_cell = None + if self.cellname: + for cell in list(self.top_circuit_cells): + if cell.GetName() == self.cellname: + self._active_cell = cell + # if self._active_cell is still None, set it to default cell + if self._active_cell is None: + self._active_cell = list(self.top_circuit_cells)[0] + self.logger.info("Cell %s Opened", self._active_cell.GetName()) + if self._active_cell: + self._init_objects() + self.logger.info("Builder was initialized.") + else: + self.logger.error("Builder was not initialized.") + + return True + + @pyaedt_function_handler() + def open_edb_inside_aedt(self): + """Open EDB inside of AEDT. + + Returns + ------- + + """ + self.logger.info("Opening EDB from HDL") + self.run_as_standalone(False) + if self.oproject.GetEDBHandle(): + self.attach(self.oproject.GetEDBHandle()) + if not self.active_db: + self.logger.warning("Error getting the database.") + self._active_cell = None + return None + self._active_cell = self.edb_api.cell.cell.FindByName( + self.active_db, self.edb_api.cell._cell.CellType.CircuitCell, self.cellname + ) + if self._active_cell is None: + self._active_cell = list(self.top_circuit_cells)[0] + if self._active_cell: + if not os.path.exists(self.edbpath): + os.makedirs(self.edbpath) + self._init_objects() + return True + else: + return None + else: + self._active_cell = None + return None + + @pyaedt_function_handler() + def create_edb(self): + """Create EDB.""" + # if self.edbversion > "2023.1": + # self.standalone = False + + self.run_as_standalone(self.standalone) + self.create(self.edbpath) + if not self.active_db: + self.logger.warning("Error creating the database.") + self._active_cell = None + return None + if not self.cellname: + self.cellname = generate_unique_name("Cell") + self._active_cell = self.edb_api.cell.create( + self.active_db, self.edb_api.cell.CellType.CircuitCell, self.cellname + ) + if self._active_cell: + self._init_objects() + return True + return None + + @pyaedt_function_handler() + def import_layout_pcb(self, input_file, working_dir, anstranslator_full_path="", use_ppe=False, control_file=None): + """Import a board file and generate an ``edb.def`` file in the working directory. + + This function supports all AEDT formats, including DXF, GDS, SML (IPC2581), BRD, MCM and TGZ. + + Parameters + ---------- + input_file : str + Full path to the board file. + working_dir : str + Directory in which to create the ``aedb`` folder. The name given to the AEDB file + is the same as the name of the board file. + anstranslator_full_path : str, optional + Full path to the Ansys translator. The default is ``""``. + use_ppe : bool + Whether to use the PPE License. The default is ``False``. + control_file : str, optional + Path to the XML file. The default is ``None``, in which case an attempt is made to find + the XML file in the same directory as the board file. To succeed, the XML file and board file + must have the same name. Only the extension differs. + + Returns + ------- + str + Full path to the AEDB file. + """ + self._components = None + self._core_primitives = None + self._stackup = None + self._padstack = None + self._siwave = None + self._hfss = None + self._nets = None + aedb_name = os.path.splitext(os.path.basename(input_file))[0] + ".aedb" + if anstranslator_full_path and os.path.exists(anstranslator_full_path): + command = anstranslator_full_path + else: + command = os.path.join(self.base_path, "anstranslator") + if is_windows: + command += ".exe" + + if not working_dir: + working_dir = os.path.dirname(input_file) + cmd_translator = [ + command, + input_file, + os.path.join(working_dir, aedb_name), + "-l={}".format(os.path.join(working_dir, "Translator.log")), + ] + if not use_ppe: + cmd_translator.append("-ppe=false") + if control_file and input_file[-3:] not in ["brd", "mcm"]: + if is_linux: + cmd_translator.append("-c={}".format(control_file)) + else: + cmd_translator.append('-c="{}"'.format(control_file)) + p = subprocess.Popen(cmd_translator) + p.wait() + if not os.path.exists(os.path.join(working_dir, aedb_name)): + self.logger.error("Translator failed to translate.") + return False + else: + self.logger.info("Translation correctly completed") + self.edbpath = os.path.join(working_dir, aedb_name) + return self.open_edb() + + @pyaedt_function_handler() + def export_to_ipc2581(self, ipc_path=None, units="MILLIMETER"): + """Create an XML IPC2581 file from the active EDB. + + .. note:: + The method works only in CPython because of some limitations on Ironpython in XML parsing and + because it's time-consuming. + This method is still being tested and may need further debugging. + Any feedback is welcome. Backdrills and custom pads are not supported yet. + + Parameters + ---------- + ipc_path : str, optional + Path to the XML IPC2581 file. The default is ``None``, in which case + an attempt is made to find the XML IPC2581 file in the same directory + as the active EDB. To succeed, the XML IPC2581 file and the active + EDT must have the same name. Only the extension differs. + units : str, optional + Units of the XML IPC2581 file. Options are ``"millimeter"``, + ``"inch"``, and ``"micron"``. The default is ``"millimeter"``. + + Returns + ------- + bool + ``True`` if successful, ``False`` if failed. + """ + if is_ironpython: # pragma no cover + self.logger.error("This method is not supported in Ironpython") + return False + if units.lower() not in ["millimeter", "inch", "micron"]: # pragma no cover + self.logger.warning("The wrong unit is entered. Setting to the default, millimeter.") + units = "millimeter" + + if not ipc_path: + ipc_path = self.edbpath[:-4] + "xml" + self.logger.info("Export IPC 2581 is starting. This operation can take a while.") + start = time.time() + ipc = Ipc2581(self, units) + ipc.load_ipc_model() + ipc.file_path = ipc_path + result = ipc.write_xml() + + if result: # pragma no cover + self.logger.info_timer("Export IPC 2581 completed.", start) + self.logger.info("File saved as %s", ipc_path) + return ipc_path + self.logger.info("Error exporting IPC 2581.") + return False + + def edb_exception(self, ex_value, tb_data): + """Write the trace stack to AEDT when a Python error occurs. + + Parameters + ---------- + ex_value : + + tb_data : + + + Returns + ------- + + """ + tb_trace = traceback.format_tb(tb_data) + tblist = tb_trace[0].split("\n") + self.logger.error(str(ex_value)) + for el in tblist: + self.logger.error(el) + + @property + def active_db(self): + """Database object.""" + return self.db + + @property + def active_cell(self): + """Active cell.""" + return self._active_cell + + @property + def core_components(self): # pragma: no cover + """Edb Components methods and properties. + + .. deprecated:: 0.6.62 + Use new property :func:`components` instead. + + Returns + ------- + Instance of :class:`pyaedt.edb_core.Components.Components` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> comp = self.edbapp.components.get_component_by_name("J1") + """ + warnings.warn("Use new property :func:`components` instead.", DeprecationWarning) + return self.components + + @property + def components(self): + """Edb Components methods and properties. + + Returns + ------- + :class:`pyaedt.edb_core.components.Components` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> comp = self.edbapp.components.get_component_by_name("J1") + """ + if not self._components and self.active_db: + self._components = Components(self) + return self._components + + @property + def core_stackup(self): + """Core stackup. + + .. deprecated:: 0.6.5 + There is no need to use the ``core_stackup`` property anymore. + You can instantiate a new ``stackup`` class directly from the ``Edb`` class. + """ + mess = "`core_stackup` is deprecated.\n" + mess += " Use `app.stackup` directly to instantiate new stackup methods." + warnings.warn(mess, DeprecationWarning) + if not self._stackup and self.active_db: + self._stackup = Stackup(self) + return self._stackup + + @property + def design_options(self): + """Edb Design Settings and Options. + + Returns + ------- + Instance of :class:`pyaedt.edb_core.edb_data.design_options.EdbDesignOptions` + """ + return EdbDesignOptions(self.active_cell) + + @property + def stackup(self): + """Stackup manager. + + Returns + ------- + Instance of :class: 'pyaedt.edb_core.Stackup` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.stackup.layers["TOP"].thickness = 4e-5 + >>> edbapp.stackup.layers["TOP"].thickness == 4e-05 + >>> edbapp.stackup.add_layer("Diel", "GND", layer_type="dielectric", thickness="0.1mm", material="FR4_epoxy") + """ + if not self._stackup2 and self.active_db: + self._stackup2 = Stackup(self) + return self._stackup2 + + @property + def materials(self): + """Material Database. + + Returns + ------- + Instance of :class: `pyaedt.edb_core.Materials` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.materials["FR4_epoxy"].conductivity = 1 + >>> edbapp.materials.add_debye_material("My_Debye2", 5, 3, 0.02, 0.05, 1e5, 1e9) + >>> edbapp.materials.add_djordjevicsarkar_material("MyDjord2", 3.3, 0.02, 3.3) + """ + + if not self._materials and self.active_db: + self._materials = Materials(self) + return self._materials + + @property + def core_padstack(self): # pragma: no cover + """Core padstack. + + + .. deprecated:: 0.6.62 + Use new property :func:`padstacks` instead. + + Returns + ------- + Instance of :class: `pyaedt.edb_core.padstack.EdbPadstack` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> p = edbapp.padstacks.create(padstackname="myVia_bullet", antipad_shape="Bullet") + >>> edbapp.padstacks.get_pad_parameters( + >>> ... p, "TOP", self.edbapp.padstacks.pad_type.RegularPad + >>> ... ) + """ + + warnings.warn("Use new property :func:`padstacks` instead.", DeprecationWarning) + return self.padstacks + + @property + def padstacks(self): + """Core padstack. + + + Returns + ------- + Instance of :class: `pyaedt.edb_core.padstack.EdbPadstack` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> p = edbapp.padstacks.create(padstackname="myVia_bullet", antipad_shape="Bullet") + >>> edbapp.padstacks.get_pad_parameters( + >>> ... p, "TOP", self.edbapp.padstacks.pad_type.RegularPad + >>> ... ) + """ + + if not self._padstack and self.active_db: + self._padstack = EdbPadstacks(self) + return self._padstack + + @property + def core_siwave(self): # pragma: no cover + """Core SIWave methods and properties. + + .. deprecated:: 0.6.62 + Use new property :func:`siwave` instead. + + Returns + ------- + Instance of :class: `pyaedt.edb_core.siwave.EdbSiwave` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> p2 = edbapp.siwave.create_circuit_port_on_net("U2A5", "V3P3_S0", "U2A5", "GND", 50, "test") + """ + warnings.warn("Use new property :func:`siwave` instead.", DeprecationWarning) + return self.siwave + + @property + def siwave(self): + """Core SIWave methods and properties. + + Returns + ------- + Instance of :class: `pyaedt.edb_core.siwave.EdbSiwave` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> p2 = edbapp.siwave.create_circuit_port_on_net("U2A5", "V3P3_S0", "U2A5", "GND", 50, "test") + """ + if not self._siwave and self.active_db: + self._siwave = EdbSiwave(self) + return self._siwave + + @property + def core_hfss(self): # pragma: no cover + """Core HFSS methods and properties. + + .. deprecated:: 0.6.62 + Use new property :func:`hfss` instead. + + Returns + ------- + Instance of :class:`pyaedt.edb_core.hfss.EdbHfss` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.hfss.configure_hfss_analysis_setup(sim_config) + """ + warnings.warn("Use new property :func:`hfss` instead.", DeprecationWarning) + return self.hfss + + @property + def hfss(self): + """Core HFSS methods and properties. + + Returns + ------- + :class:`pyaedt.edb_core.hfss.EdbHfss` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.hfss.configure_hfss_analysis_setup(sim_config) + """ + if not self._hfss and self.active_db: + self._hfss = EdbHfss(self) + return self._hfss + + @property + def core_nets(self): # pragma: no cover + """Core nets. + + .. deprecated:: 0.6.62 + Use new property :func:`nets` instead. + + Returns + ------- + :class:`pyaedt.edb_core.nets.EdbNets` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.nets.find_or_create_net("GND") + >>> edbapp.nets.find_and_fix_disjoint_nets("GND", keep_only_main_net=True) + """ + warnings.warn("Use new property :func:`nets` instead.", DeprecationWarning) + return self.nets + + @property + def nets(self): + """Core nets. + + Returns + ------- + :class:`pyaedt.edb_core.nets.EdbNets` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.nets.find_or_create_net("GND") + >>> edbapp.nets.find_and_fix_disjoint_nets("GND", keep_only_main_net=True) + """ + + if not self._nets and self.active_db: + self._nets = EdbNets(self) + return self._nets + + @property + def net_classes(self): + """Get all net classes. + + Returns + ------- + :class:`pyaedt.edb_core.nets.EdbNetClasses` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.net_classes + """ + + if self.active_db: + return EdbNetClasses(self) + + @property + def extended_nets(self): + """Get all extended nets. + + Returns + ------- + :class:`pyaedt.edb_core.nets.EdbExtendedNets` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.extended_nets + """ + + if self.active_db: + return EdbExtendedNets(self) + + @property + def differential_pairs(self): + """Get all differential pairs. + + Returns + ------- + :class:`pyaedt.edb_core.nets.EdbDifferentialPairs` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp.differential_pairs + """ + if self.active_db: + return EdbDifferentialPairs(self) + else: # pragma: no cover + return + + @property + def core_primitives(self): # pragma: no cover + """Core primitives. + + .. deprecated:: 0.6.62 + Use new property :func:`modeler` instead. + + Returns + ------- + Instance of :class: `pyaedt.edb_core.layout.EdbLayout` + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> top_prims = edbapp.modeler.primitives_by_layer["TOP"] + """ + warnings.warn("Use new property :func:`modeler` instead.", DeprecationWarning) + return self.modeler + + @property + def modeler(self): + """Core primitives modeler. + + Returns + ------- + Instance of :class: `pyaedt.edb_core.layout.EdbLayout` + + Examples + -------- + >>> edbapp = pyedb.Edb("myproject.aedb") + >>> top_prims = edbapp.modeler.primitives_by_layer["TOP"] + """ + if not self._core_primitives and self.active_db: + self._core_primitives = EdbLayout(self) + return self._core_primitives + + @property + def layout(self): + """Layout object. + + Returns + ------- + :class:`pyaedt.edb_core.dotnet.layout.Layout` + """ + return LayoutDotNet(self) + + @property + def active_layout(self): + """Active layout. + + Returns + ------- + Instance of EDB API Layout Class. + """ + return self.layout._layout + + @property + def layout_instance(self): + """Edb Layout Instance.""" + return self.layout.layout_instance + + @property + def pins(self): + """EDBPadstackInstance of Component. + + .. deprecated:: 0.6.62 + Use new method :func:`edb.padstacks.pins` instead. + + Returns + ------- + dic[str, :class:`pyaedt.edb_core.edb_data.definitions.EDBPadstackInstance`] + Dictionary of EDBPadstackInstance Components. + + + Examples + -------- + >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> pin_net_name = edbapp.pins[424968329].netname + """ + warnings.warn("Use new method :func:`edb.padstacks.pins` instead.", DeprecationWarning) + return self.padstacks.pins + + class Boundaries: + """Boundaries Enumerator. + + Returns + ------- + int + """ + + (Port, Pec, RLC, CurrentSource, VoltageSource, NexximGround, NexximPort, DcTerminal, VoltageProbe) = range(0, 9) + + @pyaedt_function_handler() + def edb_value(self, val): + """Convert a value to an EDB value. Value can be a string, float or integer. Mainly used in internal calls. + + Parameters + ---------- + val : str, float, int + + + Returns + ------- + Instance of `Edb.Utility.Value` + + """ + return self.edb_api.utility.value(val) + + @pyaedt_function_handler() + def point_3d(self, x, y, z=0.0): + """Compute the Edb 3d Point Data. + + Parameters + ---------- + x : float, int or str + X value. + y : float, int or str + Y value. + z : float, int or str, optional + Z value. + + Returns + ------- + ``Geometry.Point3DData``. + """ + return self.edb_api.geometry.point3d_data(x, y, z) + + @pyaedt_function_handler() + def point_data(self, x, y=None): + """Compute the Edb Point Data. + + Parameters + ---------- + x : float, int or str + X value. + y : float, int or str, optional + Y value. + + + Returns + ------- + ``Geometry.PointData``. + """ + if y is None: + return self.edb_api.geometry.point_data(x) + else: + return self.edb_api.geometry.point_data(x, y) + + @pyaedt_function_handler() + def _is_file_existing_and_released(self, filename): + if os.path.exists(filename): + try: + os.rename(filename, filename + "_") + os.rename(filename + "_", filename) + return True + except OSError as e: + return False + else: + return False + + @pyaedt_function_handler() + def _is_file_existing(self, filename): + if os.path.exists(filename): + return True + else: + return False + + @pyaedt_function_handler() + def _wait_for_file_release(self, timeout=30, file_to_release=None): + if not file_to_release: + file_to_release = os.path.join(self.edbpath) + tstart = time.time() + while True: + if self._is_file_existing_and_released(file_to_release): + return True + elif time.time() - tstart > timeout: + return False + else: + time.sleep(0.250) + + @pyaedt_function_handler() + def _wait_for_file_exists(self, timeout=30, file_to_release=None, wait_count=4): + if not file_to_release: + file_to_release = os.path.join(self.edbpath) + tstart = time.time() + times = 0 + while True: + if self._is_file_existing(file_to_release): + # print 'File is released' + times += 1 + if times == wait_count: + return True + elif time.time() - tstart > timeout: + # print 'Timeout reached' + return False + else: + times = 0 + time.sleep(0.250) + + @pyaedt_function_handler() + def close_edb(self): + """Close EDB and cleanup variables. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + self.close() + if self.log_name and settings.enable_local_log_file: + self._global_logger.remove_file_logger(os.path.splitext(os.path.split(self.log_name)[-1])[0]) + self._logger = self._global_logger + start_time = time.time() + self._wait_for_file_release() + elapsed_time = time.time() - start_time + self.logger.info("EDB file release time: {0:.2f}ms".format(elapsed_time * 1000.0)) + self._clean_variables() + return True + + @pyaedt_function_handler() + def save_edb(self): + """Save the EDB file. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + self.save() + start_time = time.time() + self._wait_for_file_release() + elapsed_time = time.time() - start_time + self.logger.info("EDB file save time: {0:.2f}ms".format(elapsed_time * 1000.0)) + return True + + @pyaedt_function_handler() + def save_edb_as(self, fname): + """Save the EDB file as another file. + + Parameters + ---------- + fname : str + Name of the new file to save to. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + self.save_as(fname) + start_time = time.time() + self._wait_for_file_release() + elapsed_time = time.time() - start_time + self.logger.info("EDB file save time: {0:.2f}ms".format(elapsed_time * 1000.0)) + self.edbpath = self.directory + if self.log_name: + self._global_logger.remove_file_logger(os.path.splitext(os.path.split(self.log_name)[-1])[0]) + self._logger = self._global_logger + + self.log_name = os.path.join( + os.path.dirname(fname), "pyaedt_" + os.path.splitext(os.path.split(fname)[-1])[0] + ".log" + ) + if settings.enable_local_log_file: + self._logger = self._global_logger.add_file_logger(self.log_name, "Edb") + return True + + @pyaedt_function_handler() + def execute(self, func): + """Execute a function. + + Parameters + ---------- + func : str + Function to execute. + + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + return self.edb_api.utility.utility.Command.Execute(func) + + @pyaedt_function_handler() + def import_cadence_file(self, inputBrd, WorkDir=None, anstranslator_full_path="", use_ppe=False): + """Import a board file and generate an ``edb.def`` file in the working directory. + + Parameters + ---------- + inputBrd : str + Full path to the board file. + WorkDir : str, optional + Directory in which to create the ``aedb`` folder. The default value is ``None``, + in which case the AEDB file is given the same name as the board file. Only + the extension differs. + anstranslator_full_path : str, optional + Full path to the Ansys translator. + use_ppe : bool, optional + Whether to use the PPE License. The default is ``False``. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + if self.import_layout_pcb( + inputBrd, working_dir=WorkDir, anstranslator_full_path=anstranslator_full_path, use_ppe=use_ppe + ): + return True + else: + return False + + @pyaedt_function_handler() + def import_gds_file( + self, + inputGDS, + WorkDir=None, + anstranslator_full_path="", + use_ppe=False, + control_file=None, + tech_file=None, + map_file=None, + ): + """Import a GDS file and generate an ``edb.def`` file in the working directory. + + ..note:: + `ANSYSLMD_LICENSE_FILE` is needed to run the translator. + + Parameters + ---------- + inputGDS : str + Full path to the GDS file. + WorkDir : str, optional + Directory in which to create the ``aedb`` folder. The default value is ``None``, + in which case the AEDB file is given the same name as the GDS file. Only the extension + differs. + anstranslator_full_path : str, optional + Full path to the Ansys translator. + use_ppe : bool, optional + Whether to use the PPE License. The default is ``False``. + control_file : str, optional + Path to the XML file. The default is ``None``, in which case an attempt is made to find + the XML file in the same directory as the GDS file. To succeed, the XML file and GDS file must + have the same name. Only the extension differs. + tech_file : str, optional + Technology file. It uses Helic to convert tech file to xml and then imports the gds. Works on Linux only. + map_file : str, optional + Layer map file. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + if tech_file or map_file: + control_file_temp = os.path.join(tempfile.gettempdir(), os.path.split(inputGDS)[-1][:-3] + "xml") + control_file = ControlFile(xml_input=control_file, tecnhology=tech_file, layer_map=map_file).write_xml( + control_file_temp + ) + elif tech_file: + self.logger.error("Technology files are supported only in Linux. Use control file instead.") + return False + if self.import_layout_pcb( + inputGDS, + working_dir=WorkDir, + anstranslator_full_path=anstranslator_full_path, + use_ppe=use_ppe, + control_file=control_file, + ): + return True + else: + return False + + @pyaedt_function_handler() + def _create_extent( + self, + net_signals, + extent_type, + expansion_size, + use_round_corner, + use_pyaedt_extent=False, + smart_cut=False, + reference_list=[], + include_pingroups=True, + ): + if extent_type in ["Conforming", self.edb_api.geometry.extent_type.Conforming, 1]: + if use_pyaedt_extent: + _poly = self._create_conformal( + net_signals, + expansion_size, + 1e-12, + use_round_corner, + expansion_size, + smart_cut, + reference_list, + include_pingroups, + ) + else: + _poly = self.layout.expanded_extent( + net_signals, + self.edb_api.geometry.extent_type.Conforming, + expansion_size, + False, + use_round_corner, + 1, + ) + elif extent_type in ["Bounding", self.edb_api.geometry.extent_type.BoundingBox, 0]: + _poly = self.layout.expanded_extent( + net_signals, self.edb_api.geometry.extent_type.BoundingBox, expansion_size, False, use_round_corner, 1 + ) + else: + if use_pyaedt_extent: + _poly = self._create_convex_hull( + net_signals, + expansion_size, + 1e-12, + use_round_corner, + expansion_size, + smart_cut, + reference_list, + include_pingroups, + ) + else: + _poly = self.layout.expanded_extent( + net_signals, + self.edb_api.geometry.extent_type.Conforming, + expansion_size, + False, + use_round_corner, + 1, + ) + _poly_list = convert_py_list_to_net_list([_poly]) + _poly = self.edb_api.geometry.polygon_data.get_convex_hull_of_polygons(_poly_list) + return _poly + + @pyaedt_function_handler() + def _create_conformal( + self, + net_signals, + expansion_size, + tolerance, + round_corner, + round_extension, + smart_cutout=False, + reference_list=[], + include_pingroups=True, + ): + names = [] + _polys = [] + for net in net_signals: + names.append(net.GetName()) + for prim in self.modeler.primitives: + if prim is not None and prim.net_name in names: + obj_data = prim.primitive_object.GetPolygonData().Expand( + expansion_size, tolerance, round_corner, round_extension + ) + if obj_data: + _polys.extend(list(obj_data)) + if smart_cutout: + _polys.extend(self._smart_cut(net_signals, reference_list, include_pingroups)) + _poly_unite = self.edb_api.geometry.polygon_data.unite(_polys) + if len(_poly_unite) == 1: + return _poly_unite[0] + else: + areas = [i.Area() for i in _poly_unite] + return _poly_unite[areas.index(max(areas))] + + @pyaedt_function_handler() + def _smart_cut(self, net_signals, reference_list=[], include_pingroups=True): + _polys = [] + terms = [term for term in self.layout.terminals if int(term.GetBoundaryType()) in [0, 3, 4, 7, 8]] + locations = [] + for term in terms: + if term.GetTerminalType().ToString() == "PadstackInstanceTerminal": + if term.GetParameters()[1].GetNet().GetName() in reference_list: + locations.append(self.padstacks.instances[term.GetParameters()[1].GetId()].position) + elif term.GetTerminalType().ToString() == "PointTerminal" and term.GetNet().GetName() in reference_list: + pd = term.GetParameters()[1] + locations.append([pd.X.ToDouble(), pd.Y.ToDouble()]) + if include_pingroups: + for reference in reference_list: + for pin in self.nets.nets[reference].padstack_instances: + if pin.pingroups: + locations.append(pin.position) + for point in locations: + pointA = self.edb_api.geometry.point_data( + self.edb_value(point[0] - 1e-12), self.edb_value(point[1] - 1e-12) + ) + pointB = self.edb_api.geometry.point_data( + self.edb_value(point[0] + 1e-12), self.edb_value(point[1] + 1e-12) + ) + + points = Tuple[self.edb_api.geometry.geometry.PointData, self.edb_api.geometry.geometry.PointData]( + pointA, pointB + ) + _polys.append(self.edb_api.geometry.polygon_data.create_from_bbox(points)) + for cname, c in self.components.instances.items(): + if ( + set(net_signals).intersection(c.nets) + and c.is_enabled + and c.model_type in ["SParameterModel", "SpiceModel", "NetlistModel"] + ): + for pin in c.pins: + locations.append(pin.position) + return _polys + + @pyaedt_function_handler() + def _create_convex_hull( + self, + net_signals, + expansion_size, + tolerance, + round_corner, + round_extension, + smart_cut=False, + reference_list=[], + include_pingroups=True, + ): + names = [] + _polys = [] + for net in net_signals: + names.append(net.GetName()) + for prim in self.modeler.primitives: + if prim is not None and prim.net_name in names: + _polys.append(prim.primitive_object.GetPolygonData()) + if smart_cut: + _polys.extend(self._smart_cut(net_signals, reference_list, include_pingroups)) + _poly = self.edb_api.geometry.polygon_data.get_convex_hull_of_polygons(convert_py_list_to_net_list(_polys)) + _poly = _poly.Expand(expansion_size, tolerance, round_corner, round_extension)[0] + return _poly + + @pyaedt_function_handler() + def cutout( + self, + signal_list=None, + reference_list=None, + extent_type="ConvexHull", + expansion_size=0.002, + use_round_corner=False, + output_aedb_path=None, + open_cutout_at_end=True, + use_pyaedt_cutout=True, + number_of_threads=4, + use_pyaedt_extent_computing=True, + extent_defeature=0, + remove_single_pin_components=False, + custom_extent=None, + custom_extent_units="mm", + include_partial_instances=False, + keep_voids=True, + check_terminals=False, + include_pingroups=False, + expansion_factor=0, + maximum_iterations=10, + preserve_components_with_model=False, + simple_pad_check=True, + ): + """Create a cutout using an approach entirely based on PyAEDT. + This method replaces all legacy cutout methods in PyAEDT. + It does in sequence: + - delete all nets not in list, + - create a extent of the nets, + - check and delete all vias not in the extent, + - check and delete all the primitives not in extent, + - check and intersect all the primitives that intersect the extent. + + Parameters + ---------- + signal_list : list + List of signal strings. + reference_list : list, optional + List of references to add. The default is ``["GND"]``. + extent_type : str, optional + Type of the extension. Options are ``"Conforming"``, ``"ConvexHull"``, and + ``"Bounding"``. The default is ``"Conforming"``. + expansion_size : float, str, optional + Expansion size ratio in meters. The default is ``0.002``. + use_round_corner : bool, optional + Whether to use round corners. The default is ``False``. + output_aedb_path : str, optional + Full path and name for the new AEDB file. If None, then current aedb will be cutout. + open_cutout_at_end : bool, optional + Whether to open the cutout at the end. The default is ``True``. + use_pyaedt_cutout : bool, optional + Whether to use new PyAEDT cutout method or EDB API method. + New method is faster than native API method since it benefits of multithread. + number_of_threads : int, optional + Number of thread to use. Default is 4. Valid only if ``use_pyaedt_cutout`` is set to ``True``. + use_pyaedt_extent_computing : bool, optional + Whether to use pyaedt extent computing (experimental) or EDB API. + extent_defeature : float, optional + Defeature the cutout before applying it to produce simpler geometry for mesh (Experimental). + It applies only to Conforming bounding box. Default value is ``0`` which disable it. + remove_single_pin_components : bool, optional + Remove all Single Pin RLC after the cutout is completed. Default is `False`. + custom_extent : list + Points list defining the cutout shape. This setting will override `extent_type` field. + custom_extent_units : str + Units of the point list. The default is ``"mm"``. Valid only if `custom_extend` is provided. + include_partial_instances : bool, optional + Whether to include padstack instances that have bounding boxes intersecting with point list polygons. + This operation may slow down the cutout export.Valid only if `custom_extend` and + `use_pyaedt_cutout` is provided. + keep_voids : bool + Boolean used for keep or not the voids intersecting the polygon used for clipping the layout. + Default value is ``True``, ``False`` will remove the voids.Valid only if `custom_extend` is provided. + check_terminals : bool, optional + Whether to check for all reference terminals and increase extent to include them into the cutout. + This applies to components which have a model (spice, touchstone or netlist) associated. + include_pingroups : bool, optional + Whether to check for all pingroups terminals and increase extent to include them into the cutout. + It requires ``check_terminals``. + expansion_factor : int, optional + The method computes a float representing the largest number between + the dielectric thickness or trace width multiplied by the expansion_factor factor. + The trace width search is limited to nets with ports attached. Works only if `use_pyaedt_cutout`. + Default is `0` to disable the search. + maximum_iterations : int, optional + Maximum number of iterations before stopping a search for a cutout with an error. + Default is `10`. + preserve_components_with_model : bool, optional + Whether to preserve all pins of components that have associated models (Spice or NPort). + This parameter is applicable only for a PyAEDT cutout (except point list). + simple_pad_check : bool, optional + Whether to use the center of the pad to find the intersection with extent or use the bounding box. + Second method is much slower and requires to disable multithread on padstack removal. + Default is `True`. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + Examples + -------- + >>> edb = Edb(r'C:\\test.aedb', edbversion="2022.2") + >>> edb.logger.info_timer("Edb Opening") + >>> edb.logger.reset_timer() + >>> start = time.time() + >>> signal_list = [] + >>> for net in edb.nets.netlist: + >>> if "3V3" in net: + >>> signal_list.append(net) + >>> power_list = ["PGND"] + >>> edb.cutout(signal_list=signal_list, reference_list=power_list, extent_type="Conforming") + >>> end_time = str((time.time() - start)/60) + >>> edb.logger.info("Total pyaedt cutout time in min %s", end_time) + >>> edb.nets.plot(signal_list, None, color_by_net=True) + >>> edb.nets.plot(power_list, None, color_by_net=True) + >>> edb.save_edb() + >>> edb.close_edb() + + + """ + if expansion_factor > 0: + expansion_size = self.calculate_initial_extent(expansion_factor) + if signal_list is None: + signal_list = [] + if isinstance(reference_list, str): + reference_list = [reference_list] + elif reference_list is None: + reference_list = [] + if not use_pyaedt_cutout and custom_extent: + return self._create_cutout_on_point_list( + custom_extent, + units=custom_extent_units, + output_aedb_path=output_aedb_path, + open_cutout_at_end=open_cutout_at_end, + nets_to_include=signal_list + reference_list, + include_partial_instances=include_partial_instances, + keep_voids=keep_voids, + ) + elif not use_pyaedt_cutout: + return self._create_cutout_legacy( + signal_list=signal_list, + reference_list=reference_list, + extent_type=extent_type, + expansion_size=expansion_size, + use_round_corner=use_round_corner, + output_aedb_path=output_aedb_path, + open_cutout_at_end=open_cutout_at_end, + use_pyaedt_extent_computing=use_pyaedt_extent_computing, + check_terminals=check_terminals, + include_pingroups=include_pingroups, + ) + else: + legacy_path = self.edbpath + if expansion_factor > 0 and not custom_extent: + start = time.time() + self.save_edb() + dummy_path = self.edbpath.replace(".aedb", "_smart_cutout_temp.aedb") + working_cutout = False + i = 1 + expansion = expansion_size + while i <= maximum_iterations: + self.logger.info("-----------------------------------------") + self.logger.info("Trying cutout with {}mm expansion size".format(expansion * 1e3)) + self.logger.info("-----------------------------------------") + result = self._create_cutout_multithread( + signal_list=signal_list, + reference_list=reference_list, + extent_type=extent_type, + expansion_size=expansion, + use_round_corner=use_round_corner, + number_of_threads=number_of_threads, + custom_extent=custom_extent, + output_aedb_path=dummy_path, + remove_single_pin_components=remove_single_pin_components, + use_pyaedt_extent_computing=use_pyaedt_extent_computing, + extent_defeature=extent_defeature, + custom_extent_units=custom_extent_units, + check_terminals=check_terminals, + include_pingroups=include_pingroups, + preserve_components_with_model=preserve_components_with_model, + include_partial=include_partial_instances, + simple_pad_check=simple_pad_check, + ) + if self.are_port_reference_terminals_connected(): + if output_aedb_path: + self.save_edb_as(output_aedb_path) + else: + self.save_edb_as(legacy_path) + working_cutout = True + break + self.close_edb() + self.edbpath = legacy_path + self.open_edb() + i += 1 + expansion = expansion_size * i + if working_cutout: + msg = "Cutout completed in {} iterations with expansion size of {}mm".format(i, expansion * 1e3) + self.logger.info_timer(msg, start) + else: + msg = "Cutout failed after {} iterations and expansion size of {}mm".format(i, expansion * 1e3) + self.logger.info_timer(msg, start) + return False + else: + result = self._create_cutout_multithread( + signal_list=signal_list, + reference_list=reference_list, + extent_type=extent_type, + expansion_size=expansion_size, + use_round_corner=use_round_corner, + number_of_threads=number_of_threads, + custom_extent=custom_extent, + output_aedb_path=output_aedb_path, + remove_single_pin_components=remove_single_pin_components, + use_pyaedt_extent_computing=use_pyaedt_extent_computing, + extent_defeature=extent_defeature, + custom_extent_units=custom_extent_units, + check_terminals=check_terminals, + include_pingroups=include_pingroups, + preserve_components_with_model=preserve_components_with_model, + include_partial=include_partial_instances, + simple_pad_check=simple_pad_check, + ) + if result and not open_cutout_at_end and self.edbpath != legacy_path: + self.save_edb() + self.close_edb() + self.edbpath = legacy_path + self.open_edb() + return result + + @pyaedt_function_handler() + def _create_cutout_legacy( + self, + signal_list=[], + reference_list=["GND"], + extent_type="Conforming", + expansion_size=0.002, + use_round_corner=False, + output_aedb_path=None, + open_cutout_at_end=True, + use_pyaedt_extent_computing=False, + remove_single_pin_components=False, + check_terminals=False, + include_pingroups=True, + ): + expansion_size = self.edb_value(expansion_size).ToDouble() + + # validate nets in layout + net_signals = [net.api_object for net in self.layout.nets if net.name in signal_list] + + # validate references in layout + _netsClip = convert_py_list_to_net_list( + [net.api_object for net in self.layout.nets if net.name in reference_list] + ) + + _poly = self._create_extent( + net_signals, + extent_type, + expansion_size, + use_round_corner, + use_pyaedt_extent_computing, + smart_cut=check_terminals, + reference_list=reference_list, + include_pingroups=include_pingroups, + ) + + # Create new cutout cell/design + included_nets_list = signal_list + reference_list + included_nets = convert_py_list_to_net_list( + [net.api_object for net in self.layout.nets if net.name in included_nets_list] + ) + _cutout = self.active_cell.CutOut(included_nets, _netsClip, _poly, True) + # Analysis setups do not come over with the clipped design copy, + # so add the analysis setups from the original here. + id = 1 + for _setup in self.active_cell.SimulationSetups: + # Empty string '' if coming from setup copy and don't set explicitly. + _setup_name = _setup.GetName() + if "GetSimSetupInfo" in dir(_setup): + # setup is an Ansys.Ansoft.Edb.Utility.HFSSSimulationSetup object + _hfssSimSetupInfo = _setup.GetSimSetupInfo() + _hfssSimSetupInfo.Name = "HFSS Setup " + str(id) # Set name of analysis setup + # Write the simulation setup info into the cell/design setup + _setup.SetSimSetupInfo(_hfssSimSetupInfo) + _cutout.AddSimulationSetup(_setup) # Add simulation setup to the cutout design + id += 1 + else: + _cutout.AddSimulationSetup(_setup) # Add simulation setup to the cutout design + + _dbCells = [_cutout] + + if output_aedb_path: + db2 = self.create(output_aedb_path) + _success = db2.Save() + _dbCells = convert_py_list_to_net_list(_dbCells) + db2.CopyCells(_dbCells) # Copies cutout cell/design to db2 project + if len(list(db2.CircuitCells)) > 0: + for net in list(list(db2.CircuitCells)[0].GetLayout().Nets): + if not net.GetName() in included_nets_list: + net.Delete() + _success = db2.Save() + for c in list(self.active_db.TopCircuitCells): + if c.GetName() == _cutout.GetName(): + c.Delete() + if open_cutout_at_end: # pragma: no cover + self._db = db2 + self.edbpath = output_aedb_path + self._active_cell = list(self.top_circuit_cells)[0] + self.edbpath = self.directory + self._init_objects() + if remove_single_pin_components: + self.components.delete_single_pin_rlc() + self.logger.info_timer("Single Pins components deleted") + self.components.refresh_components() + else: + if remove_single_pin_components: + try: + layout = list(db2.CircuitCells)[0].GetLayout() + _cmps = [ + l + for l in layout.Groups + if l.ToString() == "Ansys.Ansoft.Edb.Cell.Hierarchy.Component" and l.GetNumberOfPins() < 2 + ] + for _cmp in _cmps: + _cmp.Delete() + except: + self._logger.error("Failed to remove single pin components.") + db2.Close() + source = os.path.join(output_aedb_path, "edb.def.tmp") + target = os.path.join(output_aedb_path, "edb.def") + self._wait_for_file_release(file_to_release=output_aedb_path) + if os.path.exists(source) and not os.path.exists(target): + try: + shutil.copy(source, target) + except: + pass + elif open_cutout_at_end: + self._active_cell = _cutout + self._init_objects() + if remove_single_pin_components: + self.components.delete_single_pin_rlc() + self.logger.info_timer("Single Pins components deleted") + self.components.refresh_components() + return True + + @pyaedt_function_handler() + def create_cutout( + self, + signal_list=[], + reference_list=["GND"], + extent_type="Conforming", + expansion_size=0.002, + use_round_corner=False, + output_aedb_path=None, + open_cutout_at_end=True, + use_pyaedt_extent_computing=False, + ): + """Create a cutout using an approach entirely based on pyaedt. + It does in sequence: + - delete all nets not in list, + - create an extent of the nets, + - check and delete all vias not in the extent, + - check and delete all the primitives not in extent, + - check and intersect all the primitives that intersect the extent. + + .. deprecated:: 0.6.58 + Use new method :func:`cutout` instead. + + Parameters + ---------- + signal_list : list + List of signal strings. + reference_list : list, optional + List of references to add. The default is ``["GND"]``. + extent_type : str, optional + Type of the extension. Options are ``"Conforming"``, ``"ConvexHull"``, and + ``"Bounding"``. The default is ``"Conforming"``. + expansion_size : float, str, optional + Expansion size ratio in meters. The default is ``0.002``. + use_round_corner : bool, optional + Whether to use round corners. The default is ``False``. + output_aedb_path : str, optional + Full path and name for the new AEDB file. + open_cutout_at_end : bool, optional + Whether to open the cutout at the end. The default + is ``True``. + use_pyaedt_extent_computing : bool, optional + Whether to use pyaedt extent computing (experimental). + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + warnings.warn("Use new method `cutout` instead.", DeprecationWarning) + return self._create_cutout_legacy( + signal_list=signal_list, + reference_list=reference_list, + extent_type=extent_type, + expansion_size=expansion_size, + use_round_corner=use_round_corner, + output_aedb_path=output_aedb_path, + open_cutout_at_end=open_cutout_at_end, + use_pyaedt_extent_computing=use_pyaedt_extent_computing, + ) + + @pyaedt_function_handler() + def _create_cutout_multithread( + self, + signal_list=[], + reference_list=["GND"], + extent_type="Conforming", + expansion_size=0.002, + use_round_corner=False, + number_of_threads=4, + custom_extent=None, + output_aedb_path=None, + remove_single_pin_components=False, + use_pyaedt_extent_computing=False, + extent_defeature=0.0, + custom_extent_units="mm", + check_terminals=False, + include_pingroups=True, + preserve_components_with_model=False, + include_partial=False, + simple_pad_check=True, + ): + if is_ironpython: # pragma: no cover + self.logger.error("Method working only in Cpython") + return False + from concurrent.futures import ThreadPoolExecutor + + if output_aedb_path: + self.save_edb_as(output_aedb_path) + self.logger.info("Cutout Multithread started.") + expansion_size = self.edb_value(expansion_size).ToDouble() + + timer_start = self.logger.reset_timer() + if custom_extent: + if not reference_list and not signal_list: + reference_list = self.nets.netlist[::] + all_list = reference_list + else: + reference_list = reference_list + signal_list + all_list = reference_list + else: + all_list = signal_list + reference_list + pins_to_preserve = [] + nets_to_preserve = [] + if preserve_components_with_model: + for el in self.components.instances.values(): + if el.model_type in ["SPICEModel", "SParameterModel", "NetlistModel"] and list( + set(el.nets[:]) & set(signal_list[:]) + ): + pins_to_preserve.extend([i.id for i in el.pins.values()]) + nets_to_preserve.extend(el.nets) + + for i in self.nets.nets.values(): + name = i.name + if name not in all_list and name not in nets_to_preserve: + i.net_object.Delete() + reference_pinsts = [] + reference_prims = [] + for i in self.padstacks.instances.values(): + net_name = i.net_name + id = i.id + if net_name not in all_list and id not in pins_to_preserve: + i.delete() + elif net_name in reference_list and id not in pins_to_preserve: + reference_pinsts.append(i) + for i in self.modeler.primitives: + if i: + net_name = i.net_name + if net_name not in all_list: + i.delete() + elif net_name in reference_list and not i.is_void: + reference_prims.append(i) + self.logger.info_timer("Net clean up") + self.logger.reset_timer() + + if custom_extent and isinstance(custom_extent, list): + if custom_extent[0] != custom_extent[-1]: + custom_extent.append(custom_extent[0]) + custom_extent = [ + [self.number_with_units(i[0], custom_extent_units), self.number_with_units(i[1], custom_extent_units)] + for i in custom_extent + ] + plane = self.modeler.Shape("polygon", points=custom_extent) + _poly = self.modeler.shape_to_polygon_data(plane) + elif custom_extent: + _poly = custom_extent + else: + net_signals = [net.api_object for net in self.layout.nets if net.name in signal_list] + _poly = self._create_extent( + net_signals, + extent_type, + expansion_size, + use_round_corner, + use_pyaedt_extent_computing, + smart_cut=check_terminals, + reference_list=reference_list, + include_pingroups=include_pingroups, + ) + if extent_type in ["Conforming", self.edb_api.geometry.extent_type.Conforming, 1] and extent_defeature > 0: + _poly = _poly.Defeature(extent_defeature) + + if not _poly or _poly.IsNull(): + self._logger.error("Failed to create Extent.") + return False + self.logger.info_timer("Expanded Net Polygon Creation") + self.logger.reset_timer() + _poly_list = convert_py_list_to_net_list([_poly]) + prims_to_delete = [] + poly_to_create = [] + pins_to_delete = [] + + def intersect(poly1, poly2): + if not isinstance(poly2, list): + poly2 = [poly2] + return list(poly1.Intersect(convert_py_list_to_net_list(poly1), convert_py_list_to_net_list(poly2))) + + def subtract(poly, voids): + return poly.Subtract(convert_py_list_to_net_list(poly), convert_py_list_to_net_list(voids)) + + def clean_prim(prim_1): # pragma: no cover + pdata = prim_1.polygon_data.edb_api + int_data = _poly.GetIntersectionType(pdata) + if int_data == 2: + return + elif int_data == 0: + prims_to_delete.append(prim_1) + else: + list_poly = intersect(_poly, pdata) + if list_poly: + net = prim_1.net_name + voids = prim_1.voids + for p in list_poly: + if p.IsNull(): + continue + # points = list(p.Points) + list_void = [] + if voids: + voids_data = [void.polygon_data.edb_api for void in voids] + list_prims = subtract(p, voids_data) + for prim in list_prims: + if not prim.IsNull(): + poly_to_create.append([prim, prim_1.layer_name, net, list_void]) + else: + poly_to_create.append([p, prim_1.layer_name, net, list_void]) + + prims_to_delete.append(prim_1) + + def pins_clean(pinst): + if not pinst.in_polygon(_poly, include_partial=include_partial, simple_check=simple_pad_check): + pins_to_delete.append(pinst) + + if not simple_pad_check: + pad_cores = 1 + else: + pad_cores = number_of_threads + with ThreadPoolExecutor(pad_cores) as pool: + pool.map(lambda item: pins_clean(item), reference_pinsts) + + for pin in pins_to_delete: + pin.delete() + + self.logger.info_timer("Padstack Instances removal completed") + self.logger.reset_timer() + + with ThreadPoolExecutor(number_of_threads) as pool: + pool.map(lambda item: clean_prim(item), reference_prims) + + for el in poly_to_create: + self.modeler.create_polygon(el[0], el[1], net_name=el[2], voids=el[3]) + + for prim in prims_to_delete: + prim.delete() + self.logger.info_timer("Primitives cleanup completed") + self.logger.reset_timer() + + i = 0 + for _, val in self.components.components.items(): + if val.numpins == 0: + val.edbcomponent.Delete() + i += 1 + i += 1 + self.logger.info("Deleted {} additional components".format(i)) + if remove_single_pin_components: + self.components.delete_single_pin_rlc() + self.logger.info_timer("Single Pins components deleted") + + self.components.refresh_components() + if output_aedb_path: + self.save_edb() + self.logger.info_timer("Cutout completed.", timer_start) + self.logger.reset_timer() + return True + + @pyaedt_function_handler() + def create_cutout_multithread( + self, + signal_list=[], + reference_list=["GND"], + extent_type="Conforming", + expansion_size=0.002, + use_round_corner=False, + number_of_threads=4, + custom_extent=None, + output_aedb_path=None, + remove_single_pin_components=False, + use_pyaedt_extent_computing=False, + extent_defeature=0, + ): + """Create a cutout using an approach entirely based on pyaedt. + It does in sequence: + - delete all nets not in list, + - create a extent of the nets, + - check and delete all vias not in the extent, + - check and delete all the primitives not in extent, + - check and intersect all the primitives that intersect the extent. + + + .. deprecated:: 0.6.58 + Use new method :func:`cutout` instead. + + Parameters + ---------- + signal_list : list + List of signal strings. + reference_list : list, optional + List of references to add. The default is ``["GND"]``. + extent_type : str, optional + Type of the extension. Options are ``"Conforming"``, ``"ConvexHull"``, and + ``"Bounding"``. The default is ``"Conforming"``. + expansion_size : float, str, optional + Expansion size ratio in meters. The default is ``0.002``. + use_round_corner : bool, optional + Whether to use round corners. The default is ``False``. + number_of_threads : int, optional + Number of thread to use. Default is 4 + custom_extent : list, optional + Custom extent to use for the cutout. It has to be a list of points [[x1,y1],[x2,y2]....] or + Edb PolygonData object. In this case, both signal_list and reference_list will be cut. + output_aedb_path : str, optional + Full path and name for the new AEDB file. If None, then current aedb will be cutout. + remove_single_pin_components : bool, optional + Remove all Single Pin RLC after the cutout is completed. Default is `False`. + use_pyaedt_extent_computing : bool, optional + Whether to use pyaedt extent computing (experimental). + extent_defeature : float, optional + Defeature the cutout before applying it to produce simpler geometry for mesh (Experimental). + It applies only to Conforming bounding box. Default value is ``0`` which disable it. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + Examples + -------- + >>> edb = Edb(r'C:\\test.aedb', edbversion="2022.2") + >>> edb.logger.info_timer("Edb Opening") + >>> edb.logger.reset_timer() + >>> start = time.time() + >>> signal_list = [] + >>> for net in edb.nets.nets.keys(): + >>> if "3V3" in net: + >>> signal_list.append(net) + >>> power_list = ["PGND"] + >>> edb.create_cutout_multithread(signal_list=signal_list, reference_list=power_list, extent_type="Conforming") + >>> end_time = str((time.time() - start)/60) + >>> edb.logger.info("Total pyaedt cutout time in min %s", end_time) + >>> edb.nets.plot(signal_list, None, color_by_net=True) + >>> edb.nets.plot(power_list, None, color_by_net=True) + >>> edb.save_edb() + >>> edb.close_edb() + + """ + warnings.warn("Use new method `cutout` instead.", DeprecationWarning) + return self._create_cutout_multithread( + signal_list=signal_list, + reference_list=reference_list, + extent_type=extent_type, + expansion_size=expansion_size, + use_round_corner=use_round_corner, + number_of_threads=number_of_threads, + custom_extent=custom_extent, + output_aedb_path=output_aedb_path, + remove_single_pin_components=remove_single_pin_components, + use_pyaedt_extent_computing=use_pyaedt_extent_computing, + extent_defeature=extent_defeature, + ) + + @pyaedt_function_handler() + def get_conformal_polygon_from_netlist(self, netlist=None): + """Return an EDB conformal polygon based on a netlist. + + Parameters + ---------- + + netlist : List of net names. + list[str] + + Returns + ------- + :class:`Edb.Cell.Primitive.Polygon` + Edb polygon object. + + """ + temp_edb_path = self.edbpath[:-5] + "_temp_aedb.aedb" + shutil.copytree(self.edbpath, temp_edb_path) + temp_edb = Edb(temp_edb_path) + for via in list(temp_edb.padstacks.instances.values()): + via.pin.Delete() + if netlist: + nets = [net.net_obj for net in temp_edb.layout.nets if net.name in netlist] + _poly = temp_edb.layout.expanded_extent( + nets, self.edb_api.geometry.extent_type.Conforming, 0.0, True, True, 1 + ) + else: + nets = [net.api_object for net in temp_edb.layout.nets if "gnd" in net.name.lower()] + _poly = temp_edb.layout.expanded_extent( + nets, self.edb_api.geometry.extent_type.Conforming, 0.0, True, True, 1 + ) + temp_edb.close_edb() + if _poly: + return _poly + else: + return False + + @pyaedt_function_handler() + def number_with_units(self, value, units=None): + """Convert a number to a string with units. If value is a string, it's returned as is. + + Parameters + ---------- + value : float, int, str + Input number or string. + units : optional + Units for formatting. The default is ``None``, which uses ``"meter"``. + + Returns + ------- + str + String concatenating the value and unit. + + """ + if units is None: + units = "meter" + if isinstance(value, str): + return value + else: + return "{0}{1}".format(value, units) + + @pyaedt_function_handler() + def arg_with_dim(self, Value, sUnits): + """Convert a number to a string with units. If value is a string, it's returned as is. + + .. deprecated:: 0.6.56 + Use :func:`number_with_units` property instead. + + Parameters + ---------- + Value : float, int, str + Input number or string. + sUnits : optional + Units for formatting. The default is ``None``, which uses ``"meter"``. + + Returns + ------- + str + String concatenating the value and unit. + + """ + warnings.warn("Use :func:`number_with_units` instead.", DeprecationWarning) + return self.number_with_units(Value, sUnits) + + def _decompose_variable_value(self, value, unit_system=None): + val, units = decompose_variable_value(value) + if units and unit_system and units in AEDT_UNITS[unit_system]: + return AEDT_UNITS[unit_system][units] * val + else: + return val + + @pyaedt_function_handler() + def _create_cutout_on_point_list( + self, + point_list, + units="mm", + output_aedb_path=None, + open_cutout_at_end=True, + nets_to_include=None, + include_partial_instances=False, + keep_voids=True, + ): + if point_list[0] != point_list[-1]: + point_list.append(point_list[0]) + point_list = [[self.number_with_units(i[0], units), self.number_with_units(i[1], units)] for i in point_list] + plane = self.modeler.Shape("polygon", points=point_list) + polygonData = self.modeler.shape_to_polygon_data(plane) + _ref_nets = [] + if nets_to_include: + self.logger.info("Creating cutout on {} nets.".format(len(nets_to_include))) + else: + self.logger.info("Creating cutout on all nets.") # pragma: no cover + + # Check Padstack Instances overlapping the cutout + pinstance_to_add = [] + if include_partial_instances: + if nets_to_include: + pinst = [i for i in list(self.padstacks.instances.values()) if i.net_name in nets_to_include] + else: + pinst = [i for i in list(self.padstacks.instances.values())] + for p in pinst: + if p.in_polygon(polygonData): + pinstance_to_add.append(p) + # validate references in layout + for _ref in self.nets.nets: + if nets_to_include: + if _ref in nets_to_include: + _ref_nets.append(self.nets.nets[_ref].net_object) + else: + _ref_nets.append(self.nets.nets[_ref].net_object) # pragma: no cover + if keep_voids: + voids = [p for p in self.modeler.circles if p.is_void] + voids2 = [p for p in self.modeler.polygons if p.is_void] + voids.extend(voids2) + else: + voids = [] + voids_to_add = [] + for circle in voids: + if polygonData.GetIntersectionType(circle.primitive_object.GetPolygonData()) >= 3: + voids_to_add.append(circle) + + _netsClip = convert_py_list_to_net_list(_ref_nets) + # net_signals = convert_py_list_to_net_list([], type(_ref_nets[0])) + + # Create new cutout cell/design + _cutout = self.active_cell.CutOut(_netsClip, _netsClip, polygonData) + layout = _cutout.GetLayout() + cutout_obj_coll = list(layout.PadstackInstances) + ids = [] + for lobj in cutout_obj_coll: + ids.append(lobj.GetId()) + + if include_partial_instances: + p_missing = [i for i in pinstance_to_add if i.id not in ids] + self.logger.info("Added {} padstack instances after cutout".format(len(p_missing))) + for p in p_missing: + position = self.edb_api.geometry.point_data( + self.edb_value(p.position[0]), self.edb_value(p.position[1]) + ) + net = self.nets.find_or_create_net(p.net_name) + rotation = self.edb_value(p.rotation) + sign_layers = list(self.stackup.signal_layers.keys()) + if not p.start_layer: # pragma: no cover + fromlayer = self.stackup.signal_layers[sign_layers[0]]._edb_layer + else: + fromlayer = self.stackup.signal_layers[p.start_layer]._edb_layer + + if not p.stop_layer: # pragma: no cover + tolayer = self.stackup.signal_layers[sign_layers[-1]]._edb_layer + else: + tolayer = self.stackup.signal_layers[p.stop_layer]._edb_layer + padstack = None + for pad in list(self.padstacks.definitions.keys()): + if pad == p.padstack_definition: + padstack = self.padstacks.definitions[pad].edb_padstack + padstack_instance = self.edb_api.cell.primitive.padstack_instance.create( + _cutout.GetLayout(), + net, + p.name, + padstack, + position, + rotation, + fromlayer, + tolayer, + None, + None, + ) + padstack_instance.SetIsLayoutPin(p.is_pin) + break + + for void_circle in voids_to_add: + if void_circle.type == "Circle": + if is_ironpython: # pragma: no cover + res, center_x, center_y, radius = void_circle.primitive_object.GetParameters() + else: + res, center_x, center_y, radius = void_circle.primitive_object.GetParameters(0.0, 0.0, 0.0) + cloned_circle = self.edb_api.cell.primitive.circle.create( + layout, + void_circle.layer_name, + void_circle.net, + self.edb_value(center_x), + self.edb_value(center_y), + self.edb_value(radius), + ) + cloned_circle.SetIsNegative(True) + elif void_circle.type == "Polygon": + cloned_polygon = self.edb_api.cell.primitive.polygon.create( + layout, void_circle.layer_name, void_circle.net, void_circle.primitive_object.GetPolygonData() + ) + cloned_polygon.SetIsNegative(True) + layers = [i for i in list(self.stackup.signal_layers.keys())] + for layer in layers: + layer_primitves = self.modeler.get_primitives(layer_name=layer) + if len(layer_primitves) == 0: + self.modeler.create_polygon(plane, layer, net_name="DUMMY") + self.logger.info("Cutout %s created correctly", _cutout.GetName()) + id = 1 + for _setup in self.active_cell.SimulationSetups: + # Empty string '' if coming from setup copy and don't set explicitly. + _setup_name = _setup.GetName() + if "GetSimSetupInfo" in dir(_setup): + # setup is an Ansys.Ansoft.Edb.Utility.HFSSSimulationSetup object + _hfssSimSetupInfo = _setup.GetSimSetupInfo() + _hfssSimSetupInfo.Name = "HFSS Setup " + str(id) # Set name of analysis setup + # Write the simulation setup info into the cell/design setup + _setup.SetSimSetupInfo(_hfssSimSetupInfo) + _cutout.AddSimulationSetup(_setup) # Add simulation setup to the cutout design + id += 1 + else: + _cutout.AddSimulationSetup(_setup) # Add simulation setup to the cutout design + + _dbCells = [_cutout] + if output_aedb_path: + db2 = self.create(output_aedb_path) + if not db2.Save(): + self.logger.error("Failed to create new Edb. Check if the path already exists and remove it.") + return False + _dbCells = convert_py_list_to_net_list(_dbCells) + cell_copied = db2.CopyCells(_dbCells) # Copies cutout cell/design to db2 project + cell = list(cell_copied)[0] + cell.SetName(os.path.basename(output_aedb_path[:-5])) + db2.Save() + for c in list(self.active_db.TopCircuitCells): + if c.GetName() == _cutout.GetName(): + c.Delete() + if open_cutout_at_end: # pragma: no cover + _success = db2.Save() + self._db = db2 + self.edbpath = output_aedb_path + self._active_cell = cell + self.edbpath = self.directory + self._init_objects() + else: + db2.Close() + source = os.path.join(output_aedb_path, "edb.def.tmp") + target = os.path.join(output_aedb_path, "edb.def") + self._wait_for_file_release(file_to_release=output_aedb_path) + if os.path.exists(source) and not os.path.exists(target): + try: + shutil.copy(source, target) + self.logger.warning("aedb def file manually created.") + except: + pass + return True + + @pyaedt_function_handler() + def create_cutout_on_point_list( + self, + point_list, + units="mm", + output_aedb_path=None, + open_cutout_at_end=True, + nets_to_include=None, + include_partial_instances=False, + keep_voids=True, + ): + """Create a cutout on a specified shape and save it to a new AEDB file. + + .. deprecated:: 0.6.58 + Use new method :func:`cutout` instead. + + Parameters + ---------- + point_list : list + Points list defining the cutout shape. + units : str + Units of the point list. The default is ``"mm"``. + output_aedb_path : str, optional + Full path and name for the new AEDB file. + The aedb folder shall not exist otherwise the method will return ``False``. + open_cutout_at_end : bool, optional + Whether to open the cutout at the end. The default is ``True``. + nets_to_include : list, optional + List of nets to include in the cutout. The default is ``None``, in + which case all nets are included. + include_partial_instances : bool, optional + Whether to include padstack instances that have bounding boxes intersecting with point list polygons. + This operation may slow down the cutout export. + keep_voids : bool + Boolean used for keep or not the voids intersecting the polygon used for clipping the layout. + Default value is ``True``, ``False`` will remove the voids. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + warnings.warn("Use new method `cutout` instead.", DeprecationWarning) + return self._create_cutout_on_point_list( + point_list=point_list, + units=units, + output_aedb_path=output_aedb_path, + open_cutout_at_end=open_cutout_at_end, + nets_to_include=nets_to_include, + include_partial_instances=include_partial_instances, + keep_voids=keep_voids, + ) + + @pyaedt_function_handler() + def write_export3d_option_config_file(self, path_to_output, config_dictionaries=None): + """Write the options for a 3D export to a configuration file. + + Parameters + ---------- + path_to_output : str + Full path to the configuration file to save 3D export options to. + + config_dictionaries : dict, optional + Configuration dictionaries. The default is ``None``. + + """ + option_config = { + "UNITE_NETS": 1, + "ASSIGN_SOLDER_BALLS_AS_SOURCES": 0, + "Q3D_MERGE_SOURCES": 0, + "Q3D_MERGE_SINKS": 0, + "CREATE_PORTS_FOR_PWR_GND_NETS": 0, + "PORTS_FOR_PWR_GND_NETS": 0, + "GENERATE_TERMINALS": 0, + "SOLVE_CAPACITANCE": 0, + "SOLVE_DC_RESISTANCE": 0, + "SOLVE_DC_INDUCTANCE_RESISTANCE": 1, + "SOLVE_AC_INDUCTANCE_RESISTANCE": 0, + "CreateSources": 0, + "CreateSinks": 0, + "LAUNCH_Q3D": 0, + "LAUNCH_HFSS": 0, + } + if config_dictionaries: + for el, val in config_dictionaries.items(): + option_config[el] = val + with open(os.path.join(path_to_output, "options.config"), "w") as f: + for el, val in option_config.items(): + f.write(el + " " + str(val) + "\n") + return os.path.join(path_to_output, "options.config") + + @pyaedt_function_handler() + def export_hfss(self, path_to_output, net_list=None, num_cores=None, aedt_file_name=None, hidden=False): + """Export EDB to HFSS. + + Parameters + ---------- + path_to_output : str + Full path and name for saving the AEDT file. + net_list : list, optional + List of nets to export if only certain ones are to be exported. + The default is ``None``, in which case all nets are eported. + num_cores : int, optional + Number of cores to use for the export. The default is ``None``. + aedt_file_name : str, optional + Name of the AEDT output file without the ``.aedt`` extension. The default is ``None``, + in which case the default name is used. + hidden : bool, optional + Open Siwave in embedding mode. User will only see Siwave Icon but UI will be hidden. + + Returns + ------- + str + Full path to the AEDT file. + + Examples + -------- + + >>> from pyaedt import Edb + + >>> edb = Edb(edbpath=r"C:\temp\myproject.aedb", edbversion="2021.2") + + >>> options_config = {'UNITE_NETS' : 1, 'LAUNCH_Q3D' : 0} + >>> edb.write_export3d_option_config_file(r"C:\temp", options_config) + >>> edb.export_hfss(r"C:\temp") + "C:\\temp\\hfss_siwave.aedt" + + """ + siwave_s = SiwaveSolve(self.edbpath, aedt_installer_path=self.base_path) + return siwave_s.export_3d_cad("HFSS", path_to_output, net_list, num_cores, aedt_file_name, hidden=hidden) + + @pyaedt_function_handler() + def export_q3d(self, path_to_output, net_list=None, num_cores=None, aedt_file_name=None, hidden=False): + """Export EDB to Q3D. + + Parameters + ---------- + path_to_output : str + Full path and name for saving the AEDT file. + net_list : list, optional + List of nets to export only if certain ones are to be exported. + The default is ``None``, in which case all nets are eported. + num_cores : int, optional + Number of cores to use for the export. The default is ``None``. + aedt_file_name : str, optional + Name of the AEDT output file without the ``.aedt`` extension. The default is ``None``, + in which case the default name is used. + hidden : bool, optional + Open Siwave in embedding mode. User will only see Siwave Icon but UI will be hidden. + + Returns + ------- + str + Full path to the AEDT file. + + Examples + -------- + + >>> from pyaedt import Edb + + >>> edb = Edb(edbpath=r"C:\temp\myproject.aedb", edbversion="2021.2") + + >>> options_config = {'UNITE_NETS' : 1, 'LAUNCH_Q3D' : 0} + >>> edb.write_export3d_option_config_file(r"C:\temp", options_config) + >>> edb.export_q3d(r"C:\temp") + "C:\\temp\\q3d_siwave.aedt" + + """ + + siwave_s = SiwaveSolve(self.edbpath, aedt_installer_path=self.base_path) + return siwave_s.export_3d_cad( + "Q3D", path_to_output, net_list, num_cores=num_cores, aedt_file_name=aedt_file_name, hidden=hidden + ) + + @pyaedt_function_handler() + def export_maxwell(self, path_to_output, net_list=None, num_cores=None, aedt_file_name=None, hidden=False): + """Export EDB to Maxwell 3D. + + Parameters + ---------- + path_to_output : str + Full path and name for saving the AEDT file. + net_list : list, optional + List of nets to export only if certain ones are to be + exported. The default is ``None``, in which case all nets are exported. + num_cores : int, optional + Number of cores to use for the export. The default is ``None.`` + aedt_file_name : str, optional + Name of the AEDT output file without the ``.aedt`` extension. The default is ``None``, + in which case the default name is used. + hidden : bool, optional + Open Siwave in embedding mode. User will only see Siwave Icon but UI will be hidden. + + Returns + ------- + str + Full path to the AEDT file. + + Examples + -------- + + >>> from pyaedt import Edb + + >>> edb = Edb(edbpath=r"C:\temp\myproject.aedb", edbversion="2021.2") + + >>> options_config = {'UNITE_NETS' : 1, 'LAUNCH_Q3D' : 0} + >>> edb.write_export3d_option_config_file(r"C:\temp", options_config) + >>> edb.export_maxwell(r"C:\temp") + "C:\\temp\\maxwell_siwave.aedt" + + """ + siwave_s = SiwaveSolve(self.edbpath, aedt_installer_path=self.base_path) + return siwave_s.export_3d_cad( + "Maxwell", + path_to_output, + net_list, + num_cores=num_cores, + aedt_file_name=aedt_file_name, + hidden=hidden, + ) + + @pyaedt_function_handler() + def solve_siwave(self): + """Close EDB and solve it with Siwave. + + Returns + ------- + str + Siwave project path. + """ + process = SiwaveSolve(self.edbpath, aedt_version=self.edbversion) + try: + self.close() + except: + pass + process.solve() + return self.edbpath[:-5] + ".siw" + + @pyaedt_function_handler() + def export_siwave_dc_results( + self, + siwave_project, + solution_name, + output_folder=None, + html_report=True, + vias=True, + voltage_probes=True, + current_sources=True, + voltage_sources=True, + power_tree=True, + loop_res=True, + ): + """Close EDB and solve it with Siwave. + + Parameters + ---------- + siwave_project : str + Siwave full project name. + solution_name : str + Siwave DC Analysis name. + output_folder : str, optional + Ouptu folder where files will be downloaded. + html_report : bool, optional + Either if generate or not html report. Default is `True`. + vias : bool, optional + Either if generate or not vias report. Default is `True`. + voltage_probes : bool, optional + Either if generate or not voltage probe report. Default is `True`. + current_sources : bool, optional + Either if generate or not current source report. Default is `True`. + voltage_sources : bool, optional + Either if generate or not voltage source report. Default is `True`. + power_tree : bool, optional + Either if generate or not power tree image. Default is `True`. + loop_res : bool, optional + Either if generate or not loop resistance report. Default is `True`. + + Returns + ------- + list + List of files generated. + """ + process = SiwaveSolve(self.edbpath, aedt_version=self.edbversion) + try: + self.close() + except: + pass + return process.export_dc_report( + siwave_project, + solution_name, + output_folder, + html_report, + vias, + voltage_probes, + current_sources, + voltage_sources, + power_tree, + loop_res, + hidden=True, + ) + + @pyaedt_function_handler() + def variable_exists(self, variable_name): + """Check if a variable exists or not. + + Returns + ------- + tuple of bool and VaribleServer + It returns a booleand to check if the variable exists and the variable + server that should contain the variable. + """ + if "$" in variable_name: + if variable_name.index("$") == 0: + var_server = self.active_db.GetVariableServer() + + else: + var_server = self.active_cell.GetVariableServer() + + else: + var_server = self.active_cell.GetVariableServer() + + variables = var_server.GetAllVariableNames() + if variable_name in list(variables): + return True, var_server + return False, var_server + + @pyaedt_function_handler() + def get_variable(self, variable_name): + """Return Variable Value if variable exists. + + Parameters + ---------- + variable_name + + Returns + ------- + :class:`pyaedt.edb_core.edb_data.edbvalue.EdbValue` + """ + var_server = self.variable_exists(variable_name) + if var_server[0]: + tuple_value = var_server[1].GetVariableValue(variable_name) + return EdbValue(tuple_value[1]) + self.logger.info("Variable %s doesn't exists.", variable_name) + return None + + @pyaedt_function_handler() + def add_project_variable(self, variable_name, variable_value): + """Add a variable to edb database (project). The variable will have the prefix `$`. + + ..note:: + User can use also the setitem to create or assign a variable. See example below. + + Parameters + ---------- + variable_name : str + Name of the variable. Name can be provided without ``$`` prefix. + variable_value : str, float + Value of the variable with units. + + Returns + ------- + tuple + Tuple containing the ``AddVariable`` result and variable server. + + Examples + -------- + + >>> from pyaedt import Edb + >>> edb_app = Edb() + >>> boolean_1, ant_length = edb_app.add_project_variable("my_local_variable", "1cm") + >>> print(edb_app["$my_local_variable"]) #using getitem + >>> edb_app["$my_local_variable"] = "1cm" #using setitem + + """ + if not variable_name.startswith("$"): + variable_name = "${}".format(variable_name) + return self.add_design_variable(variable_name=variable_name, variable_value=variable_value) + + @pyaedt_function_handler() + def add_design_variable(self, variable_name, variable_value, is_parameter=False): + """Add a variable to edb. The variable can be a design one or a project variable (using ``$`` prefix). + + ..note:: + User can use also the setitem to create or assign a variable. See example below. + + Parameters + ---------- + variable_name : str + Name of the variable. To added the variable as a project variable, the name + must begin with ``$``. + variable_value : str, float + Value of the variable with units. + is_parameter : bool, optional + Whether to add the variable as a local variable. The default is ``False``. + When ``True``, the variable is added as a parameter default. + + Returns + ------- + tuple + Tuple containing the ``AddVariable`` result and variable server. + + Examples + -------- + + >>> from pyaedt import Edb + >>> edb_app = Edb() + >>> boolean_1, ant_length = edb_app.add_design_variable("my_local_variable", "1cm") + >>> print(edb_app["my_local_variable"]) #using getitem + >>> edb_app["my_local_variable"] = "1cm" #using setitem + >>> boolean_2, para_length = edb_app.change_design_variable_value("my_parameter", "1m", is_parameter=True + >>> boolean_3, project_length = edb_app.change_design_variable_value("$my_project_variable", "1m") + + + """ + var_server = self.variable_exists(variable_name) + if not var_server[0]: + var_server[1].AddVariable(variable_name, self.edb_value(variable_value), is_parameter) + return True, var_server[1] + self.logger.error("Variable %s already exists.", variable_name) + return False, var_server[1] + + @pyaedt_function_handler() + def change_design_variable_value(self, variable_name, variable_value): + """Change a variable value. + + ..note:: + User can use also the getitem to read the variable value. See example below. + + Parameters + ---------- + variable_name : str + Name of the variable. + variable_value : str, float + Value of the variable with units. + + Returns + ------- + tuple + Tuple containing the ``SetVariableValue`` result and variable server. + + Examples + -------- + + >>> from pyaedt import Edb + >>> edb_app = Edb() + >>> boolean, ant_length = edb_app.add_design_variable("ant_length", "1cm") + >>> boolean, ant_length = edb_app.change_design_variable_value("ant_length", "1m") + >>> print(edb_app["ant_length"]) #using getitem + """ + var_server = self.variable_exists(variable_name) + if var_server[0]: + var_server[1].SetVariableValue(variable_name, self.edb_value(variable_value)) + return True, var_server[1] + self.logger.error("Variable %s does not exists.", variable_name) + return False, var_server[1] + + @pyaedt_function_handler() + def get_bounding_box(self): + """Get the layout bounding box. + + Returns + ------- + list of list of double + Bounding box as a [lower-left X, lower-left Y], [upper-right X, upper-right Y]) pair in meters. + """ + bbox = self.edbutils.HfssUtilities.GetBBox(self.active_layout) + return [[bbox.Item1.X.ToDouble(), bbox.Item1.Y.ToDouble()], [bbox.Item2.X.ToDouble(), bbox.Item2.Y.ToDouble()]] + + @pyaedt_function_handler() + def build_simulation_project(self, simulation_setup): + # type: (SimulationConfiguration) -> bool + """Build a ready-to-solve simulation project. + + Parameters + ---------- + simulation_setup : :class:`pyaedt.edb_core.edb_data.simulation_configuration.SimulationConfiguration` object. + SimulationConfiguration object that can be instantiated or directly loaded with a + configuration file. + + Returns + ------- + bool + ``True`` when successful, False when ``Failed``. + + Examples + -------- + + >>> from pyaedt import Edb + >>> from pyaedt.edb_core.edb_data.simulation_configuration import SimulationConfiguration + >>> config_file = path_configuration_file + >>> source_file = path_to_edb_folder + >>> edb = Edb(source_file) + >>> sim_setup = SimulationConfiguration(config_file) + >>> edb.build_simulation_project(sim_setup) + >>> edb.save_edb() + >>> edb.close_edb() + """ + self.logger.info("Building simulation project.") + legacy_name = self.edbpath + if simulation_setup.output_aedb: + self.save_edb_as(simulation_setup.output_aedb) + try: + if simulation_setup.signal_layer_etching_instances: + for layer in simulation_setup.signal_layer_etching_instances: + if layer in self.stackup.layers: + idx = simulation_setup.signal_layer_etching_instances.index(layer) + if len(simulation_setup.etching_factor_instances) > idx: + self.stackup[layer].etch_factor = float(simulation_setup.etching_factor_instances[idx]) + + if not simulation_setup.signal_nets and simulation_setup.components: + nets_to_include = [] + pnets = list(self.nets.power_nets.keys())[:] + for el in simulation_setup.components: + nets_to_include.append([i for i in self.components[el].nets if i not in pnets]) + simulation_setup.signal_nets = [ + i + for i in list(set.intersection(*map(set, nets_to_include))) + if i not in simulation_setup.power_nets and i != "" + ] + self.nets.classify_nets(simulation_setup.power_nets, simulation_setup.signal_nets) + if not simulation_setup.power_nets or not simulation_setup.signal_nets: + self.logger.info("Disabling cutout as no signals or power nets have been defined.") + simulation_setup.do_cutout_subdesign = False + if simulation_setup.do_cutout_subdesign: + self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type)) + if simulation_setup.use_default_cutout: + old_cell_name = self.active_cell.GetName() + if self.cutout( + signal_list=simulation_setup.signal_nets, + reference_list=simulation_setup.power_nets, + expansion_size=simulation_setup.cutout_subdesign_expansion, + use_round_corner=simulation_setup.cutout_subdesign_round_corner, + extent_type=simulation_setup.cutout_subdesign_type, + use_pyaedt_cutout=False, + use_pyaedt_extent_computing=False, + ): + self.logger.info("Cutout processed.") + old_cell = self.active_cell.FindByName( + self.db, self.edb_api.cell.CellType.CircuitCell, old_cell_name + ) + if old_cell: + old_cell.Delete() + else: # pragma: no cover + self.logger.error("Cutout failed.") + else: + self.logger.info("Cutting out using method: {0}".format(simulation_setup.cutout_subdesign_type)) + self.cutout( + signal_list=simulation_setup.signal_nets, + reference_list=simulation_setup.power_nets, + expansion_size=simulation_setup.cutout_subdesign_expansion, + use_round_corner=simulation_setup.cutout_subdesign_round_corner, + extent_type=simulation_setup.cutout_subdesign_type, + use_pyaedt_cutout=True, + use_pyaedt_extent_computing=True, + remove_single_pin_components=True, + ) + self.logger.info("Cutout processed.") + else: + if simulation_setup.include_only_selected_nets: + included_nets = simulation_setup.signal_nets + simulation_setup.power_nets + nets_to_remove = [ + net.name for net in list(self.nets.nets.values()) if not net.name in included_nets + ] + self.nets.delete(nets_to_remove) + self.logger.info("Deleting existing ports.") + map(lambda port: port.Delete(), self.layout.terminals) + map(lambda pg: pg.Delete(), self.layout.pin_groups) + if simulation_setup.solver_type == SolverType.Hfss3dLayout: + if simulation_setup.generate_excitations: + self.logger.info("Creating HFSS ports for signal nets.") + source_type = SourceType.CoaxPort + if not simulation_setup.generate_solder_balls: + source_type = SourceType.CircPort + for cmp in simulation_setup.components: + self.components.create_port_on_component( + cmp, + net_list=simulation_setup.signal_nets, + do_pingroup=False, + reference_net=simulation_setup.power_nets, + port_type=source_type, + ) + if simulation_setup.generate_solder_balls and not self.hfss.set_coax_port_attributes( + simulation_setup + ): # pragma: no cover + self.logger.error("Failed to configure coaxial port attributes.") + self.logger.info("Number of ports: {}".format(self.hfss.get_ports_number())) + self.logger.info("Configure HFSS extents.") + if ( + simulation_setup.generate_solder_balls and simulation_setup.trim_reference_size + ): # pragma: no cover + self.logger.info( + "Trimming the reference plane for coaxial ports: {0}".format( + bool(simulation_setup.trim_reference_size) + ) + ) + self.hfss.trim_component_reference_size(simulation_setup) # pragma: no cover + self.hfss.configure_hfss_extents(simulation_setup) + if not self.hfss.configure_hfss_analysis_setup(simulation_setup): + self.logger.error("Failed to configure HFSS simulation setup.") + if simulation_setup.solver_type == SolverType.SiwaveSYZ: + if simulation_setup.generate_excitations: + for cmp in simulation_setup.components: + self.components.create_port_on_component( + cmp, + net_list=simulation_setup.signal_nets, + do_pingroup=simulation_setup.do_pingroup, + reference_net=simulation_setup.power_nets, + port_type=SourceType.CircPort, + ) + self.logger.info("Configuring analysis setup.") + if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover + self.logger.error("Failed to configure Siwave simulation setup.") + + if simulation_setup.solver_type == SolverType.SiwaveDC: + if simulation_setup.generate_excitations: + self.components.create_source_on_component(simulation_setup.sources) + if not self.siwave.configure_siw_analysis_setup(simulation_setup): # pragma: no cover + self.logger.error("Failed to configure Siwave simulation setup.") + self.padstacks.check_and_fix_via_plating() + self.save_edb() + if not simulation_setup.open_edb_after_build and simulation_setup.output_aedb: + self.close_edb() + self.edbpath = legacy_name + self.open_edb() + return True + except: # pragma: no cover + return False + + @pyaedt_function_handler() + def get_statistics(self, compute_area=False): + """Get the EDBStatistics object. + + Returns + ------- + EDBStatistics object from the loaded layout. + """ + return self.modeler.get_layout_statistics(evaluate_area=compute_area, net_list=None) + + @pyaedt_function_handler() + def are_port_reference_terminals_connected(self, common_reference=None): + """Check if all terminal references in design are connected. + If the reference nets are different, there is no hope for the terminal references to be connected. + After we have identified a common reference net we need to loop the terminals again to get + the correct reference terminals that uses that net. + + Parameters + ---------- + common_reference : str, optional + Common Reference name. If ``None`` it will be searched in ports terminal. + If a string is passed then all excitations must have such reference assigned. + + Returns + ------- + bool + Either if the ports are connected to reference_name or not. + + Examples + -------- + >>>edb = Edb() + >>> edb.hfss.create_edge_port_vertical(prim_1_id, ["-66mm", "-4mm"], "port_ver") + >>> edb.hfss.create_edge_port_horizontal( + >>> ... prim_1_id, ["-60mm", "-4mm"], prim_2_id, ["-59mm", "-4mm"], "port_hori", 30, "Lower" + >>> ... ) + >>> edb.hfss.create_wave_port(traces[0].id, trace_paths[0][0], "wave_port") + >>> edb.cutout(["Net1"]) + >>> assert edb.are_port_reference_terminals_connected() + """ + all_sources = [i for i in self.excitations.values() if not isinstance(i, (WavePort, GapPort, BundleWavePort))] + all_sources.extend([i for i in self.sources.values()]) + if not all_sources: + return True + self.logger.reset_timer() + if not common_reference: + common_reference = list(set([i.reference_net_name for i in all_sources if i.reference_net_name])) + if len(common_reference) > 1: + self.logger.error("More than 1 reference found.") + return False + if not common_reference: + self.logger.error("No Reference found.") + return False + + common_reference = common_reference[0] + all_sources = [i for i in all_sources if i.net_name != common_reference] + + setList = [ + set(i.reference_object.get_connected_object_id_set()) + for i in all_sources + if i.reference_object and i.reference_net_name == common_reference + ] + if len(setList) != len(all_sources): + self.logger.error("No Reference found.") + return False + cmps = [ + i + for i in list(self.components.resistors.values()) + if i.numpins == 2 and common_reference in i.nets and self._decompose_variable_value(i.res_value) <= 1 + ] + cmps.extend( + [i for i in list(self.components.inductors.values()) if i.numpins == 2 and common_reference in i.nets] + ) + + for cmp in cmps: + found = False + ids = [i.GetId() for i in cmp.pinlist] + for list_obj in setList: + if len(set(ids).intersection(list_obj)) == 1: + for list_obj2 in setList: + if list_obj2 != list_obj and len(set(ids).intersection(list_obj)) == 1: + if (ids[0] in list_obj and ids[1] in list_obj2) or ( + ids[1] in list_obj and ids[0] in list_obj2 + ): + setList[setList.index(list_obj)] = list_obj.union(list_obj2) + setList[setList.index(list_obj2)] = list_obj.union(list_obj2) + found = True + break + if found: + break + + # Get the set intersections for all the ID sets. + iDintersection = set.intersection(*setList) + self.logger.info_timer( + "Terminal reference primitive IDs total intersections = {}\n\n".format(len(iDintersection)) + ) + + # If the intersections are non-zero, the terminal references are connected. + return True if len(iDintersection) > 0 else False + + @pyaedt_function_handler() + def new_simulation_configuration(self, filename=None): + # type: (str) -> SimulationConfiguration + """New SimulationConfiguration Object. + + Parameters + ---------- + filename : str, optional + Input config file. + + Returns + ------- + :class:`pyaedt.edb_core.edb_data.simulation_configuration.SimulationConfiguration` + """ + return SimulationConfiguration(filename, self) + + @property + def setups(self): + """Get the dictionary of all EDB HFSS and SIwave setups. + + Returns + ------- + Dict[str, :class:`pyaedt.edb_core.edb_data.hfss_simulation_setup_data.HfssSimulationSetup`] or + Dict[str, :class:`pyaedt.edb_core.edb_data.siwave_simulation_setup_data.SiwaveDCSimulationSetup`] or + Dict[str, :class:`pyaedt.edb_core.edb_data.siwave_simulation_setup_data.SiwaveSYZSimulationSetup`] + + """ + for i in list(self.active_cell.SimulationSetups): + if i.GetName() not in self._setups: + if i.GetType() == self.edb_api.utility.utility.SimulationSetupType.kHFSS: + self._setups[i.GetName()] = HfssSimulationSetup(self, i.GetName(), i) + elif i.GetType() == self.edb_api.utility.utility.SimulationSetupType.kSIWave: + self._setups[i.GetName()] = SiwaveSYZSimulationSetup(self, i.GetName(), i) + elif i.GetType() == self.edb_api.utility.utility.SimulationSetupType.kSIWaveDCIR: + self._setups[i.GetName()] = SiwaveDCSimulationSetup(self, i.GetName(), i) + return self._setups + + @property + def hfss_setups(self): + """Active HFSS setup in EDB. + + Returns + ------- + Dict[str, :class:`pyaedt.edb_core.edb_data.hfss_simulation_setup_data.HfssSimulationSetup`] + + """ + return {name: i for name, i in self.setups.items() if i.setup_type == "kHFSS"} + + @property + def siwave_dc_setups(self): + """Active Siwave DC IR Setups. + + Returns + ------- + Dict[str, :class:`pyaedt.edb_core.edb_data.siwave_simulation_setup_data.SiwaveDCSimulationSetup`] + """ + return {name: i for name, i in self.setups.items() if i.setup_type == "kSIWaveDCIR"} + + @property + def siwave_ac_setups(self): + """Active Siwave SYZ setups. + + Returns + ------- + Dict[str, :class:`pyaedt.edb_core.edb_data.siwave_simulation_setup_data.SiwaveSYZSimulationSetup`] + """ + return {name: i for name, i in self.setups.items() if i.setup_type == "kSIWave"} + + def create_hfss_setup(self, name=None): + """Create a setup from a template. + + Parameters + ---------- + name : str, optional + Setup name. + + Returns + ------- + :class:`pyaedt.edb_core.edb_data.hfss_simulation_setup_data.HfssSimulationSetup` + + Examples + -------- + >>> setup1 = edbapp.create_hfss_setup("setup1") + >>> setup1.hfss_port_settings.max_delta_z0 = 0.5 + """ + if name in self.setups: + return False + setup = HfssSimulationSetup(self, name) + self._setups[name] = setup + return setup + + @pyaedt_function_handler() + def create_siwave_syz_setup(self, name=None): + """Create a setup from a template. + + Parameters + ---------- + name : str, optional + Setup name. + + Returns + ------- + :class:`pyaedt.edb_core.edb_data.siwave_simulation_setup_data.SiwaveSYZSimulationSetup` + + Examples + -------- + >>> setup1 = edbapp.create_siwave_syz_setup("setup1") + >>> setup1.add_frequency_sweep(frequency_sweep=[ + ... ["linear count", "0", "1kHz", 1], + ... ["log scale", "1kHz", "0.1GHz", 10], + ... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"], + ... ]) + """ + if not name: + name = generate_unique_name("Siwave_SYZ") + if name in self.setups: + return False + setup = SiwaveSYZSimulationSetup(self, name) + self._setups[name] = setup + return setup + + @pyaedt_function_handler() + def create_siwave_dc_setup(self, name=None): + """Create a setup from a template. + + Parameters + ---------- + name : str, optional + Setup name. + + Returns + ------- + :class:`pyaedt.edb_core.edb_data.siwave_simulation_setup_data.SiwaveSYZSimulationSetup` + + Examples + -------- + >>> setup1 = edbapp.create_siwave_dc_setup("setup1") + >>> setup1.mesh_bondwires = True + + """ + if not name: + name = generate_unique_name("Siwave_DC") + if name in self.setups: + return False + setup = SiwaveDCSimulationSetup(self, name) + self._setups[name] = setup + return setup + + @pyaedt_function_handler() + def calculate_initial_extent(self, expansion_factor): + """Compute a float representing the larger number between the dielectric thickness or trace width + multiplied by the nW factor. The trace width search is limited to nets with ports attached. + + Parameters + ---------- + expansion_factor : float + Value for the width multiplier (nW factor). + + Returns + ------- + float + """ + nets = [] + for port in self.excitations.values(): + nets.append(port.net_name) + for port in self.sources.values(): + nets.append(port.net_name) + nets = list(set(nets)) + max_width = 0 + for net in nets: + for primitive in self.nets[net].primitives: + if primitive.type == "Path": + max_width = max(max_width, primitive.width) + + for layer in list(self.stackup.dielectric_layers.values()): + max_width = max(max_width, layer.thickness) + + max_width = max_width * expansion_factor + self.logger.info("The W factor is {}, The initial extent = {:e}".format(expansion_factor, max_width)) + return max_width + + @pyaedt_function_handler() + def copy_zones(self, working_directory=None): + """Copy multizone EDB project to one new edb per zone. + + Parameters + ---------- + working_directory : str + Directory path where all EDB project are copied, if empty will use the current EDB project. + + Returns + ------- + dict[str](int, EDB PolygonData) + Return a dictionary with edb path as key and tuple Zone Id as first item and EDB polygon Data defining + the region as second item. + + """ + if working_directory: + if not os.path.isdir(working_directory): + os.mkdir(working_directory) + else: + shutil.rmtree(working_directory) + os.mkdir(working_directory) + else: + working_directory = os.path.dirname(self.edbpath) + zone_primitives = list(self.layout.zone_primitives) + zone_ids = list(self.stackup._layer_collection.GetZoneIds()) + edb_zones = {} + if not self.setups: + self.siwave.add_siwave_syz_analysis() + self.save_edb() + for zone_primitive in zone_primitives: + edb_zone_path = os.path.join( + working_directory, "{}_{}".format(zone_primitive.GetId(), os.path.basename(self.edbpath)) + ) + shutil.copytree(self.edbpath, edb_zone_path) + poly_data = zone_primitive.GetPolygonData() + if self.version[0] >= 10: + edb_zones[edb_zone_path] = (zone_primitive.GetZoneId(), poly_data) + elif len(zone_primitives) == len(zone_ids): + edb_zones[edb_zone_path] = (zone_ids[0], poly_data) + else: + self.logger.info( + "Number of zone primitives is not equal to zone number. Zone information will be lost." + "Use Ansys 2024 R1 or later." + ) + edb_zones[edb_zone_path] = (-1, poly_data) + return edb_zones + + @pyaedt_function_handler() + def cutout_multizone_layout(self, zone_dict, common_reference_net=None): + """Create a multizone project cutout. + + Parameters + ---------- + zone_dict : dict[str](EDB PolygonData) + Dictionary with EDB path as key and EDB PolygonData as value defining the zone region. + This dictionary is returned from the command copy_zones(): + >>> edb = Edb(edb_file) + >>> zone_dict = edb.copy_zones(r"C:\Temp\test") + + common_reference_net : str + the common reference net name. This net name must be provided to provide a valid project. + + Returns + ------- + dict[str][str] , list of str + first dictionary defined_ports with edb name as key and existing port name list as value. Those ports are the + ones defined before processing the multizone clipping. + second is the list of connected port. + + """ + terminals = {} + defined_ports = {} + project_connexions = None + for edb_path, zone_info in zone_dict.items(): + edb = Edb(edbversion=self.edbversion, edbpath=edb_path) + edb.cutout(use_pyaedt_cutout=True, custom_extent=zone_info[1], open_cutout_at_end=True) + if not zone_info[0] == -1: + layers_to_remove = [ + lay.name for lay in list(edb.stackup.layers.values()) if not lay._edb_layer.IsInZone(zone_info[0]) + ] + for layer in layers_to_remove: + edb.stackup.remove_layer(layer) + edb.stackup.stackup_mode = "Laminate" + edb.cutout(use_pyaedt_cutout=True, custom_extent=zone_info[1], open_cutout_at_end=True) + edb.active_cell.SetName(os.path.splitext(os.path.basename(edb_path))[0]) + if common_reference_net: + signal_nets = list(self.nets.signal.keys()) + defined_ports[os.path.splitext(os.path.basename(edb_path))[0]] = list(edb.excitations.keys()) + edb_terminals_info = edb.hfss.create_vertical_circuit_port_on_clipped_traces( + nets=signal_nets, reference_net=common_reference_net, user_defined_extent=zone_info[1] + ) + if edb_terminals_info: + terminals[os.path.splitext(os.path.basename(edb_path))[0]] = edb_terminals_info + project_connexions = self._get_connected_ports_from_multizone_cutout(terminals) + edb.save_edb() + edb.close_edb() + return defined_ports, project_connexions + + @pyaedt_function_handler() + def _get_connected_ports_from_multizone_cutout(self, terminal_info_dict): + """Return connected port list from clipped multizone layout. + + Parameters + terminal_info_dict : dict[str][str] + dictionary terminals with edb name as key and created ports name on clipped signal nets. + Dictionary is generated by the command cutout_multizone_layout: + >>> edb = Edb(edb_file) + >>> edb_zones = edb.copy_zones(r"C:\Temp\test") + >>> defined_ports, terminals_info = edb.cutout_multizone_layout(edb_zones, common_reference_net) + >>> project_connexions = get_connected_ports(terminals_info) + + Returns + ------- + list[str] + list of connected ports. + """ + if terminal_info_dict: + tolerance = 1e-8 + connected_ports_list = [] + project_list = list(terminal_info_dict.keys()) + project_combinations = list(combinations(range(0, len(project_list)), 2)) + for comb in project_combinations: + terminal_set1 = terminal_info_dict[project_list[comb[0]]] + terminal_set2 = terminal_info_dict[project_list[comb[1]]] + project1_nets = [t[0] for t in terminal_set1] + project2_nets = [t[0] for t in terminal_set2] + net_with_connected_ports = list(set(project1_nets).intersection(project2_nets)) + if net_with_connected_ports: + for net_name in net_with_connected_ports: + project1_port_info = [term_info for term_info in terminal_set1 if term_info[0] == net_name] + project2_port_info = [term_info for term_info in terminal_set2 if term_info[0] == net_name] + port_list = [p[3] for p in project1_port_info] + [p[3] for p in project2_port_info] + port_combinations = list(combinations(port_list, 2)) + for port_combination in port_combinations: + if not port_combination[0] == port_combination[1]: + port1 = [port for port in terminal_set1 if port[3] == port_combination[0]] + if not port1: + port1 = [port for port in terminal_set2 if port[3] == port_combination[0]] + port2 = [port for port in terminal_set2 if port[3] == port_combination[1]] + if not port2: + port2 = [port for port in terminal_set1 if port[3] == port_combination[1]] + port1 = port1[0] + port2 = port2[0] + if not port1[3] == port2[3]: + port_distance = GeometryOperators.points_distance(port1[1:3], port2[1:3]) + if port_distance < tolerance: + port1_connexion = None + port2_connexion = None + for project_path, port_info in terminal_info_dict.items(): + port1_map = [port for port in port_info if port[3] == port1[3]] + if port1_map: + port1_connexion = (project_path, port1[3]) + port2_map = [port for port in port_info if port[3] == port2[3]] + if port2_map: + port2_connexion = (project_path, port2[3]) + if port1_connexion and port2_connexion: + if ( + not port1_connexion[0] == port2_connexion[0] + or not port1_connexion[1] == port2_connexion[1] + ): + connected_ports_list.append((port1_connexion, port2_connexion)) + return connected_ports_list diff --git a/src/pyedb/edb_logger.py b/src/pyedb/edb_logger.py new file mode 100644 index 0000000000..5aa2a9449a --- /dev/null +++ b/src/pyedb/edb_logger.py @@ -0,0 +1,361 @@ +# -*- coding: utf-8 -*- +import logging +from logging.handlers import RotatingFileHandler +import os +import shutil +import sys +import tempfile +import time + +from generic.settings import settings + + +class Msg: + (INFO, WARNING, ERROR, FATAL) = range(4) + + +class EdbLogger(object): + """ + Specifies the logger to use for EDB logger. + + This class allows you to add a handler to write messages to a file and to indicate + whether to write messages to the standard output (stdout). + + Parameters + ---------- + level : int, optional + Logging level to filter the message severity allowed in the logger. + The default is ``logging.DEBUG``. + filename : str, optional + Name of the file to write messages to. The default is ``None``. + to_stdout : bool, optional + Whether to write log messages to stdout. The default is ``False``. + """ + + def __init__(self, level=logging.DEBUG, filename=None, to_stdout=False): + self._std_out_handler = None + self._files_handlers = [] + self.level = level + self.filename = filename or settings.logger_file_path + settings.logger_file_path = self.filename + + self._global = logging.getLogger("Global") + if not settings.enable_logger: + self._global.addHandler(logging.NullHandler()) + return + + if settings.formatter: + self.formatter = settings.formatter + else: + self.formatter = logging.Formatter(settings.logger_formatter, datefmt=settings.logger_datefmt) + global_handler = False + if settings.enable_global_log_file: + for handler in self._global.handlers: + if settings.global_log_file_name in str(handler): + global_handler = True + break + log_file = os.path.join(tempfile.gettempdir(), settings.global_log_file_name) + my_handler = RotatingFileHandler( + log_file, + mode="a", + maxBytes=float(settings.global_log_file_size) * 1024 * 1024, + backupCount=2, + encoding=None, + delay=0, + ) + my_handler.setFormatter(self.formatter) + my_handler.setLevel(self.level) + if not global_handler and settings.global_log_file_name: + self._global.addHandler(my_handler) + self._files_handlers.append(my_handler) + if self.filename and os.path.exists(self.filename): + shutil.rmtree(self.filename, ignore_errors=True) + if self.filename and settings.enable_local_log_file: + self.add_file_logger(self.filename) + + if to_stdout: + settings.enable_screen_logs = True + self._std_out_handler = logging.StreamHandler(sys.stdout) + self._std_out_handler.setLevel(level) + _logger_stdout_formatter = logging.Formatter("PyANSYS-edb %(levelname)s: %(message)s") + + self._std_out_handler.setFormatter(_logger_stdout_formatter) + self._global.addHandler(self._std_out_handler) + self._timer = time.time() + + def add_file_logger(self, filename): + """Add a new file to the logger handlers list.""" + _file_handler = logging.FileHandler(filename) + _file_handler.setFormatter(self.formatter) + self.info("New logger file {} added to handlers.".format(filename)) + self._files_handlers.append(_file_handler) + return True + + def remove_file_logger(self, project_name): + """Remove a file from the logger handlers list.""" + handlers = [i for i in self._global.handlers] + for handler in self._files_handlers: + if "pyaedt_{}.log".format(project_name) in str(handler): + handler.close() + if handler in handlers: + self._global.removeHandler(handler) + self.info("logger file pyaedt_{}.log removed from handlers.".format(project_name)) + + @property + def _log_on_file(self): + return settings.enable_file_logs + + @_log_on_file.setter + def _log_on_file(self, val): + settings.enable_file_logs = val + + @property + def logger(self): + """EDB logger object.""" + if self._log_on_file: + return logging.getLogger("Global") + else: + return None # pragma: no cover + + def reset_timer(self, time_val=None): + """ "Reset actual timer to actual time or specified time. + + Parameters + ---------- + time_val : float, optional + Value time to apply. + + Returns + ------- + + """ + if time_val: + self._timer = time_val + else: + self._timer = time.time() + return self._timer + + def add_error_message(self, message_text): + """ + Add a type 2 "Error" message to the message manager tree. + + Also add an error message to the logger if the handler is present. + + Parameters + ---------- + message_text : str + Text to display as the error message. + + Examples + -------- + Add an error message to the AEDT message manager. + + >>> hfss.logger.project.error("Project Error Message", "Project") + + """ + self.add_message(2, message_text) + + def add_warning_message(self, message_text): + """ + Add a type 1 "Warning" message to the message manager tree. + + Also add a warning message to the logger if the handler is present. + + Parameters + ---------- + message_text : str + Text to display as the warning message. + + Examples + -------- + Add a warning message to the EDB message manager. + + >>> edb.logger.warning("Global warning message") + + """ + self.add_message(1, message_text) + + def add_info_message(self, message_text): + """Add a type 0 "Info" message to the active design level of the message manager tree. + + Also add an info message to the logger if the handler is present. + + Parameters + ---------- + message_text : str + Text to display as the info message. + + Examples + -------- + Add an info message at the global level. + + >>> edb.logger.info("Global warning message") + + """ + self.add_message(0, message_text) + + def add_debug_message(self, message_text): + """ + Parameterized message to the message manager to specify the type and project or design level. + + Parameters + ---------- + message_text : str + Text to display as the message. + level : str, optional + Level to add the info message to. Options are ``"Global"``, + ``"Project"``, and ``"Design"``. The default value is ``None``, + in which case the info message gets added to the ``"Design"`` + level. + """ + + return self.add_message(3, message_text) + + def add_message(self, message_type, message_text): + """Add a message to the message manager to specify the type and project or design level. + + Parameters + ---------- + message_type : int + Type of the message. Options are: + * ``0`` : Info + * ``1`` : Warning + * ``2`` : Error + * ``3`` : Debug + message_text : str + Text to display as the message. + """ + self._log_on_handler(message_type, message_text) + + def _log_on_handler(self, message_type, message_text, *args, **kwargs): + if not (self._log_on_file or self._log_on_screen) or not self._global: + return + if len(message_text) > 250: + message_text = message_text[:250] + "..." + if message_type == 0: + self._global.info(message_text, *args, **kwargs) + elif message_type == 1: + self._global.warning(message_text, *args, **kwargs) + elif message_type == 2: + self._global.error(message_text, *args, **kwargs) + elif message_type == 3: + self._global.debug(message_text, *args, **kwargs) + + def disable_stdout_log(self): + """Disable printing log messages to stdout.""" + self._log_on_screen = False + self._global.removeHandler(self._std_out_handler) + self.info("StdOut is disabled") + + def enable_stdout_log(self): + """Enable printing log messages to stdout.""" + self._log_on_screen = True + if not self._std_out_handler: + self._std_out_handler = logging.StreamHandler(sys.stdout) + self._std_out_handler.setLevel(self.level) + _logger_stdout_formatter = logging.Formatter("pyaedt %(levelname)s: %(message)s") + + self._std_out_handler.setFormatter(_logger_stdout_formatter) + self._global.addHandler(self._std_out_handler) + self._global.addHandler(self._std_out_handler) + self.info("StdOut is enabled") + + def disable_log_on_file(self): + """Disable writing log messages to an output file.""" + self._log_on_file = False + for _file_handler in self._files_handlers: + _file_handler.close() + self._global.removeHandler(_file_handler) + self.info("Log on file is disabled") + + def enable_log_on_file(self): + """Enable writing log messages to an output file.""" + self._log_on_file = True + for _file_handler in self._files_handlers: + self._global.addHandler(_file_handler) + self.info("Log on file is enabled") + + def info(self, msg, *args, **kwargs): + """Write an info message to the global logger.""" + if not settings.enable_logger: + return + if args: + try: + msg1 = msg % tuple(str(i) for i in args) + except TypeError: + msg1 = msg + else: + msg1 = msg + return self._log_on_handler(0, msg, *args, **kwargs) + + def info_timer(self, msg, start_time=None, *args, **kwargs): + """Write an info message to the global logger with elapsed time. + Message will have an appendix of type Elapsed time: time.""" + if not settings.enable_logger: + return + if not start_time: + start_time = self._timer + td = time.time() - start_time + m, s = divmod(td, 60) + h, m = divmod(m, 60) + d, h = divmod(h, 24) + if d > 0: + msg += " Elapsed time: {}days {}h {}m {}sec".format(round(d), round(h), round(m), round(s)) + elif h > 0: + msg += " Elapsed time: {}h {}m {}sec".format(round(h), round(m), round(s)) + else: + msg += " Elapsed time: {}m {}sec".format(round(m), round(s)) + if args: + try: + msg1 = msg % tuple(str(i) for i in args) + except TypeError: + msg1 = msg + else: + msg1 = msg + return self._log_on_handler(0, msg, *args, **kwargs) + + def warning(self, msg, *args, **kwargs): + """Write a warning message to the global logger.""" + if not settings.enable_logger: + return + if args: + try: + msg1 = msg % tuple(str(i) for i in args) + except TypeError: + msg1 = msg + else: + msg1 = msg + return self._log_on_handler(1, msg, *args, **kwargs) + + def error(self, msg, *args, **kwargs): + """Write an error message to the global logger.""" + if args: + try: + msg1 = msg % tuple(str(i) for i in args) + except TypeError: + msg1 = msg + else: + msg1 = msg + return self._log_on_handler(2, msg, *args, **kwargs) + + def debug(self, msg, *args, **kwargs): + """Write a debug message to the global logger.""" + if not settings.enable_debug_logger or not settings.enable_logger: + return + if args: + try: + msg1 = msg % tuple(str(i) for i in args) + except TypeError: + msg1 = msg + else: + msg1 = msg + return self._log_on_handler(3, msg, *args, **kwargs) + + @property + def glb(self): + """Global logger.""" + self._global = logging.getLogger("Global") + return self._global + + +pyedb_logger = EdbLogger(to_stdout=settings.enable_screen_logs) diff --git a/src/pyedb/generic/design_types.py b/src/pyedb/generic/design_types.py index 1a14e57361..46dbff1d89 100644 --- a/src/pyedb/generic/design_types.py +++ b/src/pyedb/generic/design_types.py @@ -81,7 +81,7 @@ def Edb( >>> app = Edb("/path/to/file/myfile.gds") """ - from pyaedt.edb import Edb as app + from pyedb.edb import Edb as app return app( edbpath=edbpath, @@ -96,48 +96,5 @@ def Edb( ) -app_map = {"EDB": Edb,} +app_map = {"EDB": Edb} - -def get_pyaedt_app(project_name=None, design_name=None): - """Returns the Pyaedt Object of specific project_name and design_name. - - Parameters - ---------- - project_name - design_name - - Returns - ------- - :def :`pyaedt.Hfss` - Any of the Pyaedt App initialized. - """ - main = sys.modules["__main__"] - if "oDesktop" in dir(main): - if project_name and project_name not in main.oDesktop.GetProjectList(): - raise AttributeError("Project {} doesn't exist in current Desktop.".format(project_name)) - if not project_name: - oProject = main.oDesktop.GetActiveProject() - else: - oProject = main.oDesktop.SetActiveProject(project_name) - if not oProject: - raise AttributeError("No Project Present.") - design_names = [] - deslist = list(oProject.GetTopDesignList()) - for el in deslist: - m = re.search(r"[^;]+$", el) - design_names.append(m.group(0)) - if design_name and design_name not in design_names: - raise AttributeError("Design {} doesn't exists in current Project.".format(design_name)) - if not design_name: - oDesign = oProject.GetActiveDesign() - else: - oDesign = oProject.SetActiveDesign(design_name) - if not oDesign: - raise AttributeError("No Design Present.") - design_type = oDesign.GetDesignType() - if design_type in list(app_map.keys()): - version = main.oDesktop.GetVersion().split(".") - v = ".".join([version[0], version[1]]) - return app_map[design_type](project_name, design_name, specified_version=v) - return None diff --git a/src/pyedb/generic/general_methods.py b/src/pyedb/generic/general_methods.py index 4783daeac9..7a5b5232e6 100644 --- a/src/pyedb/generic/general_methods.py +++ b/src/pyedb/generic/general_methods.py @@ -11,7 +11,7 @@ import inspect import itertools import traceback -from generic.settings import settings +from pyedb.generic.settings import settings def pyedb_function_handler(direct_func=None): diff --git a/src/pyedb/grpc/edb_data/components_data.py b/src/pyedb/grpc/edb_data/components_data.py index baf361072d..536575133a 100644 --- a/src/pyedb/grpc/edb_data/components_data.py +++ b/src/pyedb/grpc/edb_data/components_data.py @@ -2,11 +2,10 @@ import re import warnings -from edb_core.edb_data.padstacks_data import EDBPadstackInstance - +from padstacks_data import EDBPadstackInstance import numpy as np -from generic.general_methods import get_filename_without_extension -from generic.general_methods import pyedb_function_handler +from pyedb.generic.general_methods import get_filename_without_extension +from pyedb.generic.general_methods import pyedb_function_handler class EDBComponentDef(object): @@ -157,7 +156,7 @@ def rlc_enable(self, value): @property def resistance(self): - return self._pin_pair_rlc.R.ToDouble() # pragma: no cover + return self._pin_pair_rlc.R.value # pragma: no cover @resistance.setter def resistance(self, value): diff --git a/src/pyedb/grpc/edb_data/connectable.py b/src/pyedb/grpc/edb_data/connectable.py index feaa01131e..093d56891c 100644 --- a/src/pyedb/grpc/edb_data/connectable.py +++ b/src/pyedb/grpc/edb_data/connectable.py @@ -1,4 +1,4 @@ -from generic.general_methods import pyedb_function_handler +from pyedb.generic.general_methods import pyedb_function_handler class LayoutObj(object): diff --git a/src/pyedb/grpc/edb_data/control_file.py b/src/pyedb/grpc/edb_data/control_file.py index 5b59a3b740..c5913971b2 100644 --- a/src/pyedb/grpc/edb_data/control_file.py +++ b/src/pyedb/grpc/edb_data/control_file.py @@ -4,12 +4,12 @@ import sys import xml.etree.cElementTree as ET -from generic.general_methods import env_path -from generic.general_methods import env_value -from generic.general_methods import pyedb_function_handler -from edb_logger import pyedb_logger -from edb_core.misc.misc import list_installed_ansysem -from edb_core.misc.aedtlib_personalib_install import write_pretty_xml +from pyedb.generic.general_methods import env_path +from pyedb.generic.general_methods import env_value +from pyedb.generic.general_methods import pyedb_function_handler +from pyedb.edb_logger import pyedb_logger +from pyedb.misc.misc import list_installed_ansysem +from pyedb.misc.aedtlib_personalib_install import write_pretty_xml import subprocess diff --git a/src/pyedb/grpc/edb_data/hfss_extent_info.py b/src/pyedb/grpc/edb_data/hfss_extent_info.py index c707a31651..7054fa7c4a 100644 --- a/src/pyedb/grpc/edb_data/hfss_extent_info.py +++ b/src/pyedb/grpc/edb_data/hfss_extent_info.py @@ -1,5 +1,5 @@ from ansys.edb.utility import Value -from generic.general_methods import pyedb_function_handler +from pyedb.generic.general_methods import pyedb_function_handler from ansys.edb.utility import Value diff --git a/src/pyedb/grpc/edb_data/hfss_simulation_setup_data.py b/src/pyedb/grpc/edb_data/hfss_simulation_setup_data.py index 16c84a846a..b2b265ab63 100644 --- a/src/pyedb/grpc/edb_data/hfss_simulation_setup_data.py +++ b/src/pyedb/grpc/edb_data/hfss_simulation_setup_data.py @@ -1,5 +1,9 @@ -from generic.general_methods import generate_unique_name -from generic.general_methods import pyedb_function_handler +from pyedb.generic.general_methods import generate_unique_name +from pyedb.generic.general_methods import pyedb_function_handler +from ansys.edb.simulation_setup import SweepData +from ansys.edb.utility.value import Value +from ansys.edb.simulation_setup.hfss_simulation_settings import HFSSSimulationSettings +from ansys.edb.simulation_setup.hfss_simulation_setup import HfssSimulationSetup class EdbFrequencySweep(object): """Manages EDB methods for frequency sweep.""" @@ -15,16 +19,16 @@ def __init__(self, sim_setup, frequency_sweep=None, name=None, edb_sweep_data=No self._name = generate_unique_name("sweep") else: self._name = name - self._edb_sweep_data = self._sim_setup._edb.simsetupdata.SweepData(self._name) + self._edb_sweep_data = self._sim_setup._edb.sweep_data(self._name) self.set_frequencies(frequency_sweep) @pyedb_function_handler() def _update_sweep(self): """Update sweep.""" - self._sim_setup._edb_sim_setup_info.SweepDataList.Clear() + self._sim_setup.sweep_data.frequency_string = "" for el in list(self._sim_setup.frequency_sweeps.values()): - self._sim_setup._edb_sim_setup_info.SweepDataList.Add(el._edb_sweep_data) - self._sim_setup._edb_sim_setup_info.SweepDataList.Add(self._edb_sweep_data) + self._sim_setup.swee_data.add(el._edb_sweep_data) + self._sim_setup.sweep_data.add(self._edb_sweep_data) return self._sim_setup._update_setup() @property @@ -46,7 +50,7 @@ def sweep_type(self): @property def frequencies(self): """List of frequencies points.""" - return list(self._edb_sweep_data.Frequencies) + return self._edb_sweep_data.frequencies @property def adaptive_sampling(self): @@ -57,7 +61,7 @@ def adaptive_sampling(self): bool ``True`` if adaptive sampling is used, ``False`` otherwise. """ - return self._edb_sweep_data.AdaptiveSampling + return self._edb_sweep_data.adaptive_sampling @property def adv_dc_extrapolation(self): @@ -69,7 +73,7 @@ def adv_dc_extrapolation(self): ``True`` if advanced DC Extrapolation is used, ``False`` otherwise. """ - return self._edb_sweep_data.AdvDCExtrapolation + return self._edb_sweep_data.adv_dc_extrapolation @property def auto_s_mat_only_solve(self): @@ -80,7 +84,7 @@ def auto_s_mat_only_solve(self): bool ``True`` if Auto/Manual SMatrix only solve is used, ``False`` otherwise. """ - return self._edb_sweep_data.AutoSMatOnlySolve + return self._edb_sweep_data.auto_s_mat_only_solve @property def enforce_causality(self): @@ -91,7 +95,7 @@ def enforce_causality(self): bool ``True`` if enforce causality is used, ``False`` otherwise. """ - return self._edb_sweep_data.EnforceCausality + return self._edb_sweep_data.enforce_causality @property def enforce_dc_and_causality(self): @@ -103,7 +107,7 @@ def enforce_dc_and_causality(self): ``True`` if enforce dc point and causality is used, ``False`` otherwise. """ - return self._edb_sweep_data.EnforceDCAndCausality + return self._edb_sweep_data.enforce_dc_and_causality @property def enforce_passivity(self): @@ -114,7 +118,7 @@ def enforce_passivity(self): bool ``True`` if enforce passivity is used, ``False`` otherwise. """ - return self._edb_sweep_data.EnforcePassivity + return self._edb_sweep_data.enforce_passivity @property def freq_sweep_type(self): @@ -128,7 +132,7 @@ def freq_sweep_type(self): ------- str """ - return self._edb_sweep_data.FreqSweepType.ToString() + return self._edb_sweep_data.freq_sweeptype @property def interp_use_full_basis(self): @@ -139,7 +143,7 @@ def interp_use_full_basis(self): bool ``True`` if full basis interpolation is used, ``False`` otherwise. """ - return self._edb_sweep_data.InterpUseFullBasis + return self._edb_sweep_data.interp_use_full_basis @property def interp_use_port_impedance(self): @@ -150,7 +154,7 @@ def interp_use_port_impedance(self): bool ``True`` if port impedance is used, ``False`` otherwise. """ - return self._edb_sweep_data.InterpUsePortImpedance + return self._edb_sweep_data.interp_use_port_impedance @property def interp_use_prop_const(self): @@ -161,7 +165,7 @@ def interp_use_prop_const(self): bool ``True`` if propagation constants are used, ``False`` otherwise. """ - return self._edb_sweep_data.InterpUsePropConst + return self._edb_sweep_data.interp_use_prop_const @property def interp_use_s_matrix(self): @@ -172,7 +176,7 @@ def interp_use_s_matrix(self): bool ``True`` if S matrix are used, ``False`` otherwise. """ - return self._edb_sweep_data.InterpUseSMatrix + return self._edb_sweep_data.interp_use_s_matrix @property def max_solutions(self): @@ -182,7 +186,7 @@ def max_solutions(self): ------- int """ - return self._edb_sweep_data.MaxSolutions + return self._edb_sweep_data.max_solutions @property def min_freq_s_mat_only_solve(self): @@ -193,7 +197,7 @@ def min_freq_s_mat_only_solve(self): str Frequency with units. """ - return self._edb_sweep_data.MinFreqSMatOnlySolve + return self._edb_sweep_data.min_freq_s_mat_only_solve @property def min_solved_freq(self): @@ -204,7 +208,7 @@ def min_solved_freq(self): str Frequency with units. """ - return self._edb_sweep_data.MinSolvedFreq + return self._edb_sweep_data.min_solved_freq @property def passivity_tolerance(self): @@ -214,7 +218,7 @@ def passivity_tolerance(self): ------- float """ - return self._edb_sweep_data.PassivityTolerance + return self._edb_sweep_data.passivity_tolerance @property def relative_s_error(self): @@ -224,7 +228,7 @@ def relative_s_error(self): ------- float """ - return self._edb_sweep_data.RelativeSError + return self._edb_sweep_data.relative_s_error @property def save_fields(self): @@ -235,7 +239,7 @@ def save_fields(self): bool ``True`` if save fields is enabled, ``False`` otherwise. """ - return self._edb_sweep_data.SaveFields + return self._edb_sweep_data.save_fields @property def save_rad_fields_only(self): @@ -247,7 +251,7 @@ def save_rad_fields_only(self): ``True`` if save radiated field only is used, ``False`` otherwise. """ - return self._edb_sweep_data.SaveRadFieldsOnly + return self._edb_sweep_data.save_rad_fields_only @property def use_q3d_for_dc(self): @@ -258,117 +262,116 @@ def use_q3d_for_dc(self): bool ``True`` if Q3d for DC point is used, ``False`` otherwise. """ - return self._edb_sweep_data.UseQ3DForDC + return self._edb_sweep_data.use_q3d_for_dc @adaptive_sampling.setter def adaptive_sampling(self, value): - self._edb_sweep_data.AdaptiveSampling = value + self._edb_sweep_data.adaptive_sampling = value self._update_sweep() @adv_dc_extrapolation.setter def adv_dc_extrapolation(self, value): - self._edb_sweep_data.AdvDCExtrapolation = value + self._edb_sweep_data.adv_dc_extrapolation = value self._update_sweep() @auto_s_mat_only_solve.setter def auto_s_mat_only_solve(self, value): - self._edb_sweep_data.AutoSMatOnlySolve = value + self._edb_sweep_data.auto_s_mat_only_solve = value self._update_sweep() @enforce_causality.setter def enforce_causality(self, value): - self._edb_sweep_data.EnforceCausality = value + self._edb_sweep_data.enforce_causality = value self._update_sweep() @enforce_dc_and_causality.setter def enforce_dc_and_causality(self, value): - self._edb_sweep_data.EnforceDCAndCausality = value + self._edb_sweep_data.enforce_dc_and_causality = value self._update_sweep() @enforce_passivity.setter def enforce_passivity(self, value): - self._edb_sweep_data.EnforcePassivity = value + self._edb_sweep_data.enforce_passivity = value self._update_sweep() @freq_sweep_type.setter def freq_sweep_type(self, value): - edb_freq_sweep_type = self._edb_sweep_data.TFreqSweepType - if value in [0, "kInterpolatingSweep"]: - self._edb_sweep_data.FreqSweepType = edb_freq_sweep_type.kInterpolatingSweep - elif value in [1, "kDiscreteSweep"]: - self._edb_sweep_data.FreqSweepType = edb_freq_sweep_type.kDiscreteSweep - elif value in [2, "kBroadbandFastSweep"]: - self._edb_sweep_data.FreqSweepType = edb_freq_sweep_type.kBroadbandFastSweep - elif value in [3, "kNumSweepTypes"]: - self._edb_sweep_data.FreqSweepType = edb_freq_sweep_type.kNumSweepTypes - self._edb_sweep_data.FreqSweepType.ToString() + edb_freq_sweep_type = self._edb_sweep_data.t_freq_sweep_type + if value in [0, "InterpolatingSweep"]: + self._edb_sweep_data.freq_sweep_type = edb_freq_sweep_type.interpolating_sweep + elif value in [1, "DiscreteSweep"]: + self._edb_sweep_data.freq_sweep_type = edb_freq_sweep_type.discrete_sweep + elif value in [2, "BroadbandFastSweep"]: + self._edb_sweep_data.freq_sweep_type = edb_freq_sweep_type.broadband_fast_sweep + elif value in [3, "NumSweepTypes"]: + self._edb_sweep_data.freq_sweep_type = edb_freq_sweep_type.num_sweep_types @interp_use_full_basis.setter def interp_use_full_basis(self, value): - self._edb_sweep_data.InterpUseFullBasis = value + self._edb_sweep_data.interp_use_full_basis = value self._update_sweep() @interp_use_port_impedance.setter def interp_use_port_impedance(self, value): - self._edb_sweep_data.InterpUsePortImpedance = value + self._edb_sweep_data.interp_use_port_impedance = value self._update_sweep() @interp_use_prop_const.setter def interp_use_prop_const(self, value): - self._edb_sweep_data.InterpUsePropConst = value + self._edb_sweep_data.interp_use_prop_const = value self._update_sweep() @interp_use_s_matrix.setter def interp_use_s_matrix(self, value): - self._edb_sweep_data.InterpUseSMatrix = value + self._edb_sweep_data.interp_use_s_matrix = value self._update_sweep() @max_solutions.setter def max_solutions(self, value): - self._edb_sweep_data.MaxSolutions = value + self._edb_sweep_data.max_solutions = value self._update_sweep() @min_freq_s_mat_only_solve.setter def min_freq_s_mat_only_solve(self, value): - self._edb_sweep_data.MinFreqSMatOnlySolve = value + self._edb_sweep_data.min_freq_s_mat_only_solve = value self._update_sweep() @min_solved_freq.setter def min_solved_freq(self, value): - self._edb_sweep_data.MinSolvedFreq = value + self._edb_sweep_data.min_solved_freq = value self._update_sweep() @passivity_tolerance.setter def passivity_tolerance(self, value): - self._edb_sweep_data.PassivityTolerance = value + self._edb_sweep_data.passivity_tolerance = value self._update_sweep() @relative_s_error.setter def relative_s_error(self, value): - self._edb_sweep_data.RelativeSError = value + self._edb_sweep_data.relative_s_error = value self._update_sweep() @save_fields.setter def save_fields(self, value): - self._edb_sweep_data.SaveFields = value + self._edb_sweep_data.save_fields = value self._update_sweep() @save_rad_fields_only.setter def save_rad_fields_only(self, value): - self._edb_sweep_data.SaveRadFieldsOnly = value + self._edb_sweep_data.save_rad_fields_only = value self._update_sweep() @use_q3d_for_dc.setter def use_q3d_for_dc(self, value): - self._edb_sweep_data.UseQ3DForDC = value + self._edb_sweep_data.use_q3d_for_dc = value self._update_sweep() - @pyaedt_function_handler() + @pyedb_function_handler() def _set_frequencies(self, freq_sweep_string="Linear Step: 0GHz to 20GHz, step=0.05GHz"): - self._edb_sweep_data.SetFrequencies(freq_sweep_string) + self._edb_sweep_data.frequency_string = freq_sweep_string self._update_sweep() - @pyaedt_function_handler() + @pyedb_function_handler() def set_frequencies_linear_scale(self, start="0.1GHz", stop="20GHz", step="50MHz"): """Set a linear scale frequency sweep. @@ -387,10 +390,10 @@ def set_frequencies_linear_scale(self, start="0.1GHz", stop="20GHz", step="50MHz ``True`` if correctly executed, ``False`` otherwise. """ - self._edb_sweep_data.Frequencies = self._edb_sweep_data.SetFrequencies(start, stop, step) + self._edb_sweep_data.frequency_string = self._edb_sweep_data(start_f=start, stop_f=stop, step=step) return self._update_sweep() - @pyaedt_function_handler() + @pyedb_function_handler() def set_frequencies_linear_count(self, start="1kHz", stop="0.1GHz", count=10): """Set a linear count frequency sweep. @@ -411,10 +414,10 @@ def set_frequencies_linear_count(self, start="1kHz", stop="0.1GHz", count=10): """ start = self._sim_setup._edb.arg_to_dim(start, "Hz") stop = self._sim_setup._edb.arg_to_dim(stop, "Hz") - self._edb_sweep_data.Frequencies = self._edb_sweep_data.SetFrequencies(start, stop, count) + self._edb_sweep_data.frequency_string = self._edb_sweep_data.frequency_string(start, stop, count) return self._update_sweep() - @pyaedt_function_handler() + @pyedb_function_handler() def set_frequencies_log_scale(self, start="1kHz", stop="0.1GHz", samples=10): """Set a log count frequency sweep. @@ -434,10 +437,10 @@ def set_frequencies_log_scale(self, start="1kHz", stop="0.1GHz", samples=10): """ start = self._sim_setup._edb.arg_to_dim(start, "Hz") stop = self._sim_setup._edb.arg_to_dim(stop, "Hz") - self._edb_sweep_data.Frequencies = self._edb_sweep_data.SetLogFrequencies(start, stop, samples) + self._edb_sweep_data.frequency_stringequencies = self._edb_sweep_data.log_frequencies(start, stop, samples) return self._update_sweep() - @pyaedt_function_handler() + @pyedb_function_handler() def set_frequencies(self, frequency_list=None): """Set frequency list to the sweep frequencies. @@ -560,8 +563,8 @@ def nets_layers_list(self, values): temp = [] for net, layers in values.items(): for layer in layers: - temp.append(Tuple[str, str, bool](net, layer, True)) - self.mesh_operation.NetsLayersList = convert_py_list_to_net_list(temp) + temp.append(net, layer, True) + self.mesh_operation.NetsLayersList = temp @property def refine_inside(self): @@ -573,26 +576,26 @@ def refine_inside(self): ``True`` if refine inside objects is used, ``False`` otherwise. """ - return self.mesh_operation.RefineInside + return self.mesh_operation.refine_inside @enabled.setter def enabled(self, value): - self.mesh_operation.Enabled = value + self.mesh_operation.enabled = value self._parent._update_setup() @mesh_region.setter def mesh_region(self, value): - self.mesh_operation.MeshRegion = value + self.mesh_operation.mesh_region = value self._parent._update_setup() @name.setter def name(self, value): - self.mesh_operation.Name = value + self.mesh_operation.name = value self._parent._update_setup() @refine_inside.setter def refine_inside(self, value): - self.mesh_operation.RefineInside = value + self.mesh_operation.refine_inside = value self._parent._update_setup() @property @@ -603,7 +606,7 @@ def max_elements(self): ------- str """ - return self.mesh_operation.MaxElems + return self.mesh_operation.max_elems @property def restrict_max_elements(self): @@ -613,11 +616,11 @@ def restrict_max_elements(self): ------- bool """ - return self.mesh_operation.RestrictMaxElem + return self.mesh_operation.restrict_max_elem @max_elements.setter def max_elements(self, value): - self.mesh_operation.MaxElems = str(value) + self.mesh_operation.max_elems = value self._parent._update_setup() @restrict_max_elements.setter @@ -628,7 +631,7 @@ def restrict_max_elements(self, value): ------- bool """ - self.mesh_operation.RestrictMaxElem = value + self.mesh_operation.restrict_max_elem = value self._parent._update_setup() @@ -653,7 +656,7 @@ def max_length(self): ------- str """ - return self.mesh_operation.MaxLength + return self.mesh_operation.max_length @property def restrict_length(self): @@ -663,11 +666,11 @@ def restrict_length(self): ------- bool """ - return self.mesh_operation.RestrictLength + return self.mesh_operation.restrict_length @max_length.setter def max_length(self, value): - self.mesh_operation.MaxLength = value + self.mesh_operation.max_length = value self._parent._update_setup() @restrict_length.setter @@ -678,7 +681,7 @@ def restrict_length(self, value): ------- bool """ - self.mesh_operation.RestrictLength = value + self.mesh_operation.restrict_length = value self._parent._update_setup() @@ -703,11 +706,11 @@ def skin_depth(self): ------- str """ - return self.mesh_operation.SkinDepth + return self.mesh_operation.skin_depth @skin_depth.setter def skin_depth(self, value): - self.mesh_operation.SkinDepth = value + self.mesh_operation.skin_depth = value self._parent._update_setup() @property @@ -718,11 +721,11 @@ def surface_triangle_length(self): ------- str """ - return self.mesh_operation.SurfTriLength + return self.mesh_operation.surf_tri_length @surface_triangle_length.setter def surface_triangle_length(self, value): - self.mesh_operation.SurfTriLength = value + self.mesh_operation.surf_tri_length = value self._parent._update_setup() @property @@ -733,11 +736,11 @@ def number_of_layer_elements(self): ------- str """ - return self.mesh_operation.NumLayers + return self.mesh_operation.num_layers @number_of_layer_elements.setter def number_of_layer_elements(self, value): - self.mesh_operation.NumLayers = str(value) + self.mesh_operation.num_layers = value self._parent._update_setup() @@ -749,7 +752,7 @@ def __init__(self, parent): @property def _hfss_port_settings(self): - return self._parent._edb_sim_setup_info.SimulationSettings.HFSSPortSettings + return self._parent._edb_sim_setup_info.simulation_settings.hfsss_port_settings @property def max_delta_z0(self): @@ -759,11 +762,11 @@ def max_delta_z0(self): ------- float """ - return self._hfss_port_settings.MaxDeltaZ0 + return self._hfss_port_settings.max_delta_z0 @max_delta_z0.setter def max_delta_z0(self, value): - self._hfss_port_settings.MaxDeltaZ0 = value + self._hfss_port_settings.max_delta_z0 = value self._parent._update_setup() @property @@ -774,11 +777,11 @@ def max_triangles_wave_port(self): ------- int """ - return self._hfss_port_settings.MaxTrianglesWavePort + return self._hfss_port_settings.max_triangles_wave_port @max_triangles_wave_port.setter def max_triangles_wave_port(self, value): - self._hfss_port_settings.MaxTrianglesWavePort = value + self._hfss_port_settings.max_triangles_wave_port = value self._parent._update_setup() @property @@ -789,11 +792,11 @@ def min_triangles_wave_port(self): ------- int """ - return self._hfss_port_settings.MinTrianglesWavePort + return self._hfss_port_settings.min_triangles_wave_port @min_triangles_wave_port.setter def min_triangles_wave_port(self, value): - self._hfss_port_settings.MinTrianglesWavePort = value + self._hfss_port_settings.min_triangles_wave_port = value self._parent._update_setup() @property @@ -805,11 +808,11 @@ def enable_set_triangles_wave_port(self): bool ``True`` if triangles wave port is used, ``False`` otherwise. """ - return self._hfss_port_settings.SetTrianglesWavePort + return self._hfss_port_settings.triangles_wave_port @enable_set_triangles_wave_port.setter def enable_set_triangles_wave_port(self, value): - self._hfss_port_settings.SetTrianglesWavePort = value + self._hfss_port_settings.triangles_wave_port = value self._parent._update_setup() @@ -821,7 +824,7 @@ def __init__(self, parent): @property def _hfss_solver_settings(self): - return self._parent._edb_sim_setup_info.SimulationSettings.HFSSSolverSettings + return self._parent._edb_sim_setup_info.simulation_settings.hfss_solver_settings @property def enhanced_low_freq_accuracy(self): @@ -832,11 +835,11 @@ def enhanced_low_freq_accuracy(self): bool ``True`` if low frequency accuracy is used, ``False`` otherwise. """ - return self._hfss_solver_settings.EnhancedLowFreqAccuracy + return self._hfss_solver_settings.enhanced_low_freq_accuracy @enhanced_low_freq_accuracy.setter def enhanced_low_freq_accuracy(self, value): - self._hfss_solver_settings.EnhancedLowFreqAccuracy = value + self._hfss_solver_settings.enhanced_low_freq_accuracy = value self._parent._update_setup() @property @@ -852,12 +855,12 @@ def order_basis(self): int Integer value according to the description.""" mapping = {0: "zero", 1: "first", 2: "second", 3: "mixed"} - return mapping[self._hfss_solver_settings.OrderBasis] + return mapping[self._hfss_solver_settings.order_basis] @order_basis.setter def order_basis(self, value): mapping = {"zero": 0, "first": 1, "second": 2, "mixed": 3} - self._hfss_solver_settings.OrderBasis = mapping[value] + self._hfss_solver_settings.order_basis = mapping[value] self._parent._update_setup() @property @@ -868,11 +871,11 @@ def relative_residual(self): ------- float """ - return self._hfss_solver_settings.RelativeResidual + return self._hfss_solver_settings.relative_residual @relative_residual.setter def relative_residual(self, value): - self._hfss_solver_settings.RelativeResidual = value + self._hfss_solver_settings.relative_residual = value self._parent._update_setup() @property @@ -889,17 +892,17 @@ def solver_type(self): str """ mapping = {"kAutoSolver": "auto", "kDirectSolver": "direct", "kIterativeSolver": "iterative"} - solver_type = self._hfss_solver_settings.SolverType.ToString() + solver_type = self._hfss_solver_settings.solver_type return mapping[solver_type] @solver_type.setter def solver_type(self, value): mapping = { - "auto": self._hfss_solver_settings.SolverType.kAutoSolver, - "direct": self._hfss_solver_settings.SolverType.kDirectSolver, - "iterative": self._hfss_solver_settings.SolverType.kIterativeSolver, + "auto": self._hfss_solver_settings.solver_type.auto_solver, + "direct": self._hfss_solver_settings.solver_type.direct_solver, + "iterative": self._hfss_solver_settings.solver_type.iterative_solver, } - self._hfss_solver_settings.SolverType = mapping[value] + self._hfss_solver_settings.solver_type = mapping[value] self._parent._update_setup() @property @@ -911,11 +914,11 @@ def use_shell_elements(self): bool ``True`` if shall elements are used, ``False`` otherwise. """ - return self._hfss_solver_settings.UseShellElements + return self._hfss_solver_settings.use_shell_elements @use_shell_elements.setter def use_shell_elements(self, value): - self._hfss_solver_settings.UseShellElements = value + self._hfss_solver_settings.use_shell_elements = value self._parent._update_setup() @@ -934,11 +937,11 @@ def adaptive_frequency(self): str Frequency with units. """ - return self._adaptive_frequency_data.AdaptiveFrequency + return self._adaptive_frequency_data.adaptive_frequency @adaptive_frequency.setter def adaptive_frequency(self, value): - self._adaptive_frequency_data.AdaptiveFrequency = value + self._adaptive_frequency_data.adaptive_frequency = value @property def max_delta(self): @@ -949,11 +952,11 @@ def max_delta(self): ------- str """ - return self._adaptive_frequency_data.MaxDelta + return self._adaptive_frequency_data.max_delta @max_delta.setter def max_delta(self, value): - self._adaptive_frequency_data.MaxDelta = str(value) + self._adaptive_frequency_data.max_delta = str(value) @property def max_passes(self): @@ -963,11 +966,11 @@ def max_passes(self): ------- int """ - return self._adaptive_frequency_data.MaxPasses + return self._adaptive_frequency_data.max_passes @max_passes.setter def max_passes(self, value): - self._adaptive_frequency_data.MaxPasses = value + self._adaptive_frequency_data.max_passes = value class AdaptiveSettings(object): @@ -976,10 +979,10 @@ class AdaptiveSettings(object): def __init__(self, parent): self._parent = parent self._adapt_type_mapping = { - "kSingle": self.adaptive_settings.AdaptType.kSingle, - "kMultiFrequencies": self.adaptive_settings.AdaptType.kMultiFrequencies, - "kBroadband": self.adaptive_settings.AdaptType.kBroadband, - "kNumAdaptTypes": self.adaptive_settings.AdaptType.kNumAdaptTypes, + "single": self.adaptive_settings.adapt_type.single, + "multi_frequencies": self.adaptive_settings.adapt_type.multi_frequencies, + "broadband": self.adaptive_settings.adapt_type.broadband, + "num_adapt_types": self.adaptive_settings.adapt_type.mum_adapt_types, } @property @@ -990,7 +993,7 @@ def adaptive_settings(self): ------- :class:`pyaedt.edb_core.edb_data.hfss_simulation_setup_data.AdaptiveSettings` """ - return self._parent._edb_sim_setup_info.SimulationSettings.AdaptiveSettings + return self._parent._edb_sim_setup_info.simulation_settings.adaptive_settings @property def adaptive_frequency_data_list(self): @@ -1000,7 +1003,7 @@ def adaptive_frequency_data_list(self): ------- :class:`pyaedt.edb_core.edb_data.hfss_simulation_setup_data.AdaptiveFrequencyData` """ - return [AdaptiveFrequencyData(i) for i in list(self.adaptive_settings.AdaptiveFrequencyDataList)] + return [AdaptiveFrequencyData(i) for i in list(self.adaptive_settings.adaptive_frequency_data)] @property def adapt_type(self): @@ -1015,11 +1018,11 @@ def adapt_type(self): ------- str """ - return self.adaptive_settings.AdaptType.ToString() + return self.adaptive_settings.adapt_type @adapt_type.setter def adapt_type(self, value): - self.adaptive_settings.AdaptType = self._adapt_type_mapping[value] + self.adaptive_settings.adapt_type = self._adapt_type_mapping[value] self._parent._update_setup() @property @@ -1030,7 +1033,7 @@ def basic(self): ------- ``True`` if bais adaptive is used, ``False`` otherwise. """ - return self.adaptive_settings.Basic + return self.adaptive_settings.basic @basic.setter def basic(self, value): @@ -1047,7 +1050,7 @@ def do_adaptive(self): ``True`` if adaptive is used, ``False`` otherwise. """ - return self.adaptive_settings.DoAdaptive + return self.adaptive_settings.do_adaptive @property def max_refinement(self): @@ -1057,11 +1060,11 @@ def max_refinement(self): ------- int """ - return self.adaptive_settings.MaxRefinement + return self.adaptive_settings.max_refinement @max_refinement.setter def max_refinement(self, value): - self.adaptive_settings.MaxRefinement = value + self.adaptive_settings.max_refinement = value self._parent._update_setup() @property @@ -1072,11 +1075,11 @@ def max_refine_per_pass(self): ------- int """ - return self.adaptive_settings.MaxRefinePerPass + return self.adaptive_settings.max_refine_per_pass @max_refine_per_pass.setter def max_refine_per_pass(self, value): - self.adaptive_settings.MaxRefinePerPass = value + self.adaptive_settings.max_refine_per_pass = value self._parent._update_setup() @property @@ -1087,11 +1090,11 @@ def min_passes(self): ------- int """ - return self.adaptive_settings.MinPasses + return self.adaptive_settings.min_passes @min_passes.setter def min_passes(self, value): - self.adaptive_settings.MinPasses = value + self.adaptive_settings.min_passes = value self._parent._update_setup() @property @@ -1103,11 +1106,11 @@ def save_fields(self): bool ``True`` if save fields is used, ``False`` otherwise. """ - return self.adaptive_settings.SaveFields + return self.adaptive_settings.save_fields @save_fields.setter def save_fields(self, value): - self.adaptive_settings.SaveFields = value + self.adaptive_settings.save_fields = value self._parent._update_setup() @property @@ -1120,11 +1123,11 @@ def save_rad_field_only(self): ``True`` if save radiated field only is used, ``False`` otherwise. """ - return self.adaptive_settings.SaveRadFieldsOnly + return self.adaptive_settings.save_rad_fields_only @save_rad_field_only.setter def save_rad_field_only(self, value): - self.adaptive_settings.SaveRadFieldsOnly = value + self.adaptive_settings.save_rad_fields_only = value self._parent._update_setup() @property @@ -1137,11 +1140,11 @@ def use_convergence_matrix(self): ``True`` if convergence matrix is used, ``False`` otherwise. """ - return self.adaptive_settings.UseConvergenceMatrix + return self.adaptive_settings.use_convergence_matrix @use_convergence_matrix.setter def use_convergence_matrix(self, value): - self.adaptive_settings.UseConvergenceMatrix = value + self.adaptive_settings.use_convergence_matrix = value self._parent._update_setup() @property @@ -1153,14 +1156,14 @@ def use_max_refinement(self): bool ``True`` if maximum refinement is used, ``False`` otherwise. """ - return self.adaptive_settings.UseMaxRefinement + return self.adaptive_settings.use_max_refinement @use_max_refinement.setter def use_max_refinement(self, value): - self.adaptive_settings.UseMaxRefinement = value + self.adaptive_settings.use_max_refinement = value self._parent._update_setup() - @pyaedt_function_handler() + @pyedb_function_handler() def add_adaptive_frequency_data(self, frequency=0, max_num_passes=10, max_delta_s=0.02): """Add a setup for frequency data. @@ -1178,15 +1181,15 @@ def add_adaptive_frequency_data(self, frequency=0, max_num_passes=10, max_delta_ bool ``True`` if method is successful, ``False`` otherwise. """ - low_freq_adapt_data = self._parent._edb.simsetupdata.AdaptiveFrequencyData() - low_freq_adapt_data.MaxDelta = self._parent._edb.edb_value(max_delta_s).ToString() - low_freq_adapt_data.MaxPasses = max_num_passes - low_freq_adapt_data.AdaptiveFrequency = self._parent._edb.edb_value(frequency).ToString() - self.adaptive_settings.AdaptiveFrequencyDataList.Clear() - self.adaptive_settings.AdaptiveFrequencyDataList.Add(low_freq_adapt_data) + low_freq_adapt_data = AdaptiveFrequencyData() + low_freq_adapt_data.max_delta = Value(max_delta_s) + low_freq_adapt_data.max_passes = max_num_passes + low_freq_adapt_data.adaptive_frequency = Value(frequency) + self.adaptive_settings.adaptive_frequency_data = "" + self.adaptive_settings.adaptive_frequency_data = low_freq_adapt_data return self._parent._update_setup() - @pyaedt_function_handler() + @pyedb_function_handler() def add_broadband_adaptive_frequency_data( self, low_frequency=0, high_frequency=10e9, max_num_passes=10, max_delta_s=0.02 ): @@ -1209,16 +1212,15 @@ def add_broadband_adaptive_frequency_data( ``True`` if method is successful, ``False`` otherwise. """ low_freq_adapt_data = self._parent._edb.simsetupdata.AdaptiveFrequencyData() - low_freq_adapt_data.MaxDelta = self._parent._edb.edb_value(max_delta_s).ToString() - low_freq_adapt_data.MaxPasses = max_num_passes - low_freq_adapt_data.AdaptiveFrequency = self._parent._edb.edb_value(low_frequency).ToString() + low_freq_adapt_data.max_delta = Value(max_delta_s) + low_freq_adapt_data.max_passes = max_num_passes + low_freq_adapt_data.adaptive_frequency = Value(low_frequency) high_freq_adapt_data = self._parent._edb.simsetupdata.AdaptiveFrequencyData() - high_freq_adapt_data.MaxDelta = self._parent._edb.edb_value(max_delta_s).ToString() - high_freq_adapt_data.MaxPasses = max_num_passes - high_freq_adapt_data.AdaptiveFrequency = self._parent._edb.edb_value(high_frequency).ToString() - self.adaptive_settings.AdaptiveFrequencyDataList.Clear() - self.adaptive_settings.AdaptiveFrequencyDataList.Add(low_freq_adapt_data) - self.adaptive_settings.AdaptiveFrequencyDataList.Add(high_freq_adapt_data) + high_freq_adapt_data.max_delta = Value(max_delta_s) + high_freq_adapt_data.may_passes = max_num_passes + high_freq_adapt_data.adaptive_fFrequency = Value(high_frequency) + self.adaptive_settings.adaptive_frequency_data = "" + self.adaptive_settings.adaptive_frequency_data = [low_freq_adapt_data, high_freq_adapt_data] return self._parent._update_setup() @@ -1230,7 +1232,7 @@ def __init__(self, parent): @property def _defeature_settings(self): - return self._parent._edb_sim_setup_info.SimulationSettings.DefeatureSettings + return self._parent._edb_sim_setup_info.simulation_settings.defeature_settings @property def defeature_abs_length(self): @@ -1240,11 +1242,11 @@ def defeature_abs_length(self): ------- str """ - return self._defeature_settings.DefeatureAbsLength + return self._defeature_settings.defeature_abs_length @defeature_abs_length.setter def defeature_abs_length(self, value): - self._defeature_settings.DefeatureAbsLength = value + self._defeature_settings.defeature_abs_length = value self._parent._update_setup() @property @@ -1255,11 +1257,11 @@ def defeature_ratio(self): ------- float """ - return self._defeature_settings.DefeatureRatio + return self._defeature_settings.defeature_ratio @defeature_ratio.setter def defeature_ratio(self, value): - self._defeature_settings.DefeatureRatio = value + self._defeature_settings.defeature_ratio = value self._parent._update_setup() @property @@ -1273,11 +1275,11 @@ def healing_option(self): ------- int """ - return self._defeature_settings.HealingOption + return self._defeature_settings.healing_option @healing_option.setter def healing_option(self, value): - self._defeature_settings.HealingOption = value + self._defeature_settings.healing_option = value self._parent._update_setup() @property @@ -1291,12 +1293,12 @@ def model_type(self): ------- int """ - return self._defeature_settings.ModelType + return self._defeature_settings.model_type @model_type.setter def model_type(self, value): """Model type (General 0 or IC 1).""" - self._defeature_settings.ModelType = value + self._defeature_settings.model_type = value self._parent._update_setup() @property @@ -1308,11 +1310,11 @@ def remove_floating_geometry(self): bool ``True`` if floating geometry removal is used, ``False`` otherwise. """ - return self._defeature_settings.RemoveFloatingGeometry + return self._defeature_settings.remove_floating_geometry @remove_floating_geometry.setter def remove_floating_geometry(self, value): - self._defeature_settings.RemoveFloatingGeometry = value + self._defeature_settings.remove_floating_geometry = value self._parent._update_setup() @property @@ -1323,11 +1325,11 @@ def small_void_area(self): ------- float """ - return self._defeature_settings.SmallVoidArea + return self._defeature_settings.small_void_area @small_void_area.setter def small_void_area(self, value): - self._defeature_settings.SmallVoidArea = value + self._defeature_settings.small_void_area = value self._parent._update_setup() @property @@ -1339,11 +1341,11 @@ def union_polygons(self): bool ``True`` if union polygons is used, ``False`` otherwise. """ - return self._defeature_settings.UnionPolygons + return self._defeature_settings.union_polygons @union_polygons.setter def union_polygons(self, value): - self._defeature_settings.UnionPolygons = value + self._defeature_settings.union_polygons = value self._parent._update_setup() @property @@ -1355,11 +1357,11 @@ def use_defeature(self): bool ``True`` if defeature is used, ``False`` otherwise. """ - return self._defeature_settings.UseDefeature + return self._defeature_settings.use_defeature @use_defeature.setter def use_defeature(self, value): - self._defeature_settings.UseDefeature = value + self._defeature_settings.use_defeature = value self._parent._update_setup() @property @@ -1372,11 +1374,11 @@ def use_defeature_abs_length(self): ``True`` if defeature absolute length is used, ``False`` otherwise. """ - return self._defeature_settings.UseDefeatureAbsLength + return self._defeature_settings.use_defeature_abs_length @use_defeature_abs_length.setter def use_defeature_abs_length(self, value): - self._defeature_settings.UseDefeatureAbsLength = value + self._defeature_settings.use_defeature_abs_length = value self._parent._update_setup() @@ -1389,7 +1391,7 @@ def __init__( ): self._parent = parent self._via_style_mapping = { - "k25DViaWirebond": self._via_settings.T25DViaStyle.k25DViaWirebond, + "k25DViaWirebond": self._via_settings.t25_d_via_style.k25_d_via_wirebond, "k25DViaRibbon": self._via_settings.T25DViaStyle.k25DViaRibbon, "k25DViaMesh": self._via_settings.T25DViaStyle.k25DViaMesh, "k25DViaField": self._via_settings.T25DViaStyle.k25DViaField, @@ -1398,7 +1400,7 @@ def __init__( @property def _via_settings(self): - return self._parent._edb_sim_setup_info.SimulationSettings.ViaSettings + return self._parent._edb_sim_setup_info.simulation_settings.via_settings @property def via_density(self): @@ -1408,11 +1410,11 @@ def via_density(self): ------- float """ - return self._via_settings.ViaDensity + return self._via_settings.via_density @via_density.setter def via_density(self, value): - self._via_settings.ViaDensity = value + self._via_settings.via_density = value self._parent._update_setup() @property @@ -1423,11 +1425,11 @@ def via_material(self): ------- str """ - return self._via_settings.ViaMaterial + return self._via_settings.via_material @via_material.setter def via_material(self, value): - self._via_settings.ViaMaterial = value + self._via_settings.via_material = value self._parent._update_setup() @property @@ -1438,11 +1440,11 @@ def via_num_sides(self): ------- int """ - return self._via_settings.ViaNumSides + return self._via_settings.via_num_sides @via_num_sides.setter def via_num_sides(self, value): - self._via_settings.ViaNumSides = value + self._via_settings.via_num_sides = value self._parent._update_setup() @property @@ -1459,11 +1461,11 @@ def via_style(self): ------- str """ - return self._via_settings.ViaStyle.ToString() + return self._via_settings.via_style @via_style.setter def via_style(self, value): - self._via_settings.ViaStyle = self._via_style_mapping[value] + self._via_settings.via_style = self._via_style_mapping[value] self._parent._update_setup() @@ -1475,7 +1477,7 @@ def __init__(self, parent): @property def _advanced_mesh_settings(self): - return self._parent._edb_sim_setup_info.SimulationSettings.AdvancedMeshSettings + return self._parent._edb_sim_setup_info.simulation_settings.advanced_mesh_settings @property def layer_snap_tol(self): @@ -1486,11 +1488,11 @@ def layer_snap_tol(self): str """ - return self._advanced_mesh_settings.LayerSnapTol + return self._advanced_mesh_settings.layer_snap_tol @layer_snap_tol.setter def layer_snap_tol(self, value): - self._advanced_mesh_settings.LayerSnapTol = value + self._advanced_mesh_settings.layer_snap_tol = value self._parent._update_setup() @property @@ -1501,11 +1503,11 @@ def mesh_display_attributes(self): ------- str """ - return self._advanced_mesh_settings.MeshDisplayAttributes + return self._advanced_mesh_settings.mesh_display_attributes @mesh_display_attributes.setter def mesh_display_attributes(self, value): - self._advanced_mesh_settings.MeshDisplayAttributes = value + self._advanced_mesh_settings.mesh_display_attributes = value self._parent._update_setup() @property @@ -1518,11 +1520,11 @@ def replace_3d_triangles(self): ``True`` if replace 3D triangles is used, ``False`` otherwise. """ - return self._advanced_mesh_settings.Replace3DTriangles + return self._advanced_mesh_settings.replace_3D_triangles @replace_3d_triangles.setter def replace_3d_triangles(self, value): - self._advanced_mesh_settings.Replace3DTriangles = value + self._advanced_mesh_settings.replace_3D_triangles = value self._parent._update_setup() @@ -1534,7 +1536,7 @@ def __init__(self, parent): @property def _curve_approx_settings(self): - return self._parent._edb_sim_setup_info.SimulationSettings.CurveApproxSettings + return self._parent._edb_sim_setup_info.simulation_settings.curve_approx_settings @property def arc_angle(self): @@ -1544,11 +1546,11 @@ def arc_angle(self): ------- str """ - return self._curve_approx_settings.ArcAngle + return self._curve_approx_settings.arc_angle @arc_angle.setter def arc_angle(self, value): - self._curve_approx_settings.ArcAngle = value + self._curve_approx_settings.arc_angle = value self._parent._update_setup() @property @@ -1559,11 +1561,11 @@ def arc_to_chord_error(self): ------- str """ - return self._curve_approx_settings.ArcToChordError + return self._curve_approx_settings.arc_to_chord_error @arc_to_chord_error.setter def arc_to_chord_error(self, value): - self._curve_approx_settings.ArcToChordError = value + self._curve_approx_settings.arc_to_chord_error = value self._parent._update_setup() @property @@ -1574,11 +1576,11 @@ def max_arc_points(self): ------- int """ - return self._curve_approx_settings.MaxArcPoints + return self._curve_approx_settings.max_arc_points @max_arc_points.setter def max_arc_points(self, value): - self._curve_approx_settings.MaxArcPoints = value + self._curve_approx_settings.max_arc_points = value self._parent._update_setup() @property @@ -1589,11 +1591,11 @@ def start_azimuth(self): ------- str """ - return self._curve_approx_settings.StartAzimuth + return self._curve_approx_settings.start_azimuth @start_azimuth.setter def start_azimuth(self, value): - self._curve_approx_settings.StartAzimuth = value + self._curve_approx_settings.start_azimuth = value self._parent._update_setup() @property @@ -1604,11 +1606,11 @@ def use_arc_to_chord_error(self): ------- ``True`` if arc-to-chord error is used, ``False`` otherwise. """ - return self._curve_approx_settings.UseArcToChordError + return self._curve_approx_settings.use_arc_to_chord_error @use_arc_to_chord_error.setter def use_arc_to_chord_error(self, value): - self._curve_approx_settings.UseArcToChordError = value + self._curve_approx_settings.use_arc_to_chord_error = value self._parent._update_setup() @@ -1620,7 +1622,7 @@ def __init__(self, parent): @property def _dcr_settings(self): - return self._parent._edb_sim_setup_info.SimulationSettings.DCRSettings + return self._parent._edb_sim_setup_info.simulation_settings.dcr_settings @property def conduction_max_passes(self): @@ -1630,11 +1632,11 @@ def conduction_max_passes(self): ------- int """ - return self._dcr_settings.ConductionMaxPasses + return self._dcr_settings.conduction_max_passes @conduction_max_passes.setter def conduction_max_passes(self, value): - self._dcr_settings.ConductionMaxPasses = value + self._dcr_settings.conduction_max_passes = value self._parent._update_setup() @property @@ -1645,11 +1647,11 @@ def conduction_min_converged_passes(self): ------- int """ - return self._dcr_settings.ConductionMinConvergedPasses + return self._dcr_settings.conduction_min_converged_passes @conduction_min_converged_passes.setter def conduction_min_converged_passes(self, value): - self._dcr_settings.ConductionMinConvergedPasses = value + self._dcr_settings.conduction_min_converged_passes = value self._parent._update_setup() @property @@ -1660,11 +1662,11 @@ def conduction_min_passes(self): ------- int """ - return self._dcr_settings.ConductionMinPasses + return self._dcr_settings.conduction_min_passes @conduction_min_passes.setter def conduction_min_passes(self, value): - self._dcr_settings.ConductionMinPasses = value + self._dcr_settings.conduction_min_passes = value self._parent._update_setup() @property @@ -1675,11 +1677,11 @@ def conduction_per_error(self): ------- float """ - return self._dcr_settings.ConductionPerError + return self._dcr_settings.conduction_per_error @conduction_per_error.setter def conduction_per_error(self, value): - self._dcr_settings.ConductionPerError = value + self._dcr_settings.conduction_per_error = value self._parent._update_setup() @property @@ -1690,11 +1692,11 @@ def conduction_per_refine(self): ------- float """ - return self._dcr_settings.ConductionPerRefine + return self._dcr_settings.conduction_per_refine @conduction_per_refine.setter def conduction_per_refine(self, value): - self._dcr_settings.ConductionPerRefine = value + self._dcr_settings.conduction_per_refine = value self._parent._update_setup() @@ -1709,11 +1711,9 @@ def __init__(self, edb, name=None, edb_hfss_sim_setup=None): if edb_hfss_sim_setup: self._edb_sim_setup = edb_hfss_sim_setup self._edb_sim_setup_info = edb_hfss_sim_setup.GetSimSetupInfo() - self._name = edb_hfss_sim_setup.GetName() + self._name = edb_hfss_sim_setup.name else: - self._edb_sim_setup_info = self._edb.simsetupdata.SimSetupInfo[ - self._edb.simsetupdata.HFSSSimulationSettings - ]() + self._edb_sim_setup_info = HFSSSimulationSettings() if not name: self._edb_sim_setup_info.Name = generate_unique_name("hfss") else: @@ -1721,7 +1721,7 @@ def __init__(self, edb, name=None, edb_hfss_sim_setup=None): self._name = name self.hfss_solver_settings.order_basis = "mixed" - self._edb_sim_setup = self._edb.edb_api.utility.utility.HFSSSimulationSetup(self._edb_sim_setup_info) + self._edb_sim_setup = HfssSimulationSetup(self._edb_sim_setup_info) self._update_setup() @property @@ -1729,22 +1729,22 @@ def edb_sim_setup_info(self): """EDB internal simulation setup object.""" return self._edb_sim_setup_info - @pyaedt_function_handler() + @pyedb_function_handler() def _update_setup(self): - mesh_operations = self._edb_sim_setup_info.SimulationSettings.MeshOperations - mesh_operations.Clear() + mesh_operations = self._edb_sim_setup_info.simulation_settings.mesh_operations + mesh_operations.clear() for mop in self.mesh_operations.values(): - mesh_operations.Add(mop.mesh_operation) + mesh_operations.add(mop.mesh_operation) - self._edb_sim_setup = self._edb.edb_api.utility.utility.HFSSSimulationSetup(self._edb_sim_setup_info) + self._edb_sim_setup = HfssSimulationSetup(self._edb_sim_setup_info) if self._name in self._edb.setups: - self._edb.active_cell.DeleteSimulationSetup(self._name) + self._edb.active_cell.delete_simulation_setup(self._name) self._name = self.name - self._edb.active_cell.AddSimulationSetup(self._edb_sim_setup) - for i in list(self._edb.active_cell.SimulationSetups): - if i.GetSimSetupInfo().Name == self._name: - self._edb_sim_setup_info = i.GetSimSetupInfo() + self._edb.active_cell.add_simulation_setup(self._edb_sim_setup) + for i in list(self._edb.active_cell.simulation_setups): + if i.sim_setup_info().name == self._name: + self._edb_sim_setup_info = i.sim_setup_info return True return False @@ -1757,14 +1757,14 @@ def frequency_sweeps(self): List of :class:`pyaedt.edb_core.edb_data.hfss_simulation_setup_data.EdbFrequencySweep` """ sweep_data_list = {} - for i in list(self._edb_sim_setup_info.SweepDataList): - sweep_data_list[i.Name] = EdbFrequencySweep(self, None, i.Name, i) + for i in self._edb_sim_setup_info.sweep_data: + sweep_data_list[i.name] = EdbFrequencySweep(self, None, i.Name, i) return sweep_data_list @property def name(self): """Name of the setup.""" - return self._edb_sim_setup_info.Name + return self._edb_sim_setup_info.name @name.setter def name(self, value): @@ -1788,34 +1788,34 @@ def solver_slider_type(self): ------- str """ - return self._edb_sim_setup_info.SimulationSettings.TSolveSliderType.ToString() + return self._edb_sim_setup_info.simulation_settings.t_solve_slider_type @solver_slider_type.setter def solver_slider_type(self, value): """Set solver slider type.""" solver_types = { - "kFast": self._edb_sim_setup_info.SimulationSettings.TSolveSliderType.k25DViaWirebond, - "kMedium": self._edb_sim_setup_info.SimulationSettings.TSolveSliderType.k25DViaRibbon, - "kAccurate": self._edb_sim_setup_info.SimulationSettings.TSolveSliderType.k25DViaMesh, - "kNumSliderTypes": self._edb_sim_setup_info.SimulationSettings.TSolveSliderType.k25DViaField, + "kFast": self._edb_sim_setup_info.simulation_settings.t_solve_slider_type.k25DViaWirebond, + "kMedium": self._edb_sim_setup_info.simulation_settings.t_solve_slider_type.k25DViaRibbon, + "kAccurate": self._edb_sim_setup_info.simulation_settings.t_solve_slider_type.k25DViaMesh, + "kNumSliderTypes": self._edb_sim_setup_info.simulation_settings.t_solve_slider_type.k25DViaField, } - self._edb_sim_setup_info.SimulationSettings.TSolveSliderType = solver_types[value] + self._edb_sim_setup_info.simulation_settings.t_solve_slider_type = solver_types[value] self._update_setup() @property def is_auto_setup(self): """Whether if auto setup is enabled.""" - return self._edb_sim_setup_info.SimulationSettings.IsAutoSetup + return self._edb_sim_setup_info.simulation_settings.is_auto_setup @is_auto_setup.setter def is_auto_setup(self, value): - self._edb_sim_setup_info.SimulationSettings.IsAutoSetup = value + self._edb_sim_setup_info.simulation_settings.is_auto_setup = value self._update_setup() @property def setup_type(self): """Setup type.""" - return self._edb_sim_setup_info.SimulationSettings.SetupType + return self._edb_sim_setup_info.simulation_settings.setup_type @property def hfss_solver_settings(self): @@ -1916,7 +1916,7 @@ def mesh_operations(self): """ if self._mesh_operations: return self._mesh_operations - settings = self._edb_sim_setup_info.SimulationSettings.MeshOperations + settings = self._edb_sim_setup_info.simulation_settings.mesh_operations self._mesh_operations = {} for i in list(settings): if i.MeshOpType == i.TMeshOpType.kMeshSetupLength: @@ -1928,7 +1928,7 @@ def mesh_operations(self): return self._mesh_operations - @pyaedt_function_handler() + @pyedb_function_handler() def add_length_mesh_operation( self, net_layer_list, @@ -1979,7 +1979,7 @@ def add_length_mesh_operation( self.mesh_operations[name] = mesh_operation return mesh_operation if self._update_setup() else False - @pyaedt_function_handler() + @pyedb_function_handler() def add_skin_depth_mesh_operation( self, net_layer_list, @@ -2034,7 +2034,7 @@ def add_skin_depth_mesh_operation( self.mesh_operations[name] = mesh_operation return mesh_operation if self._update_setup() else False - @pyaedt_function_handler() + @pyedb_function_handler() def add_frequency_sweep(self, name=None, frequency_sweep=None): """Add frequency sweep. @@ -2064,7 +2064,7 @@ def add_frequency_sweep(self, name=None, frequency_sweep=None): name = generate_unique_name("sweep") return EdbFrequencySweep(self, frequency_sweep, name) - @pyaedt_function_handler() + @pyedb_function_handler() def set_solution_single_frequency(self, frequency="5GHz", max_num_passes=10, max_delta_s=0.02): """Set single-frequency solution. @@ -2086,7 +2086,7 @@ def set_solution_single_frequency(self, frequency="5GHz", max_num_passes=10, max self.adaptive_settings.adaptive_settings.AdaptiveFrequencyDataList.Clear() return self.adaptive_settings.add_adaptive_frequency_data(frequency, max_num_passes, max_delta_s) - @pyaedt_function_handler() + @pyedb_function_handler() def set_solution_multi_frequencies(self, frequencies=("5GHz", "10GHz"), max_num_passes=10, max_delta_s="0.02"): """Set multi-frequency solution. @@ -2111,7 +2111,7 @@ def set_solution_multi_frequencies(self, frequencies=("5GHz", "10GHz"), max_num_ return False return True - @pyaedt_function_handler() + @pyedb_function_handler() def set_solution_broadband( self, low_frequency="5GHz", high_frequency="10GHz", max_num_passes=10, max_delta_s="0.02" ): diff --git a/src/pyedb/grpc/edb_data/layer_data.py b/src/pyedb/grpc/edb_data/layer_data.py index 404c2e4a79..e3bdc67b3d 100644 --- a/src/pyedb/grpc/edb_data/layer_data.py +++ b/src/pyedb/grpc/edb_data/layer_data.py @@ -2,7 +2,7 @@ import re -from generic.general_methods import pyedb_function_handler +from pyedb.generic.general_methods import pyedb_function_handler from ansys.edb.utility import Value diff --git a/src/pyedb/grpc/edb_data/nets_data.py b/src/pyedb/grpc/edb_data/nets_data.py index 317be82e26..b40a988a07 100644 --- a/src/pyedb/grpc/edb_data/nets_data.py +++ b/src/pyedb/grpc/edb_data/nets_data.py @@ -3,9 +3,9 @@ from ansys.edb.layout.layout import NetClass from ansys.edb.layout.layout import Net from ansys.edb.primitive.primitive import PrimitiveType -from pyaedt.edb_core.edb_data.padstacks_data import EDBPadstackInstance -from pyaedt.edb_core.edb_data.primitives_data import cast -from generic.general_methods import pyedb_function_handler +from padstacks_data import EDBPadstackInstance +from primitives_data import cast +from pyedb.generic.general_methods import pyedb_function_handler class EDBNetsData(Net): diff --git a/src/pyedb/grpc/edb_data/padstacks_data.py b/src/pyedb/grpc/edb_data/padstacks_data.py index fe85c9608c..5af5633e34 100644 --- a/src/pyedb/grpc/edb_data/padstacks_data.py +++ b/src/pyedb/grpc/edb_data/padstacks_data.py @@ -3,19 +3,19 @@ import re import warnings -# from pyaedt.edb_core.dotnet.database import PolygonDataDotNet -# from pyaedt.edb_core.edb_data.edbvalue import EdbValue -from pyaedt.edb_core.edb_data.primitives_data import EDBPrimitivesMain -# from pyaedt.edb_core.general import PadGeometryTpe -# from pyaedt.edb_core.general import convert_py_list_to_net_list -# from pyaedt.generic.clr_module import String -# from pyaedt.generic.clr_module import _clr +from primitives_data import EDBPrimitivesMain +from ansys.edb.layer.layer import LayerType +from terminals import PadstackInstanceTerminal from ansys.edb.utility import Value -from generic.general_methods import generate_unique_name -from generic.general_methods import pyedb_function_handler +from ansys.edb.geometry.point_data import PointData +from ansys.edb.database import ProductIdType +from ansys.edb.definition.padstack_def_data import PadType +from pyedb.generic.general_methods import generate_unique_name +from pyedb.generic.general_methods import pyedb_function_handler from ansys.edb.geometry.polygon_data import PolygonData +from ansys.edb.hierarchy import MeshClosure from ansys.edb.definition.padstack_def_data import PadGeometryType -from pyaedt.modeler.geometry_operators import GeometryOperators +from pyedb.modeler.geometry_operators import GeometryOperators class EDBPadProperties(object): @@ -54,7 +54,7 @@ def _edb(self): @property def _pad_parameter_value(self): - pad_params = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.pad_type) + pad_params = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.int_to_pad_type(self.pad_type)) return pad_params @property @@ -67,7 +67,7 @@ def geometry_type(self): Type of the geometry. """ - padparams = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.pad_type) + padparams = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.int_to_pad_type(self.pad_type)) return int(padparams[1]) @geometry_type.setter @@ -122,7 +122,8 @@ def polygon_data(self): List of parameters. """ try: - pad_values = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.pad_type) + pad_values = self._edb_padstack.data.get_pad_parameters(self.layer_name, + self.int_to_pad_type(self.pad_type)) if isinstance(pad_values[0], PolygonData): return pad_values[0] else: @@ -151,7 +152,8 @@ def parameters(self): ) elif self.shape == PadGeometryType.PADGEOMTYPE_NSIDED_POLYGON.name: return OrderedDict({"Size": Value(value[0]), "NumSides": Value(value[1])}) - elif self.shape in [PadGeometryType.PADGEOMTYPE_ROUND45, PadGeometryType.PADGEOMTYPE_ROUND90]: # pragma: no cover + elif self.shape in [PadGeometryType.PADGEOMTYPE_ROUND45, + PadGeometryType.PADGEOMTYPE_ROUND90]: # pragma: no cover return OrderedDict( {"Inner": Value(value[0]), "ChannelWidth": Value(value[1]), "IsolationGap": Value(value[2])} ) @@ -182,24 +184,17 @@ def parameters(self, value): params = [Value(value["Size"])] elif self.shape == PadGeometryType.PADGEOMTYPE_RECTANGLE: params = [Value(value["XSize"]), Value(value["YSize"])] - elif self.shape == [PadGeometryTpe.Oval.name, PadGeometryTpe.Bullet.name]: - params = [ - self._get_edb_value(value["XSize"]), - self._get_edb_value(value["YSize"]), - self._get_edb_value(value["CornerRadius"]), - ] - elif self.shape in [PadGeometryTpe.Round45.name, PadGeometryTpe.Round90.name]: # pragma: no cover - params = [ - self._get_edb_value(value["Inner"]), - self._get_edb_value(value["ChannelWidth"]), - self._get_edb_value(value["IsolationGap"]), - ] + elif self.shape == [PadGeometryType.PADGEOMTYPE_OVAL, PadGeometryType.PADGEOMTYPE_BULLET]: + params = [Value(value["XSize"]), Value(value["YSize"]), Value(value["CornerRadius"])] + elif self.shape in [PadGeometryType.PADGEOMTYPE_ROUND45, + PadGeometryType.PADGEOMTYPE_ROUND90]: # pragma: no cover + params = [Value(value["Inner"]), Value(value["ChannelWidth"]), Value(value["IsolationGap"])] else: # pragma: no cover params = None elif isinstance(value, list): - params = [self._get_edb_value(i) for i in value] + params = [Value(i) for i in value] else: - params = [self._get_edb_value(value)] + params = [Value(value)] self._update_pad_parameters_parameters(params=params) @property @@ -212,10 +207,8 @@ def offset_x(self): Offset for the X axis. """ - pad_values = self._edb_padstack.GetData().GetPadParametersValue( - self.layer_name, self.int_to_pad_type(self.pad_type) - ) - return pad_values[3].ToString() + pad_values = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.int_to_pad_type(self.pad_type)) + return pad_values[3] @offset_x.setter def offset_x(self, offset_value): @@ -231,10 +224,8 @@ def offset_y(self): Offset for the Y axis. """ - pad_values = self._edb_padstack.GetData().GetPadParametersValue( - self.layer_name, self.int_to_pad_type(self.pad_type) - ) - return pad_values[4].ToString() + pad_values = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.int_to_pad_type(self.pad_type)) + return pad_values[4] @offset_y.setter def offset_y(self, offset_value): @@ -250,10 +241,8 @@ def rotation(self): Value for the rotation. """ - pad_values = self._edb_padstack.GetData().GetPadParametersValue( - self.layer_name, self.int_to_pad_type(self.pad_type) - ) - return pad_values[5].ToString() + pad_values = self._edb_padstack.data.get_pad_parameters(self.layer_name, self.int_to_pad_type(self.pad_type)) + return pad_values[5] @rotation.setter def rotation(self, rotation_value): @@ -274,7 +263,7 @@ def int_to_pad_type(self, val=0): """ return self._pedbpadstack._ppadstack.int_to_pad_type(val) - @pyaedt_function_handler() + @pyedb_function_handler() def int_to_geometry_type(self, val=0): """Convert an integer to an EDB.PadGeometryType. @@ -289,7 +278,7 @@ def int_to_geometry_type(self, val=0): """ return self._pedbpadstack._ppadstack.int_to_geometry_type(val) - @pyaedt_function_handler() + @pyedb_function_handler() def _update_pad_parameters_parameters( self, layer_name=None, @@ -324,15 +313,12 @@ def _update_pad_parameters_parameters( bool ``True`` when successful, ``False`` when failed. """ - originalPadstackDefinitionData = self._edb_padstack.GetData() - newPadstackDefinitionData = self._edb.definition.PadstackDefData(originalPadstackDefinitionData) + new_padstack_def_data = self._edb.definition.PadstackDefData(self._edb_padstack.data) if not pad_type: pad_type = self.pad_type if not geom_type: geom_type = self.geometry_type if params: - params = convert_py_list_to_net_list(params) - else: params = self._pad_parameter_value[2] if not offsetx: offsetx = self.offset_x @@ -343,16 +329,16 @@ def _update_pad_parameters_parameters( if not layer_name: layer_name = self.layer_name - newPadstackDefinitionData.SetPadParameters( + new_padstack_def_data.set_pad_parameters( layer_name, self.int_to_pad_type(pad_type), self.int_to_geometry_type(geom_type), params, - self._get_edb_value(offsetx), - self._get_edb_value(offsety), - self._get_edb_value(rotation), + Value(offsetx), + Value(offsety), + Value(rotation), ) - self._edb_padstack.SetData(newPadstackDefinitionData) + self._edb_padstack.SetData(new_padstack_def_data) class EDBPadstack(object): @@ -367,8 +353,8 @@ class EDBPadstack(object): Examples -------- - >>> from pyaedt import Edb - >>> edb = Edb(myedb, edbversion="2021.2") + >>> from pyedb import Edb + >>> edb = Edb(myedb, edbversion="2024.1") >>> edb_padstack = edb.padstacks.definitions["MyPad"] """ @@ -391,10 +377,6 @@ def name(self): """Padstack Definition Name.""" return self.edb_padstack.GetName() - @property - def _padstack_methods(self): - return self._ppadstack._padstack_methods - @property def _stackup_layers(self): return self._ppadstack._stackup_layers @@ -403,9 +385,6 @@ def _stackup_layers(self): def _edb(self): return self._ppadstack._edb - def _get_edb_value(self, value): - return self._ppadstack._get_edb_value(value) - @property def via_layers(self): """Layers. @@ -415,7 +394,7 @@ def via_layers(self): list List of layers. """ - return self.edb_padstack.GetData().GetLayerNames() + return self.edb_padstack.data.layer_names @property def via_start_layer(self): @@ -426,7 +405,7 @@ def via_start_layer(self): str Name of the starting layer. """ - return list(self.via_layers)[0] + return self.via_layers[0] @property def via_stop_layer(self): @@ -437,15 +416,7 @@ def via_stop_layer(self): str Name of the stopping layer. """ - return list(self.via_layers)[-1] - - @property - def hole_params(self): - """Via Hole parameters values.""" - - viaData = self.edb_padstack.GetData() - self._hole_params = viaData.GetHoleParametersValue() - return self._hole_params + return self.via_layers[-1] @property def hole_parameters(self): @@ -456,10 +427,9 @@ def hole_parameters(self): list List of the hole parameters. """ - self._hole_parameters = self.hole_params[2] - return self._hole_parameters + return self.edb_padstack.data.get_hole_parameters() - @pyaedt_function_handler() + @pyedb_function_handler() def _update_hole_parameters(self, hole_type=None, params=None, offsetx=None, offsety=None, rotation=None): """Update hole parameters. @@ -481,28 +451,25 @@ def _update_hole_parameters(self, hole_type=None, params=None, offsetx=None, off bool ``True`` when successful, ``False`` when failed. """ - originalPadstackDefinitionData = self.edb_padstack.GetData() - newPadstackDefinitionData = self._edb.definition.PadstackDefData(originalPadstackDefinitionData) + new_padsatck_def_data = self._edb.definition.PadstackDefData(self.edb_padstack.data) if not hole_type: hole_type = self.hole_type if not params: params = self.hole_parameters - if isinstance(params, list): - params = convert_py_list_to_net_list(params) if not offsetx: offsetx = self.hole_offset_x if not offsety: offsety = self.hole_offset_y if not rotation: rotation = self.hole_rotation - newPadstackDefinitionData.SetHoleParameters( + new_padsatck_def_data.set_hole_parameters( hole_type, params, - self._get_edb_value(offsetx), - self._get_edb_value(offsety), - self._get_edb_value(rotation), + Value(offsetx), + Value(offsety), + Value(rotation), ) - self.edb_padstack.SetData(newPadstackDefinitionData) + self.edb_padstack.SetData(new_padsatck_def_data) @property def hole_properties(self): @@ -513,15 +480,15 @@ def hole_properties(self): list List of float values for hole properties. """ - self._hole_properties = [i.ToDouble() for i in self.hole_params[2]] + self._hole_properties = [i.value for i in self.hole_parameters] return self._hole_properties @hole_properties.setter def hole_properties(self, propertylist): if not isinstance(propertylist, list): - propertylist = [self._get_edb_value(propertylist)] + propertylist = [Value(propertylist)] else: - propertylist = [self._get_edb_value(i) for i in propertylist] + propertylist = [Value(i) for i in propertylist] self._update_hole_parameters(params=propertylist) @property @@ -533,7 +500,7 @@ def hole_type(self): int Type of the hole. """ - self._hole_type = self.hole_params[1] + self._hole_type = self.hole_parameters return self._hole_type @property @@ -545,7 +512,7 @@ def hole_offset_x(self): str Hole offset value for the X axis. """ - self._hole_offset_x = self.hole_params[3].ToString() + self._hole_offset_x = self.hole_parameters[3] return self._hole_offset_x @hole_offset_x.setter @@ -562,7 +529,7 @@ def hole_offset_y(self): str Hole offset value for the Y axis. """ - self._hole_offset_y = self.hole_params[4].ToString() + self._hole_offset_y = self.hole_parameters[4] return self._hole_offset_y @hole_offset_y.setter @@ -579,7 +546,7 @@ def hole_rotation(self): str Value for the hole rotation. """ - self._hole_rotation = self.hole_params[5].ToString() + self._hole_rotation = self.hole_parameters[5] return self._hole_rotation @hole_rotation.setter @@ -596,14 +563,13 @@ def hole_plating_ratio(self): float Percentage for the hole plating. """ - return self._edb.definition.PadstackDefData(self.edb_padstack.GetData()).GetHolePlatingPercentage() + return self._edb.definition.PadstackDefData(self.edb_padstack.data.plating_percentage) @hole_plating_ratio.setter def hole_plating_ratio(self, ratio): - originalPadstackDefinitionData = self.edb_padstack.GetData() - newPadstackDefinitionData = self._edb.definition.PadstackDefData(originalPadstackDefinitionData) - newPadstackDefinitionData.SetHolePlatingPercentage(self._get_edb_value(ratio)) - self.edb_padstack.SetData(newPadstackDefinitionData) + new_padstack_def_data = self._edb.definition.PadstackDefData(self.edb_padstack.data) + new_padstack_def_data.plating_percentage = Value(ratio) + self.edb_padstack.data = new_padstack_def_data @property def hole_plating_thickness(self): @@ -615,7 +581,7 @@ def hole_plating_thickness(self): Thickness of the hole plating if present. """ if len(self.hole_properties) > 0: - return (float(self.hole_properties[0]) * self.hole_plating_ratio / 100) / 2 + return (self.hole_properties[0] * self.hole_plating_ratio / 100) / 2 else: return 0 @@ -628,7 +594,7 @@ def hole_plating_thickness(self, value): float Thickness of the hole plating if present. """ - hr = 200 * float(value) / float(self.hole_properties[0]) + hr = 200 * value / self.hole_properties[0] self.hole_plating_ratio = hr @property @@ -654,18 +620,17 @@ def material(self): str Material of the hole. """ - return self.edb_padstack.GetData().GetMaterial() + return self.edb_padstack.data.material @material.setter def material(self, materialname): - originalPadstackDefinitionData = self.edb_padstack.GetData() - newPadstackDefinitionData = self._edb.definition.PadstackDefData(originalPadstackDefinitionData) - newPadstackDefinitionData.SetMaterial(materialname) - self.edb_padstack.SetData(newPadstackDefinitionData) + new_padstack_def_data = self._edb.definition.PadstackDefData(self.edb_padstack.data) + new_padstack_def_data.material = materialname + self.edb_padstack.data = new_padstack_def_data @property def padstack_instances(self): - """Get all the vias that belongs to active Padstack definition. + """Get all the padstack instances that belongs to active padstack definition. Returns ------- @@ -685,15 +650,15 @@ def hole_range(self): Possible returned values are ``"through"``, ``"begin_on_upper_pad"``, ``"end_on_lower_pad"``, ``"upper_pad_to_lower_pad"``, and ``"undefined"``. """ - cloned_padstackdef_data = self._edb.definition.PadstackDefData(self.edb_padstack.GetData()) - hole_ange_type = int(cloned_padstackdef_data.GetHoleRange()) - if hole_ange_type == 0: # pragma no cover + cloned_padstackdef_data = self._edb.definition.PadstackDefData(self.edb_padstack.data) + hole_range_type = int(cloned_padstackdef_data.hole_range) + if hole_range_type == 0: # pragma no cover return "through" - elif hole_ange_type == 1: # pragma no cover + elif hole_range_type == 1: # pragma no cover return "begin_on_upper_pad" - elif hole_ange_type == 2: # pragma no cover + elif hole_range_type == 2: # pragma no cover return "end_on_lower_pad" - elif hole_ange_type == 3: # pragma no cover + elif hole_range_type == 3: # pragma no cover return "upper_pad_to_lower_pad" else: # pragma no cover return "undefined" @@ -701,20 +666,20 @@ def hole_range(self): @hole_range.setter def hole_range(self, value): if isinstance(value, str): # pragma no cover - cloned_padstackdef_data = self._edb.definition.PadstackDefData(self.edb_padstack.GetData()) + cloned_padstackdef_data = self._edb.definition.PadstackDefData(self.edb_padstack.data) if value == "through": # pragma no cover - cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.Through) + cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.THROUGH) elif value == "begin_on_upper_pad": # pragma no cover - cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.BeginOnUpperPad) + cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.BEGIN_ON_UPPER_PAD) elif value == "end_on_lower_pad": # pragma no cover - cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.EndOnLowerPad) + cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.END_ON_LOWER_PAD) elif value == "upper_pad_to_lower_pad": # pragma no cover - cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.UpperPadToLowerPad) + cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.UPPER_PAD_TO_LOWER_PAD) else: # pragma no cover return - self.edb_padstack.SetData(cloned_padstackdef_data) + self.edb_padstack.data = cloned_padstackdef_data - @pyaedt_function_handler() + @pyedb_function_handler() def convert_to_3d_microvias(self, convert_only_signal_vias=True, hole_wall_angle=15): """Convert actual padstack instance to microvias 3D Objects with a given aspect ratio. @@ -757,32 +722,32 @@ def convert_to_3d_microvias(self, convert_only_signal_vias=True, hole_wall_angle layout, self.via_start_layer, via._edb_padstackinstance.GetNet(), - self.pad_by_layer[self.via_start_layer].polygon_data.edb_api, + self.pad_by_layer[self.via_start_layer].polygon_data, ) else: self._edb.cell.primitive.circle.create( layout, self.via_start_layer, via._edb_padstackinstance.GetNet(), - self._get_edb_value(pos[0]), - self._get_edb_value(pos[1]), - self._get_edb_value(self.pad_by_layer[self.via_start_layer].parameters_values[0] / 2), + Value(pos[0]), + Value(pos[1]), + Value(self.pad_by_layer[self.via_start_layer].parameters_values[0] / 2), ) if len(self.pad_by_layer[self.via_stop_layer].parameters) == 0: self._edb.cell.primitive.polygon.create( layout, self.via_stop_layer, - via._edb_padstackinstance.GetNet(), - self.pad_by_layer[self.via_stop_layer].polygon_data.edb_api, + via._edb_padstackinstance.net, + self.pad_by_layer[self.via_stop_layer].polygon_data, ) else: self._edb.cell.primitive.circle.create( layout, self.via_stop_layer, - via._edb_padstackinstance.GetNet(), - self._get_edb_value(pos[0]), - self._get_edb_value(pos[1]), - self._get_edb_value(self.pad_by_layer[self.via_stop_layer].parameters_values[0] / 2), + via._edb_padstackinstance.net, + Value(pos[0]), + Value(pos[1]), + Value(self.pad_by_layer[self.via_stop_layer].parameters_values[0] / 2), ) for layer_name in layer_names: stop = "" @@ -792,26 +757,26 @@ def convert_to_3d_microvias(self, convert_only_signal_vias=True, hole_wall_angle cloned_circle = self._edb.cell.primitive.circle.create( layout, start, - via._edb_padstackinstance.GetNet(), - self._get_edb_value(pos[0]), - self._get_edb_value(pos[1]), - self._get_edb_value(rad1), + via._edb_padstackinstance.net, + Value(pos[0]), + Value(pos[1]), + Value(rad1), ) cloned_circle2 = self._edb.cell.primitive.circle.create( layout, stop, - via._edb_padstackinstance.GetNet(), - self._get_edb_value(pos[0]), - self._get_edb_value(pos[1]), - self._get_edb_value(rad2), + via._edb_padstackinstance.net, + Value(pos[0]), + Value(pos[1]), + Value(rad2), ) - s3d = self._edb.cell.hierarchy._hierarchy.Structure3D.Create( + s3d = self._edb.cell.hierarchy._hierarchy.Structure3D.create( layout, generate_unique_name("via3d_" + via.aedt_name.replace("via_", ""), n=3) ) - s3d.AddMember(cloned_circle.prim_obj) - s3d.AddMember(cloned_circle2.prim_obj) - s3d.SetMaterial(self.material) - s3d.SetMeshClosureProp(self._edb.cell.hierarchy._hierarchy.Structure3D.TClosure.EndsClosed) + s3d.add_member(cloned_circle.prim_obj) + s3d.add_member(cloned_circle2.prim_obj) + s3d.set_material(self.material) + s3d.mesh_closure = MeshClosure.ENDS_CLOSED started = True i += 1 if stop == via.stop_layer: @@ -820,7 +785,7 @@ def convert_to_3d_microvias(self, convert_only_signal_vias=True, hole_wall_angle self._ppadstack._pedb.logger.info("{} Converted successfully to 3D Objects.".format(i)) return True - @pyaedt_function_handler() + @pyedb_function_handler() def split_to_microvias(self): """Convert actual padstack definition to multiple microvias definitions. @@ -839,7 +804,7 @@ def split_to_microvias(self): ) return False started = False - p1 = self.edb_padstack.GetData() + p1 = self.edb_padstack.data new_instances = [] for layer_name in layer_names: stop = "" @@ -848,82 +813,82 @@ def split_to_microvias(self): stop = layer_names[layer_names.index(layer_name) + 1] new_padstack_name = "MV_{}_{}_{}".format(self.name, start, stop) included = [start, stop] - new_padstack_definition_data = self._ppadstack._pedb.edb_api.definition.PadstackDefData.Create() - new_padstack_definition_data.AddLayers(convert_py_list_to_net_list(included)) + new_padstack_definition_data = self._ppadstack._pedb.edb_api.definition.PadstackDefData.create() + new_padstack_definition_data.add_layers(included) for layer in included: pl = self.pad_by_layer[layer] - new_padstack_definition_data.SetPadParameters( + new_padstack_definition_data.set_pad_parameters( layer, - self._ppadstack._pedb.edb_api.definition.PadType.RegularPad, + PadType.REGULAR_PAD, pl.int_to_geometry_type(pl.geometry_type), list( - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) ) )[2], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[3], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[4], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[5], ) pl = self.antipad_by_layer[layer] - new_padstack_definition_data.SetPadParameters( + new_padstack_definition_data.set_pad_parameters( layer, - self._ppadstack._pedb.edb_api.definition.PadType.AntiPad, + PadType.ANTI_PAD, pl.int_to_geometry_type(pl.geometry_type), list( - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) ) )[2], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[3], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[4], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[5], ) pl = self.thermalpad_by_layer[layer] new_padstack_definition_data.SetPadParameters( layer, - self._ppadstack._pedb.edb_api.definition.PadType.ThermalPad, + PadType.THERMAL_PAD, pl.int_to_geometry_type(pl.geometry_type), list( - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) ) )[2], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[3], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[4], - pl._edb_padstack.GetData().GetPadParametersValue( + pl._edb_padstack.data.get_pad_parameters( pl.layer_name, pl.int_to_pad_type(pl.pad_type) )[5], ) - new_padstack_definition_data.SetHoleParameters( + new_padstack_definition_data.set_hole_parameters( self.hole_type, self.hole_parameters, - self._get_edb_value(self.hole_offset_x), - self._get_edb_value(self.hole_offset_y), - self._get_edb_value(self.hole_rotation), + Value(self.hole_offset_x), + Value(self.hole_offset_y), + Value(self.hole_rotation), ) - new_padstack_definition_data.SetMaterial(self.material) - new_padstack_definition_data.SetHolePlatingPercentage(self._get_edb_value(self.hole_plating_ratio)) - padstack_definition = self._edb.definition.PadstackDef.Create( + new_padstack_definition_data.material = self.material + new_padstack_definition_data.plating_percent(Value(self.hole_plating_ratio)) + padstack_definition = self._edb.definition.PadstackDef.create( self._ppadstack._pedb.active_db, new_padstack_name ) - padstack_definition.SetData(new_padstack_definition_data) + padstack_definition.data = new_padstack_definition_data new_instances.append(EDBPadstack(padstack_definition, self._ppadstack)) started = True if self.via_stop_layer == stop: @@ -935,26 +900,26 @@ def split_to_microvias(self): from_layer = [ l for l in self._ppadstack._pedb.stackup._edb_layer_list - if l.GetName() == list(instance.GetData().GetLayerNames())[0] + if l.name == list(instance.data.layer_names)[0] ][0] to_layer = [ l for l in self._ppadstack._pedb.stackup._edb_layer_list - if l.GetName() == list(instance.GetData().GetLayerNames())[-1] + if l.name == list(instance.data.layer_names())[-1] ][0] padstack_instance = self._edb.cell.primitive.padstack_instance.create( layout, - via._edb_padstackinstance.GetNet(), - generate_unique_name(instance.GetName()), + via._edb_padstackinstance.net, + generate_unique_name(instance.name), instance, - via._edb_padstackinstance.GetPositionAndRotationValue()[1], - via._edb_padstackinstance.GetPositionAndRotationValue()[2], + via._edb_padstackinstance.get_position_and_rotation()[1], + via._edb_padstackinstance.get_position_and_rotation()[2], from_layer, to_layer, None, None, ) - padstack_instance.SetIsLayoutPin(via.is_pin) + padstack_instance.is_layout_pin = via.is_pin i += 1 via.delete() self._ppadstack._pedb.logger.info("Created {} new microvias.".format(i)) @@ -973,7 +938,7 @@ class EDBPadstackInstance(EDBPrimitivesMain): Examples -------- - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb(myedb, edbversion="2021.2") >>> edb_padstack_instance = edb.padstacks.instances[0] """ @@ -989,24 +954,22 @@ def __init__(self, edb_padstackinstance, _pedb): @property def terminal(self): """Return PadstackInstanceTerminal object.""" - from pyaedt.edb_core.edb_data.terminals import PadstackInstanceTerminal - term = PadstackInstanceTerminal(self._pedb, self._edb_object.GetPadstackInstanceTerminal()) + term = PadstackInstanceTerminal(self._pedb, self._edb_object.get_padstack_instance_terminal()) if not term.is_null: return term - @pyaedt_function_handler + @pyedb_function_handler def _create_terminal(self, name=None): """Create a padstack instance terminal""" - from pyaedt.edb_core.edb_data.terminals import PadstackInstanceTerminal - term = PadstackInstanceTerminal(self._pedb, self._edb_object.GetPadstackInstanceTerminal()) + term = PadstackInstanceTerminal(self._pedb, self._edb_object.get_padstack_instance_terminal()) return term.create(self, name) - @pyaedt_function_handler + @pyedb_function_handler def create_coax_port(self, name=None, radial_extent_factor=0): """Create a coax port.""" - from pyaedt.edb_core.edb_data.ports import CoaxPort + from ports import CoaxPort term = self._create_terminal(name) coax = CoaxPort(self._pedb, term._edb_object) @@ -1038,8 +1001,8 @@ def _em_properties(self): r"$end 'EM properties'\n" ) - pid = self._pedb.edb_api.ProductId.Designer - _, p = self._edb_padstackinstance.GetProductProperty(pid, 18, "") + pid = ProductIdType.DESIGNER + _, p = self._edb_padstackinstance.get_product_property(pid, 18, "") if p: return p else: @@ -1048,8 +1011,8 @@ def _em_properties(self): @_em_properties.setter def _em_properties(self, em_prop): """Set EM properties""" - pid = self._pedb.edb_api.ProductId.Designer - self._edb_padstackinstance.SetProductProperty(pid, 18, em_prop) + pid = ProductIdType.DESIGNER + self._edb_padstackinstance.set_product_property(pid, 18, em_prop) @property def dcir_equipotential_region(self): @@ -1081,9 +1044,7 @@ def object_instance(self): """Return Ansys.Ansoft.Edb.LayoutInstance.LayoutObjInstance object.""" if not self._object_instance: self._object_instance = ( - self._edb_padstackinstance.GetLayout() - .GetLayoutInstance() - .GetLayoutObjInstance(self._edb_padstackinstance, None) + self._edb_padstackinstance.layout.layout_instance.get_layout_obj_instance_in_context(self._edb_padstackinstance, None) ) return self._object_instance @@ -1098,14 +1059,14 @@ def bounding_box(self): """ if self._bounding_box: return self._bounding_box - bbox = self.object_instance.GetBBox() + bbox = self.object_instance.get_bbox() self._bounding_box = [ - [bbox.Item1.X.ToDouble(), bbox.Item1.Y.ToDouble()], - [bbox.Item2.X.ToDouble(), bbox.Item2.Y.ToDouble()], + [bbox[0].x.value, bbox[0].y.value], + [bbox[1].x.value, bbox[1].y.value], ] return self._bounding_box - @pyaedt_function_handler() + @pyedb_function_handler() def in_polygon(self, polygon_data, include_partial=True, simple_check=False): """Check if padstack Instance is in given polygon data. @@ -1123,7 +1084,7 @@ def in_polygon(self, polygon_data, include_partial=True, simple_check=False): ``True`` when successful, ``False`` when failed. """ pos = [i for i in self.position] - int_val = 1 if polygon_data.PointInPolygon(self._pedb.point_data(*pos)) else 0 + int_val = 1 if polygon_data.is_inside(PointData(*pos)) else 0 if int_val == 0: return False @@ -1134,7 +1095,7 @@ def in_polygon(self, polygon_data, include_partial=True, simple_check=False): else: plane = self._pedb.modeler.Shape("rectangle", pointA=self.bounding_box[0], pointB=self.bounding_box[1]) rectangle_data = self._pedb.modeler.shape_to_polygon_data(plane) - int_val = polygon_data.GetIntersectionType(rectangle_data) + int_val = polygon_data.tntersection_type(rectangle_data) # Intersection type: # 0 = objects do not intersect # 1 = this object fully inside other (no common contour points) @@ -1163,7 +1124,7 @@ def padstack_definition(self): str Name of the padstack definition. """ - self._pdef = self._edb_padstackinstance.GetPadstackDef().GetName() + self._pdef = self._edb_padstackinstance.padstack_def.name return self._pdef @property @@ -1175,29 +1136,17 @@ def backdrill_top(self): tuple Tuple of the layer name, drill diameter, and offset if it exists. """ - layer = self._pedb.edb_api.cell.layer("", self._pedb.edb_api.cell.layer_type.SignalLayer) - val = self._pedb.edb_value(0) - offset = self._pedb.edb_value(0.0) - if is_ironpython: # pragma: no cover - diameter = _clr.StrongBox[type(val)]() - drill_to_layer = _clr.StrongBox[self._pedb.edb_api.Cell.ILayerReadOnly]() - flag = self._edb_padstackinstance.GetBackDrillParametersLayerValue(drill_to_layer, offset, diameter, False) - else: - ( - flag, - drill_to_layer, - offset, - diameter, - ) = self._edb_padstackinstance.GetBackDrillParametersLayerValue(layer, offset, val, False) + layer = self._pedb.edb_api.cell.layer("", LayerType.SIGNAL_LAYER) + flag, drill_to_layer, offset, diameter = self._edb_padstackinstance.get_back_drill_by_layer() if flag: - if offset.ToDouble(): - return drill_to_layer.GetName(), diameter.ToString(), offset.ToString() + if offset.value: + return drill_to_layer.name, diameter.value, offset.value else: - return drill_to_layer.GetName(), diameter.ToString() + return drill_to_layer.name, diameter.value else: return - def set_backdrill_top(self, drill_depth, drill_diameter, offset=0.0): + def set_backdrill_top(self, drill_depth, drill_diameter, offset=0.0, from_bottom=True): """Set backdrill from top. Parameters @@ -1210,6 +1159,8 @@ def set_backdrill_top(self, drill_depth, drill_diameter, offset=0.0): Offset for the backdrill. The default is ``0.0``. If the value is other than the default, the stub does not stop at the layer. In AEDT, this parameter is called "Mfg stub length". + from_bottom : bool + ``True`` back drill starts from bottom ``True`` from top. Default value is ``False``. Returns ------- @@ -1217,12 +1168,15 @@ def set_backdrill_top(self, drill_depth, drill_diameter, offset=0.0): True if success, False otherwise. """ layer = self._pedb.stackup.layers[drill_depth]._edb_layer - val = self._pedb.edb_value(drill_diameter) - offset = self._pedb.edb_value(offset) - if offset.ToDouble(): - return self._edb_padstackinstance.SetBackDrillParameters(layer, offset, val, False) + val = Value(drill_diameter) + offset = Value(offset) + if offset.value: + return self._edb_padstackinstance.set_back_drill_by_layer(drill_to_layer=layer, + offset=offset, + diameter=val, + from_bottom=from_bottom) else: - return self._edb_padstackinstance.SetBackDrillParameters(layer, val, False) + return self._edb_padstackinstance.set_back_drill_by_layer(layer, val, False) @property def backdrill_bottom(self): @@ -1233,25 +1187,13 @@ def backdrill_bottom(self): tuple Tuple of the layer name, drill diameter, and drill offset if it exists. """ - layer = self._pedb.edb_api.cell.layer("", self._pedb.edb_api.cell.layer_type.SignalLayer) - val = self._pedb.edb_value(0) - offset = self._pedb.edb_value(0.0) - if is_ironpython: # pragma: no cover - diameter = _clr.StrongBox[type(val)]() - drill_to_layer = _clr.StrongBox[self._pedb.edb_api.Cell.ILayerReadOnly]() - flag = self._edb_padstackinstance.GetBackDrillParametersLayerValue(drill_to_layer, offset, diameter, True) - else: - ( - flag, - drill_to_layer, - offset, - diameter, - ) = self._edb_padstackinstance.GetBackDrillParametersLayerValue(layer, offset, val, True) + layer = self._pedb.edb_api.cell.layer("", LayerType.SIGNAL_LAYER) + flag, drill_to_layer, offset, diameter, = self._edb_padstackinstance.get_back_drill_parameters_layer() if flag: - if offset.ToDouble(): - return drill_to_layer.GetName(), diameter.ToString(), offset.ToString() + if offset.value: + return drill_to_layer.name, diameter.value, offset.value else: - return drill_to_layer.GetName(), diameter.ToString() + return drill_to_layer.name, diameter.value else: return @@ -1275,12 +1217,12 @@ def set_backdrill_bottom(self, drill_depth, drill_diameter, offset=0.0): True if success, False otherwise. """ layer = self._pedb.stackup.layers[drill_depth]._edb_layer - val = self._pedb.edb_value(drill_diameter) - offset = self._pedb.edb_value(offset) - if offset.ToDouble(): - return self._edb_padstackinstance.SetBackDrillParameters(layer, offset, val, True) + val = Value(drill_diameter) + offset = Value(offset) + if offset.value: + return self._edb_padstackinstance.set_back_drill_parameters(layer, offset, val, True) else: - return self._edb_padstackinstance.SetBackDrillParameters(layer, val, True) + return self._edb_padstackinstance.set_bBack_drillParameters(layer, val, True) @property def start_layer(self): @@ -1291,18 +1233,17 @@ def start_layer(self): str Name of the starting layer. """ - layer = self._pedb.edb_api.cell.layer("", self._pedb.edb_api.cell.layer_type.SignalLayer) - _, start_layer, stop_layer = self._edb_padstackinstance.GetLayerRange() + _, start_layer, stop_layer = self._edb_padstackinstance.get_layer_range() if start_layer: - return start_layer.GetName() + return start_layer.name return None @start_layer.setter def start_layer(self, layer_name): stop_layer = self._pedb.stackup.signal_layers[self.stop_layer]._edb_layer layer = self._pedb.stackup.signal_layers[layer_name]._edb_layer - self._edb_padstackinstance.SetLayerRange(layer, stop_layer) + self._edb_padstackinstance.set_layer_range(layer, stop_layer) @property def stop_layer(self): @@ -1313,27 +1254,26 @@ def stop_layer(self): str Name of the stopping layer. """ - layer = self._pedb.edb_api.cell.layer("", self._pedb.edb_api.cell.layer_type.SignalLayer) _, start_layer, stop_layer = self._edb_padstackinstance.GetLayerRange() if stop_layer: - return stop_layer.GetName() + return stop_layer.name return None @stop_layer.setter def stop_layer(self, layer_name): start_layer = self._pedb.stackup.signal_layers[self.start_layer]._edb_layer layer = self._pedb.stackup.signal_layers[layer_name]._edb_layer - self._edb_padstackinstance.SetLayerRange(start_layer, layer) + self._edb_padstackinstance.set_layer_range(start_layer, layer) @property def layer_range_names(self): """List of all layers to which the padstack instance belongs.""" - _, start_layer, stop_layer = self._edb_padstackinstance.GetLayerRange() + _, start_layer, stop_layer = self._edb_padstackinstance.get_layer_range() started = False layer_list = [] - start_layer_name = start_layer.GetName() - stop_layer_name = stop_layer.GetName() + start_layer_name = start_layer.name + stop_layer_name = stop_layer.name for layer_name in list(self._pedb.stackup.layers.keys()): if started: layer_list.append(layer_name) @@ -1360,18 +1300,18 @@ def net_name(self): str Name of the net. """ - return self._edb_padstackinstance.GetNet().GetName() + return self._edb_padstackinstance.net.name @net_name.setter def net_name(self, val): if not isinstance(val, str): try: - self._edb_padstackinstance.SetNet(val.net_obj) + self._edb_padstackinstance.net = val.net_obj except: raise AttributeError("Value inserted not found. Input has to be net name or net object.") elif val in self._pedb.nets.netlist: net = self._pedb.nets.nets[val].net_object - self._edb_padstackinstance.SetNet(net) + self._edb_padstackinstance.net = net else: raise AttributeError("Value inserted not found. Input has to be net name or net object.") @@ -1384,7 +1324,7 @@ def is_pin(self): bool True if this padstack type is a layout pin, False otherwise. """ - return self._edb_padstackinstance.IsLayoutPin() + return self._edb_padstackinstance.is_layout_pin @is_pin.setter def is_pin(self, pin): @@ -1395,7 +1335,8 @@ def is_pin(self, pin): pin : bool True if set this padstack instance as pin, False otherwise """ - self._edb_padstackinstance.SetIsLayoutPin(pin) + if isinstance(pin, bool): + self._edb_padstackinstance.is_layout_pin = pin @property def position(self): @@ -1407,12 +1348,12 @@ def position(self): List of ``[x, y]``` coordinates for the padstack instance position. """ self._position = [] - out = self._edb_padstackinstance.GetPositionAndRotationValue() - if self._edb_padstackinstance.GetComponent(): - out2 = self._edb_padstackinstance.GetComponent().GetTransform().TransformPoint(out[1]) - self._position = [out2.X.ToDouble(), out2.Y.ToDouble()] + out = self._edb_padstackinstance.get_position_and_rotation() + if self._edb_padstackinstance.component: + out2 = self._edb_padstackinstance.component.transform.transform_point(out[1]) + self._position = [out2.x.value, out2.y.value] elif out[0]: - self._position = [out[1].X.ToDouble(), out[1].Y.ToDouble()] + self._position = [out[1].x.value, out[1].y.value] return self._position @position.setter @@ -1420,11 +1361,11 @@ def position(self, value): pos = [] for v in value: if isinstance(v, (float, int, str)): - pos.append(self._pedb.edb_value(v)) + pos.append(Value(v)) else: pos.append(v) point_data = self._pedb.edb_api.geometry.point_data(pos[0], pos[1]) - self._edb_padstackinstance.SetPositionAndRotation(point_data, self._pedb.edb_value(self.rotation)) + self._edb_padstackinstance.set_position_and_rotation(point_data, Value(self.rotation)) @property def rotation(self): @@ -1433,28 +1374,27 @@ def rotation(self): Returns ------- float - Rotatation value for the padstack instance. + Rotation value for the padstack instance. """ - point_data = self._pedb.edb_api.geometry.point_data(self._pedb.edb_value(0.0), self._pedb.edb_value(0.0)) - out = self._edb_padstackinstance.GetPositionAndRotationValue() + out = self._edb_padstackinstance.get_position_and_rotation() if out[0]: - return out[2].ToDouble() + return out[2].value @property def name(self): """Padstack Instance Name. If it is a pin, the syntax will be like in AEDT ComponentName-PinName.""" if self.is_pin: - comp_name = self._edb_padstackinstance.GetComponent().GetName() - pin_name = self._edb_padstackinstance.GetName() + comp_name = self._edb_padstackinstance.component.name + pin_name = self._edb_padstackinstance.name return "-".join([comp_name, pin_name]) else: - return self._edb_padstackinstance.GetName() + return self._edb_padstackinstance.name @name.setter def name(self, value): - self._edb_padstackinstance.SetName(value) - self._edb_padstackinstance.SetProductProperty(self._pedb.edb_api.ProductId.Designer, 11, value) + self._edb_padstackinstance.name = value + self._edb_padstackinstance.set_product_property(ProductIdType.DESIGNER, 11, value) @property def metal_volume(self): @@ -1492,7 +1432,7 @@ def metal_volume(self): @property def pin_number(self): """Get pin number.""" - return self._edb_padstackinstance.GetName() + return self._edb_padstackinstance.name @property def aedt_name(self): @@ -1509,21 +1449,16 @@ def aedt_name(self): Examples -------- - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edbapp = Edb("myaedbfolder", "project name", "release version") >>> edbapp.padstacks.instances[111].get_aedt_pin_name() """ - if is_ironpython: - name = _clr.Reference[String]() - self._edb_padstackinstance.GetProductProperty(self._pedb.edb_api.ProductId.Designer, 11, name) - else: - val = String("") - _, name = self._edb_padstackinstance.GetProductProperty(self._pedb.edb_api.ProductId.Designer, 11, val) + _, name = self._edb_padstackinstance.get_product_property(ProductIdType.DESIGNER, 11, "") name = str(name).strip("'") return name - @pyaedt_function_handler() + @pyedb_function_handler() def parametrize_position(self, prefix=None): """Parametrize the instance position. @@ -1548,7 +1483,7 @@ def parametrize_position(self, prefix=None): self.position = [var_name + "X", var_name + "Y"] return [var_name + "X", var_name + "Y"] - @pyaedt_function_handler() + @pyedb_function_handler() def delete_padstack_instance(self): """Delete this padstack instance. @@ -1556,10 +1491,10 @@ def delete_padstack_instance(self): Use :func:`delete` property instead. """ warnings.warn("`delete_padstack_instance` is deprecated. Use `delete` instead.", DeprecationWarning) - self._edb_padstackinstance.Delete() + self._edb_padstackinstance.delete() return True - @pyaedt_function_handler() + @pyedb_function_handler() def in_voids(self, net_name=None, layer_name=None): """Check if this padstack instance is in any void. @@ -1575,13 +1510,13 @@ def in_voids(self, net_name=None, layer_name=None): list List of the voids that include this padstack instance. """ - x_pos = self._pedb.edb_value(self.position[0]) - y_pos = self._pedb.edb_value(self.position[1]) + x_pos = Value(self.position[0]) + y_pos = Value(self.position[1]) point_data = self._pedb.modeler._edb.geometry.point_data(x_pos, y_pos) voids = [] for prim in self._pedb.modeler.get_primitives(net_name, layer_name, is_void=True): - if prim.primitive_object.GetPolygonData().PointInPolygon(point_data): + if prim.primitive_object.polygon_data.in_polygon(point_data): voids.append(prim) return voids @@ -1594,7 +1529,7 @@ def pingroups(self): list List of pin groups that the pin belongs to. """ - return self._edb_padstackinstance.GetPinGroups() + return self._edb_padstackinstance.pin_groups() @property def placement_layer(self): @@ -1605,7 +1540,7 @@ def placement_layer(self): str Name of the placement layer. """ - return self._edb_padstackinstance.GetGroup().GetPlacementLayer().Clone().GetName() + return self._edb_padstackinstance.group.placement_layer.name @property def lower_elevation(self): @@ -1616,7 +1551,7 @@ def lower_elevation(self): float Lower elavation of the placement layer. """ - return self._edb_padstackinstance.GetGroup().GetPlacementLayer().Clone().GetLowerElevation() + return self._edb_padstackinstance.group.placement_layer.lower_elevation @property def upper_elevation(self): @@ -1627,7 +1562,7 @@ def upper_elevation(self): float Upper elevation of the placement layer. """ - return self._edb_padstackinstance.GetGroup().GetPlacementLayer().Clone().GetUpperElevation() + return self._edb_padstackinstance.group.placement_layer.upper_elevation @property def top_bottom_association(self): @@ -1644,9 +1579,9 @@ def top_bottom_association(self): * 4 Number of top/bottom association type. * -1 Undefined. """ - return int(self._edb_padstackinstance.GetGroup().GetPlacementLayer().GetTopBottomAssociation()) + return int(self._edb_padstackinstance.group.placement_layer.top_bottom_association) - @pyaedt_function_handler() + @pyedb_function_handler() def create_rectangle_in_pad(self, layer_name, return_points=False, partition_max_order=16): """Create a rectangle inscribed inside a padstack instance pad. @@ -1671,7 +1606,7 @@ def create_rectangle_in_pad(self, layer_name, return_points=False, partition_max Examples -------- - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edbapp = Edb("myaedbfolder", edbversion="2021.2") >>> edb_layout = edbapp.modeler >>> list_of_padstack_instances = list(edbapp.padstacks.instances.values()) @@ -1813,13 +1748,13 @@ def _translate(p): # Polygon points = [] i = 0 - while i < polygon_data.edb_api.Count: - point = polygon_data.edb_api.GetPoint(i) + while i < len(polygon_data.points): + point = polygon_data.points[i] i += 1 - if point.IsArc(): + if point.is_arc: continue else: - points.append([point.X.ToDouble(), point.Y.ToDouble()]) + points.append([point.x.value, point.y.value]) xpoly, ypoly = zip(*points) polygon = [list(xpoly), list(ypoly)] rectangles = GeometryOperators.find_largest_rectangle_inside_polygon( @@ -1835,8 +1770,8 @@ def _translate(p): pdata = self._pedb.modeler.shape_to_polygon_data(path) new_rect = [] for point in pdata.Points: - p_transf = self._edb_padstackinstance.GetComponent().GetTransform().TransformPoint(point) - new_rect.append([p_transf.X.ToDouble(), p_transf.Y.ToDouble()]) + p_transf = self._edb_padstackinstance.component.transform.transform_point(point) + new_rect.append([p_transf.x.value, p_transf.y.value]) if return_points: return new_rect else: @@ -1844,7 +1779,7 @@ def _translate(p): created_polygon = self._pedb.modeler.create_polygon(path, layer_name) return created_polygon - @pyaedt_function_handler() + @pyedb_function_handler() def get_connected_object_id_set(self): """Produce a list of all geometries physically connected to a given layout object. @@ -1853,17 +1788,17 @@ def get_connected_object_id_set(self): list Found connected objects IDs with Layout object. """ - layoutInst = self._edb_padstackinstance.GetLayout().GetLayoutInstance() - layoutObjInst = self.object_instance - return [loi.GetLayoutObj().GetId() for loi in layoutInst.GetConnectedObjects(layoutObjInst).Items] + layout_inst = self._edb_padstackinstance.layout.layout_instance + layout_bbj_inst = self.object_instance + return [loi.layout_obj.id for loi in layout_inst.get_connected_objects(layout_bbj_inst).Items] - @pyaedt_function_handler() + @pyedb_function_handler() def _get_connected_object_obj_set(self): - layoutInst = self._edb_padstackinstance.GetLayout().GetLayoutInstance() - layoutObjInst = self.object_instance - return list([loi.GetLayoutObj() for loi in layoutInst.GetConnectedObjects(layoutObjInst).Items]) + layout_inst = self._edb_padstackinstance.layout.layout_instance + layout_bbj_inst = self.object_instance + return [loi.layout_obj for loi in layout_inst.get_connected_objects(layout_bbj_inst).Items] - @pyaedt_function_handler() + @pyedb_function_handler() def get_reference_pins(self, reference_net="GND", search_radius=5e-3, max_limit=0, component_only=True): """Search for reference pins using given criteria. diff --git a/src/pyedb/grpc/edb_data/ports.py b/src/pyedb/grpc/edb_data/ports.py index 26e5d1271c..8524b58706 100644 --- a/src/pyedb/grpc/edb_data/ports.py +++ b/src/pyedb/grpc/edb_data/ports.py @@ -1,7 +1,8 @@ -from pyaedt.edb_core.edb_data.terminals import BundleTerminal -from pyaedt.edb_core.edb_data.terminals import EdgeTerminal -from pyaedt.edb_core.edb_data.terminals import PadstackInstanceTerminal -from pyaedt.edb_core.edb_data.terminals import Terminal +from terminals import BundleTerminal +from terminals import EdgeTerminal +from terminals import PadstackInstanceTerminal +from terminals import Terminal +from ansys.edb.utility.value import Value class GapPort(EdgeTerminal): @@ -17,7 +18,7 @@ class GapPort(EdgeTerminal): Examples -------- This example shows how to access the ``GapPort`` class. - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb("myaedb.aedb") >>> gap_port = edb.ports["gap_port"] """ @@ -28,29 +29,29 @@ def __init__(self, pedb, edb_object): @property def magnitude(self): """Magnitude.""" - return self._edb_object.GetSourceAmplitude().ToDouble() + return self._edb_object.source_amplitude.value @property def phase(self): """Phase.""" - return self._edb_object.GetSourcePhase().ToDouble() + return self._edb_object.source_phase.value @property def renormalize(self): """Whether renormalize is active.""" - return self._edb_object.GetPortPostProcessingProp().DoRenormalize + return self._edb_object.port_post_processing_prop.do_renormalize @property def deembed(self): """Inductance value of the deembed gap port.""" - return self._edb_object.GetPortPostProcessingProp().DoDeembedGapL + return self._edb_object.port_post_processing_prop.do_deembed_gap_l @property def renormalize_z0(self): """Renormalize Z0 value (real, imag).""" return ( - self._edb_object.GetPortPostProcessingProp().RenormalizionZ0.ToComplex().Item1, - self._edb_object.GetPortPostProcessingProp().RenormalizionZ0.ToComplex().Item2, + self._edb_object.port_post_processing_prop.renormalizion_z0.complex[0], + self._edb_object.port_post_processing_prop.renormalizion_z0.complex[1], ) @@ -68,7 +69,7 @@ class WavePort(EdgeTerminal): -------- This example shows how to access the ``WavePort`` class. - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb("myaedb.aedb") >>> exc = edb.ports """ @@ -112,24 +113,24 @@ def pec_launch_width(self, value): @property def deembed(self): """Whether deembed is active.""" - return self._edb_object.GetPortPostProcessingProp().DoDeembed + return self._edb_object.port_post_processing_prop.do_deembed @deembed.setter def deembed(self, value): - p = self._edb_object.GetPortPostProcessingProp() - p.DoDeembed = value - self._edb_object.SetPortPostProcessingProp(p) + p = self._edb_object.port_post_processing_prop + p.do_deembed = value + self._edb_object.port_post_processing_prop = p @property def deembed_length(self): """Deembed Length.""" - return self._edb_object.GetPortPostProcessingProp().DeembedLength.ToDouble() + return self._edb_object.port_post_processing_prop.deembed_length.value @deembed_length.setter def deembed_length(self, value): - p = self._edb_object.GetPortPostProcessingProp() - p.DeembedLength = self._pedb.edb_value(value) - self._edb_object.SetPortPostProcessingProp(p) + p = self._edb_object.port_post_processing_prop + p.deembed_length = Value(value) + self._edb_object.port_post_processing_prop = p class ExcitationSources(Terminal): @@ -147,7 +148,7 @@ class ExcitationSources(Terminal): Examples -------- This example shows how to access this class. - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb("myaedb.aedb") >>> all_sources = edb.sources >>> print(all_sources["VSource1"].name) @@ -160,20 +161,20 @@ def __init__(self, pedb, edb_terminal): @property def magnitude(self): """Get the magnitude of the source.""" - return self._edb_object.GetSourceAmplitude().ToDouble() + return self._edb_object.source_amplitude.value @magnitude.setter def magnitude(self, value): - self._edb_object.SetSourceAmplitude(self._edb.utility.value(value)) + self._edb_object.source_amplitude = Value(value) @property def phase(self): """Get the phase of the source.""" - return self._edb_object.GetSourcePhase().ToDouble() + return self._edb_object.source_phase.value @phase.setter def phase(self, value): - self._edb_object.SetSourcePhase(self._edb.utility.value(value)) + self._edb_object.source_phase = Value(value) class ExcitationProbes(Terminal): @@ -190,7 +191,7 @@ class ExcitationProbes(Terminal): Examples -------- This example shows how to access this class. - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb("myaedb.aedb") >>> probes = edb.probes >>> print(probes["Probe1"].name) @@ -270,7 +271,7 @@ class CoaxPort(PadstackInstanceTerminal): Parameters ---------- - pedb : pyaedt.edb.Edb + pedb : pyedb.edb.Edb EDB object from the ``Edblib`` library. edb_object : Ansys.Ansoft.Edb.Cell.Terminal.PadstackInstanceTerminal PadstackInstanceTerminal instance from EDB. diff --git a/src/pyedb/grpc/edb_data/primitives_data.py b/src/pyedb/grpc/edb_data/primitives_data.py index 514b0d279a..1932be2c07 100644 --- a/src/pyedb/grpc/edb_data/primitives_data.py +++ b/src/pyedb/grpc/edb_data/primitives_data.py @@ -1,15 +1,15 @@ import math -from pyaedt.edb_core.dotnet.primitive import BondwireDotNet -from pyaedt.edb_core.dotnet.primitive import CircleDotNet -from pyaedt.edb_core.dotnet.primitive import PathDotNet -from pyaedt.edb_core.dotnet.primitive import PolygonDotNet -from pyaedt.edb_core.dotnet.primitive import RectangleDotNet -from pyaedt.edb_core.dotnet.primitive import TextDotNet -from pyaedt.edb_core.edb_data.connectable import Connectable -from pyaedt.edb_core.general import convert_py_list_to_net_list -from pyaedt.generic.general_methods import pyaedt_function_handler -from pyaedt.modeler.geometry_operators import GeometryOperators +from ansys.edb.primitive.primitive import Bondwire +from ansys.edb.primitive.primitive import Circle +from ansys.edb.primitive.primitive import Path +from ansys.edb.primitive.primitive import Polygon +from ansys.edb.primitive.primitive import Rectangle +from ansys.edb.primitive.primitive import Text +from ansys.edb.primitive.primitive import PrimitiveType +from ansys.edb.utility.value import Value +from pyedb.generic.general_methods import pyedb_function_handler +from pyedb.modeler.geometry_operators import GeometryOperators def cast(raw_primitive, core_app): @@ -19,32 +19,32 @@ def cast(raw_primitive, core_app): ------- Primitive """ - if isinstance(raw_primitive, RectangleDotNet): + if isinstance(raw_primitive, Rectangle): return EdbRectangle(raw_primitive.prim_obj, core_app) - elif isinstance(raw_primitive, PolygonDotNet): + elif isinstance(raw_primitive, Polygon): return EdbPolygon(raw_primitive.prim_obj, core_app) - elif isinstance(raw_primitive, PathDotNet): + elif isinstance(raw_primitive, Path): return EdbPath(raw_primitive.prim_obj, core_app) - elif isinstance(raw_primitive, BondwireDotNet): + elif isinstance(raw_primitive, Bondwire): return EdbBondwire(raw_primitive.prim_obj, core_app) - elif isinstance(raw_primitive, TextDotNet): + elif isinstance(raw_primitive, Text): return EdbText(raw_primitive.prim_obj, core_app) - elif isinstance(raw_primitive, CircleDotNet): + elif isinstance(raw_primitive, Circle): return EdbCircle(raw_primitive.prim_obj, core_app) else: try: - prim_type = raw_primitive.GetPrimitiveType() - if prim_type == prim_type.Rectangle: + prim_type = raw_primitive.primitive_type + if prim_type == PrimitiveType.RECTANGLE: return EdbRectangle(raw_primitive, core_app) - elif prim_type == prim_type.Polygon: + elif prim_type == PrimitiveType.POLYGON: return EdbPolygon(raw_primitive, core_app) - elif prim_type == prim_type.Path: + elif prim_type == PrimitiveType.PATH: return EdbPath(raw_primitive, core_app) - elif prim_type == prim_type.Bondwire: + elif prim_type == PrimitiveType.BONDWIRE: return EdbBondwire(raw_primitive, core_app) - elif prim_type == prim_type.Text: + elif prim_type == PrimitiveType.TEXT: return EdbText(raw_primitive, core_app) - elif prim_type == prim_type.Circle: + elif prim_type == PrimitiveType.CIRCLE: return EdbCircle(raw_primitive, core_app) else: return None @@ -52,13 +52,13 @@ def cast(raw_primitive, core_app): return None -class EDBPrimitivesMain(Connectable): +class EDBPrimitivesMain: """Manages EDB functionalities for a primitives. It Inherits EDB Object properties. Examples -------- - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb(myedb, edbversion="2021.2") >>> edb_prim = edb.modeler.primitives[0] >>> edb_prim.is_void # Class Property @@ -81,10 +81,10 @@ def type(self): ------- str """ - types = ["Circle", "Path", "Polygon", "Rectangle", "Bondwire"] - str_type = self.primitive_type.ToString().split(".") + types = ["CIRCLE", "PATH", "POLYGON", "RECTANGLE", "BONDWIRE"] + str_type = str(self.primitive_type).split(".") if str_type[-1] in types: - return str_type[-1] + return f"{str_type[-1][0]}{str_type[-1][:1].lower()}" return None @property @@ -95,13 +95,12 @@ def net_name(self): ------- str """ - return self.net.GetName() + return self.net.name @net_name.setter def net_name(self, name): if isinstance(name, str): - net = self._app.nets.nets[name].net_object - self.primitive_object.SetNet(net) + self.primitive_object.name = name else: try: self.net = name @@ -111,7 +110,7 @@ def net_name(self, name): @property def layer(self): """Get the primitive edb layer object.""" - return self.primitive_object.GetLayer() + return self.primitive_object.layer @property def layer_name(self): @@ -121,19 +120,19 @@ def layer_name(self): ------- str """ - return self.layer.GetName() + return self.layer.name @layer_name.setter def layer_name(self, val): if isinstance(val, str) and val in list(self._core_stackup.layers.keys()): lay = self._core_stackup.layers["TOP"]._edb_layer if lay: - self.primitive_object.SetLayer(lay) + self.primitive_object.layer = lay else: raise AttributeError("Layer {} not found in layer".format(val)) elif isinstance(val, type(self._core_stackup.layers["TOP"])): try: - self.primitive_object.SetLayer(val._edb_layer) + self.primitive_object.layer = val._edb_layer except: raise AttributeError("Failed to assign new layer on primitive.") else: @@ -147,7 +146,7 @@ def is_void(self): ------- bool """ - return self._edb_object.IsVoid() + return self._edb_object.is_void class EDBPrimitives(EDBPrimitivesMain): @@ -156,7 +155,7 @@ class EDBPrimitives(EDBPrimitivesMain): Examples -------- - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb(myedb, edbversion="2021.2") >>> edb_prim = edb.modeler.primitives[0] >>> edb_prim.is_void # Class Property @@ -166,7 +165,7 @@ class EDBPrimitives(EDBPrimitivesMain): def __init__(self, raw_primitive, core_app): EDBPrimitivesMain.__init__(self, raw_primitive, core_app) - @pyaedt_function_handler() + @pyedb_function_handler() def area(self, include_voids=True): """Return the total area. @@ -179,10 +178,10 @@ def area(self, include_voids=True): ------- float """ - area = self.primitive_object.GetPolygonData().Area() + area = self.primitive_object.polygon_data.area if include_voids: - for el in self.primitive_object.Voids: - area -= el.GetPolygonData().Area() + for el in self.primitive_object.voids: + area -= el.polygon_data.area return area @property @@ -194,11 +193,12 @@ def is_negative(self): bool True if it is negative, False otherwise. """ - return self.primitive_object.GetIsNegative() + return self.primitive_object.is_negative @is_negative.setter def is_negative(self, value): - self.primitive_object.SetIsNegative(value) + if isinstance(value, bool): + self.primitive_object.is_negative = value @staticmethod def _eval_arc_points(p1, p2, h, n=6, tol=1e-12): @@ -283,16 +283,16 @@ def _get_points_for_plot(self, my_net_points, num): y = [] for i, point in enumerate(my_net_points): if not self.is_arc(point): - x.append(point.X.ToDouble()) - y.append(point.Y.ToDouble()) + x.append(point.x.value) + y.append(point.y.value) # i += 1 else: - arc_h = point.GetArcHeight().ToDouble() - p1 = [my_net_points[i - 1].X.ToDouble(), my_net_points[i - 1].Y.ToDouble()] + arc_h = point.arc_height.value + p1 = [my_net_points[i - 1].x.value, my_net_points[i - 1].y.value] if i + 1 < len(my_net_points): - p2 = [my_net_points[i + 1].X.ToDouble(), my_net_points[i + 1].Y.ToDouble()] + p2 = [my_net_points[i + 1].x.value, my_net_points[i + 1].y.value] else: - p2 = [my_net_points[0].X.ToDouble(), my_net_points[0].Y.ToDouble()] + p2 = [my_net_points[0].x.value, my_net_points[0].y.value] x_arc, y_arc = self._eval_arc_points(p1, p2, arc_h, num) x.extend(x_arc) y.extend(y_arc) @@ -310,8 +310,8 @@ def bbox(self): [lower_left x, lower_left y, upper right x, upper right y] """ - bbox = self.polygon_data.edb_api.GetBBox() - return [bbox.Item1.X.ToDouble(), bbox.Item1.Y.ToDouble(), bbox.Item2.X.ToDouble(), bbox.Item2.Y.ToDouble()] + bbox = self.polygon_data.bbox + return [bbox[0].x.value, bbox[0].y.value, bbox[1].x.value, bbox[1].y.value] @property def center(self): @@ -326,7 +326,7 @@ def center(self): bbox = self.bbox return [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2] - @pyaedt_function_handler() + @pyedb_function_handler() def is_arc(self, point): """Either if a point is an arc or not. @@ -336,7 +336,7 @@ def is_arc(self, point): """ return point.IsArc() - @pyaedt_function_handler() + @pyedb_function_handler() def get_connected_object_id_set(self): """Produce a list of all geometries physically connected to a given layout object. @@ -345,17 +345,17 @@ def get_connected_object_id_set(self): list Found connected objects IDs with Layout object. """ - layoutInst = self.primitive_object.GetLayout().GetLayoutInstance() - layoutObjInst = layoutInst.GetLayoutObjInstance(self.primitive_object, None) # 2nd arg was [] - return [loi.GetLayoutObj().GetId() for loi in layoutInst.GetConnectedObjects(layoutObjInst).Items] + layout_inst = self.primitive_object.layout.layout_instance + layout_obj_inst = layout_inst.layout_obj_instance(self.primitive_object, None) + return [loi.layout_obj.id for loi in layout_inst.get_connected_objects(layout_obj_inst)] - @pyaedt_function_handler() + @pyedb_function_handler() def _get_connected_object_obj_set(self): - layoutInst = self.primitive_object.GetLayout().GetLayoutInstance() - layoutObjInst = layoutInst.GetLayoutObjInstance(self.primitive_object, None) - return list([loi.GetLayoutObj() for loi in layoutInst.GetConnectedObjects(layoutObjInst).Items]) + layout_inst = self.primitive_object.layout.layout_instance + layout_obj_inst = layout_inst.layout_obj_instance(self.primitive_object, None) + return [loi.layout_obj for loi in layout_inst.get_connected_objects(layout_obj_inst)] - @pyaedt_function_handler() + @pyedb_function_handler() def convert_to_polygon(self): """Convert path to polygon. @@ -365,12 +365,12 @@ def convert_to_polygon(self): """ if self.type == "Path": - polygon_data = self.primitive_object.GetPolygonData() + polygon_data = self.primitive_object.polygon_data polygon = self._app.modeler.create_polygon(polygon_data, self.layer_name, [], self.net_name) - self.primitive_object.Delete() + self.primitive_object.delete() return polygon - @pyaedt_function_handler() + @pyedb_function_handler() def subtract(self, primitives): """Subtract active primitive with one or more primitives. @@ -382,30 +382,30 @@ def subtract(self, primitives): ------- List of :class:`pyaedt.edb_core.edb_data.EDBPrimitives` """ - poly = self.primitive_object.GetPolygonData() + poly = self.primitive_object.polygon_data if not isinstance(primitives, list): primitives = [primitives] primi_polys = [] voids_of_prims = [] for prim in primitives: if isinstance(prim, EDBPrimitives): - primi_polys.append(prim.primitive_object.GetPolygonData()) + primi_polys.append(prim.primitive_object.polygon_data) for void in prim.voids: - voids_of_prims.append(void.polygon_data.edb_api) + voids_of_prims.append(void.polygon_data) else: try: - primi_polys.append(prim.GetPolygonData()) + primi_polys.append(prim.polygon_data) except: primi_polys.append(prim) for v in self.voids[:]: primi_polys.append(v.polygon_data.edb_api) - primi_polys = poly.Unite(convert_py_list_to_net_list(primi_polys)) - p_to_sub = poly.Unite(convert_py_list_to_net_list([poly] + voids_of_prims)) - list_poly = poly.Subtract(p_to_sub, primi_polys) + primi_polys = poly.unite(primi_polys) + p_to_sub = poly.unite([poly] + voids_of_prims) + list_poly = poly.subtract(p_to_sub, primi_polys) new_polys = [] if list_poly: for p in list_poly: - if p.IsNull(): + if p.is_null: continue new_polys.append( cast( @@ -415,16 +415,13 @@ def subtract(self, primitives): ) self.delete() for prim in primitives: - if isinstance(prim, EDBPrimitives): + try: prim.delete() - else: - try: - prim.Delete() - except AttributeError: - continue + except AttributeError: + continue return new_polys - @pyaedt_function_handler() + @pyedb_function_handler() def intersect(self, primitives): """Intersect active primitive with one or more primitives. @@ -436,42 +433,40 @@ def intersect(self, primitives): ------- List of :class:`pyaedt.edb_core.edb_data.EDBPrimitives` """ - poly = self.primitive_object.GetPolygonData() + poly = self.primitive_object.polygon_data if not isinstance(primitives, list): primitives = [primitives] primi_polys = [] for prim in primitives: if isinstance(prim, EDBPrimitives): - primi_polys.append(prim.primitive_object.GetPolygonData()) + primi_polys.append(prim.primitive_object.polygon_data) else: try: - primi_polys.append(prim.GetPolygonData()) + primi_polys.append(prim.polygon_data) except: primi_polys.append(prim) - list_poly = poly.Intersect(convert_py_list_to_net_list([poly]), convert_py_list_to_net_list(primi_polys)) + list_poly = poly.Intersect([poly], primi_polys) new_polys = [] if list_poly: voids = self.voids for p in list_poly: - if p.IsNull(): + if p.is_null: continue list_void = [] void_to_subtract = [] if voids: for void in voids: - void_pdata = void.prim_obj.GetPolygonData() - int_data2 = p.GetIntersectionType(void_pdata) + void_pdata = void.prim_obj.polygon_data + int_data2 = p.intersection_type(void_pdata) if int_data2 > 2 or int_data2 == 1: void_to_subtract.append(void_pdata) elif int_data2 == 2: list_void.append(void_pdata) if void_to_subtract: - polys_cleans = p.Subtract( - convert_py_list_to_net_list(p), convert_py_list_to_net_list(void_to_subtract) - ) + polys_cleans = p.subtract(p, void_to_subtract) for polys_clean in polys_cleans: - if not polys_clean.IsNull(): - void_to_append = [v for v in list_void if polys_clean.GetIntersectionType(v) == 2] + if not polys_clean.is_null: + void_to_append = [v for v in list_void if polys_clean.tntersection_type(v) == 2] new_polys.append( cast( self._app.modeler.create_polygon( @@ -500,16 +495,13 @@ def intersect(self, primitives): ) self.delete() for prim in primitives: - if isinstance(prim, EDBPrimitives): + try: prim.delete() - else: - try: - prim.Delete() - except AttributeError: - continue + except AttributeError: + continue return new_polys - @pyaedt_function_handler() + @pyedb_function_handler() def unite(self, primitives): """Unite active primitive with one or more primitives. @@ -521,30 +513,30 @@ def unite(self, primitives): ------- List of :class:`pyaedt.edb_core.edb_data.EDBPrimitives` """ - poly = self.primitive_object.GetPolygonData() + poly = self.primitive_object.polygon_data if not isinstance(primitives, list): primitives = [primitives] primi_polys = [] for prim in primitives: if isinstance(prim, EDBPrimitives): - primi_polys.append(prim.primitive_object.GetPolygonData()) + primi_polys.append(prim.primitive_object.polygon_data) else: try: - primi_polys.append(prim.GetPolygonData()) + primi_polys.append(prim.polygon_data) except: primi_polys.append(prim) - list_poly = poly.Unite(convert_py_list_to_net_list([poly] + primi_polys)) + list_poly = poly.unite([poly] + primi_polys) new_polys = [] if list_poly: voids = self.voids for p in list_poly: - if p.IsNull(): + if p.is_null: continue list_void = [] if voids: for void in voids: - void_pdata = void.primitive_object.GetPolygonData() - int_data2 = p.GetIntersectionType(void_pdata) + void_pdata = void.primitive_object.polygon_data + int_data2 = p.intersection_type(void_pdata) if int_data2 > 1: list_void.append(void_pdata) new_polys.append( @@ -555,16 +547,13 @@ def unite(self, primitives): ) self.delete() for prim in primitives: - if isinstance(prim, EDBPrimitives): - prim.delete() - else: - try: - prim.Delete() - except AttributeError: - continue + try: + prim.Delete() + except AttributeError: + continue return new_polys - @pyaedt_function_handler() + @pyedb_function_handler() def intersection_type(self, primitive): """Get intersection type between actual primitive and another primitive or polygon data. @@ -587,9 +576,9 @@ def intersection_type(self, primitive): poly = primitive.polygon_data except AttributeError: pass - return int(self.polygon_data.edb_api.GetIntersectionType(poly.edb_api)) + return int(self.polygon_data.intersection_type(poly)) - @pyaedt_function_handler() + @pyedb_function_handler() def is_intersecting(self, primitive): """Check if actual primitive and another primitive or polygon data intesects. @@ -603,7 +592,7 @@ def is_intersecting(self, primitive): """ return True if self.intersection_type(primitive) >= 1 else False - @pyaedt_function_handler() + @pyedb_function_handler() def get_closest_point(self, point): """Get the closest point of the primitive to the input data. @@ -616,12 +605,12 @@ def get_closest_point(self, point): list of float """ if isinstance(point, (list, tuple)): - point = self._app.edb_api.geometry.point_data(self._app.edb_value(point[0]), self._app.edb_value(point[1])) + point = self._app.geometry.point_data(Value(point[0]), Value(point[1])) - p0 = self.polygon_data.edb_api.GetClosestPoint(point) - return [p0.X.ToDouble(), p0.Y.ToDouble()] + p0 = self.polygon_data.closest_points(point) + return [p0.x.value, p0.y.value] - @pyaedt_function_handler() + @pyedb_function_handler() def get_closest_arc_midpoint(self, point): """Get the closest arc midpoint of the primitive to the input data. @@ -633,17 +622,17 @@ def get_closest_arc_midpoint(self, point): ------- list of float """ - if isinstance(point, self._app.edb_api.geometry.geometry.PointData): - point = [point.X.ToDouble(), point.Y.ToDouble()] + if isinstance(point, self._app.geometry.geometry.PointData): + point = [point.x.value, point.y.value] dist = 1e12 out = None for arc in self.arcs: mid_point = arc.mid_point - mid_point = [mid_point.X.ToDouble(), mid_point.Y.ToDouble()] + mid_point = [mid_point.x.value, mid_point.y.value] if GeometryOperators.points_distance(mid_point, point) < dist: out = arc.mid_point dist = GeometryOperators.points_distance(mid_point, point) - return [out.X.ToDouble(), out.Y.ToDouble()] + return [out.x.value, out.y.value] @property def arcs(self): @@ -674,10 +663,9 @@ def shortest_arc(self): return arc -class EdbPath(EDBPrimitives, PathDotNet): +class EdbPath(EDBPrimitives): def __init__(self, raw_primitive, core_app): EDBPrimitives.__init__(self, raw_primitive, core_app) - PathDotNet.__init__(self, self._app, raw_primitive) @property def width(self): @@ -689,16 +677,13 @@ def width(self): Path width or None. """ if self.type == "Path": - return self.primitive_object.GetWidth() + return self.primitive_object.width return @width.setter def width(self, value): if self.type == "Path": - if isinstance(value, (int, str, float)): - self.primitive_object.SetWidth(self._app.edb_value(value)) - else: - self.primitive_object.SetWidth(value) + self.primitive_object.width = Value(value).value @property def length(self): @@ -716,7 +701,7 @@ def length(self): length += GeometryOperators.points_distance(center_line[pt_ind], center_line[pt_ind + 1]) return length - @pyaedt_function_handler + @pyedb_function_handler def get_center_line(self, to_string=False): """Get the center line of the trace. @@ -730,11 +715,11 @@ def get_center_line(self, to_string=False): """ if to_string: - return [[p.X.ToString(), p.Y.ToString()] for p in list(self.primitive_object.GetCenterLine().Points)] + return [[str(p.x.value), str(p.y.value)] for p in list(self.primitive_object.center_line.points)] else: - return [[p.X.ToDouble(), p.Y.ToDouble()] for p in list(self.primitive_object.GetCenterLine().Points)] + return [[p.x.value, p.y.value] for p in list(self.primitive_object.center_line.points)] - @pyaedt_function_handler + @pyedb_function_handler def clone(self): """Clone a primitive object with keeping same definition and location. @@ -761,7 +746,7 @@ def clone(self): return cloned_path # @pyaedt_function_handler - @pyaedt_function_handler + @pyedb_function_handler def create_edge_port( self, name, @@ -799,7 +784,7 @@ def create_edge_port( Examples -------- - >>> edbapp = pyaedt.Edb("myproject.aedb") + >>> edbapp = pyedb.Edb("myproject.aedb") >>> sig = appedb.modeler.create_trace([[0, 0], ["9mm", 0]], "TOP", "1mm", "SIG", "Flat", "Flat") >>> sig.create_edge_port("pcb_port", "end", "Wave", None, 8, 8) @@ -815,24 +800,21 @@ def create_edge_port( return self._app.hfss.create_edge_port_vertical(self.id, pos, name, 50, reference_layer) -class EdbRectangle(EDBPrimitives, RectangleDotNet): +class EdbRectangle(EDBPrimitives): def __init__(self, raw_primitive, core_app): EDBPrimitives.__init__(self, raw_primitive, core_app) - RectangleDotNet.__init__(self, self._app, raw_primitive) -class EdbCircle(EDBPrimitives, CircleDotNet): +class EdbCircle(EDBPrimitives): def __init__(self, raw_primitive, core_app): EDBPrimitives.__init__(self, raw_primitive, core_app) - CircleDotNet.__init__(self, self._app, raw_primitive) -class EdbPolygon(EDBPrimitives, PolygonDotNet): +class EdbPolygon(EDBPrimitives): def __init__(self, raw_primitive, core_app): EDBPrimitives.__init__(self, raw_primitive, core_app) - PolygonDotNet.__init__(self, self._app, raw_primitive) - @pyaedt_function_handler + @pyedb_function_handler def clone(self): """Clone a primitive object with keeping same definition and location. @@ -841,20 +823,20 @@ def clone(self): bool ``True`` when successful, ``False`` when failed. """ - cloned_poly = self._app.edb_api.cell.primitive.polygon.create( - self._app.active_layout, self.layer_name, self.net, self.polygon_data.edb_api + cloned_poly = self._app.cell.primitive.polygon.create( + self._app.active_layout, self.layer_name, self.net, self.polygon_data ) if cloned_poly: for void in self.voids: - cloned_void = self._app.edb_api.cell.primitive.polygon.create( - self._app.active_layout, self.layer_name, self.net, void.polygon_data.edb_api + cloned_void = self._app.cell.primitive.polygon.create( + self._app.active_layout, self.layer_name, self.net, void.polygon_data ) # cloned_void - cloned_poly.prim_obj.AddVoid(cloned_void.prim_obj) + cloned_poly.prim_obj.add_void(cloned_void.prim_obj) return cloned_poly return False - @pyaedt_function_handler() + @pyedb_function_handler() def in_polygon( self, point_data, @@ -874,10 +856,9 @@ def in_polygon( ``True`` when successful, ``False`` when failed. """ if isinstance(point_data, list): - point_data = self._app.edb_api.geometry.point_data( - self._app.edb_value(point_data[0]), self._app.edb_value(point_data[1]) + point_data = self._app.geometry.point_data(Value(point_data[0]), Value(point_data[1]) ) - int_val = int(self.polygon_data.edb_api.PointInPolygon(point_data)) + int_val = int(self.polygon_data.in_polygon(point_data)) # Intersection type: # 0 = objects do not intersect @@ -893,45 +874,14 @@ def in_polygon( else: return False - # @pyaedt_function_handler() - # def add_void(self, point_list): - # """Add a void to current primitive. - # - # Parameters - # ---------- - # point_list : list or :class:`pyaedt.edb_core.edb_data.primitives_data.EDBPrimitives` or EDB Primitive Object - # Point list in the format of `[[x1,y1], [x2,y2],..,[xn,yn]]`. - # - # Returns - # ------- - # bool - # ``True`` if successful, either ``False``. - # """ - # if isinstance(point_list, list): - # plane = self._app.modeler.Shape("polygon", points=point_list) - # _poly = self._app.modeler.shape_to_polygon_data(plane) - # if _poly is None or _poly.IsNull() or _poly is False: - # self._logger.error("Failed to create void polygon data") - # return False - # prim = self._app.edb_api.cell.primitive.polygon.create( - # self._app.active_layout, self.layer_name, self.primitive_object.GetNet(), _poly - # ) - # elif isinstance(point_list, EDBPrimitives): - # prim = point_list.primitive_object - # else: - # prim = point_list - # return self.add_void(prim) - - -class EdbText(EDBPrimitivesMain, TextDotNet): + +class EdbText(EDBPrimitivesMain): def __init__(self, raw_primitive, core_app): - TextDotNet.__init__(self, self._app, raw_primitive) EDBPrimitives.__init__(self, raw_primitive, core_app) -class EdbBondwire(EDBPrimitivesMain, BondwireDotNet): +class EdbBondwire(EDBPrimitivesMain): def __init__(self, raw_primitive, core_app): - BondwireDotNet.__init__(self, self._app, raw_primitive) EDBPrimitives.__init__(self, raw_primitive, core_app) @@ -941,8 +891,8 @@ class EDBArcs(object): Examples -------- - >>> from pyaedt import Edb - >>> edb = Edb(myedb, edbversion="2021.2") + >>> from pyedb import Edb + >>> edb = Edb(myedb, edbversion="2024.1") >>> prim_arcs = edb.modeler.primitives[0].arcs >>> prim_arcs.center # arc center >>> prim_arcs.points # arc point list @@ -970,8 +920,8 @@ def start(self): >>> print(start_coordinate) [x_value, y_value] """ - point = self.arc_object.Start - return [point.X.ToDouble(), point.Y.ToDouble()] + point = self.arc_object.start + return [point.x.value, point.y.value] @property def end(self): @@ -987,8 +937,8 @@ def end(self): >>> appedb = Edb(fpath, edbversion="2023.2") >>> end_coordinate = appedb.nets["V1P0_S0"].primitives[0].arcs[0].end """ - point = self.arc_object.End - return [point.X.ToDouble(), point.Y.ToDouble()] + point = self.arc_object.end + return [point.x.value, point.y.value] @property def height(self): @@ -1005,7 +955,7 @@ def height(self): >>> appedb = Edb(fpath, edbversion="2023.2") >>> arc_height = appedb.nets["V1P0_S0"].primitives[0].arcs[0].height """ - return self.arc_object.Height + return self.arc_object.height @property def center(self): @@ -1015,8 +965,8 @@ def center(self): ------- list """ - cent = self.arc_object.GetCenter() - return [cent.X.ToDouble(), cent.Y.ToDouble()] + cent = self.arc_object.center + return [cent.x.value, cent.y.value] @property def length(self): @@ -1026,7 +976,7 @@ def length(self): ------- float """ - return self.arc_object.GetLength() + return self.arc_object.length @property def mid_point(self): @@ -1036,7 +986,7 @@ def mid_point(self): ------- float """ - return self.arc_object.GetMidPoint() + return self.arc_object.mid_point @property def radius(self): @@ -1046,7 +996,7 @@ def radius(self): ------- float """ - return self.arc_object.GetRadius() + return self.arc_object.radius @property def is_segment(self): @@ -1056,7 +1006,7 @@ def is_segment(self): ------- bool """ - return self.arc_object.IsSegment() + return self.arc_object.is_segment @property def is_point(self): @@ -1066,7 +1016,7 @@ def is_point(self): ------- bool """ - return self.arc_object.IsPoint() + return self.arc_object.is_point @property def is_ccw(self): @@ -1076,7 +1026,7 @@ def is_ccw(self): ------- bool """ - return self.arc_object.IsCCW() + return self.arc_object.is_ccw @property def points_raw(self): @@ -1087,7 +1037,7 @@ def points_raw(self): list Edb Points. """ - return list(self.arc_object.GetPointData()) + return self.arc_object.points @property def points(self, arc_segments=6): diff --git a/src/pyedb/grpc/edb_data/simulation_configuration.py b/src/pyedb/grpc/edb_data/simulation_configuration.py index 7e71cb1069..db46d410a8 100644 --- a/src/pyedb/grpc/edb_data/simulation_configuration.py +++ b/src/pyedb/grpc/edb_data/simulation_configuration.py @@ -2,17 +2,16 @@ import json import os -from pyaedt import generate_unique_name -from pyaedt.edb_core.edb_data.sources import Source -from pyaedt.edb_core.edb_data.sources import SourceType -from pyaedt.generic.clr_module import Dictionary -from pyaedt.generic.constants import BasisOrder -from pyaedt.generic.constants import CutoutSubdesignType -from pyaedt.generic.constants import RadiationBoxType -from pyaedt.generic.constants import SolverType -from pyaedt.generic.constants import SweepType -from pyaedt.generic.constants import validate_enum_class_value -from pyaedt.generic.general_methods import pyaedt_function_handler +from pyedb.generic.general_methods import generate_unique_name +from sources import Source +from pyedb.generic.constants import SourceType +from pyedb.generic.constants import BasisOrder +from pyedb.generic.constants import CutoutSubdesignType +from pyedb.generic.constants import RadiationBoxType +from pyedb.generic.constants import SolverType +from pyedb.generic.constants import SweepType +from pyedb.generic.constants import validate_enum_class_value +from pyedb.generic.general_methods import pyedb_function_handler class SimulationConfigurationBatch(object): @@ -502,7 +501,7 @@ def sources(self, value): # pragma: no cover if len([src for src in value if isinstance(src, Source)]) == len(value): self._sources = value - @pyaedt_function_handler() + @pyedb_function_handler() def add_source(self, source=None): # pragma: no cover """Add a new source to configuration. @@ -667,7 +666,7 @@ def __init__(self): self._dc_per_pin_use_pin_format = True self._dc_use_loop_res_for_per_pin = True self._dc_via_report_path = "" - self._dc_source_terms_to_ground = Dictionary[str, int]() + self._dc_source_terms_to_ground = {} @property def dc_min_plane_area_to_mesh(self): # pragma: no cover @@ -1898,7 +1897,7 @@ class SimulationConfiguration(object): The class is instantiated from an open edb: - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edb = Edb() >>> sim_setup = edb.new_simulation_configuration() @@ -1906,7 +1905,7 @@ class SimulationConfiguration(object): From this class you can assign a lot of parameters related the project configuration but also solver options. Here is the list of parameters available: - >>> from pyaedt.generic.constants import SolverType + >>> from pyedb.generic.constants import SolverType >>> sim_setup.solver_type = SolverType.Hfss3dLayout Solver type can be selected, HFSS 3D Layout and Siwave are supported. @@ -1932,7 +1931,7 @@ class SimulationConfiguration(object): When true activates the layout cutout based on net signal net selection and cutout expansion. - >>> from pyaedt.generic.constants import CutoutSubdesignType + >>> from pyedb.generic.constants import CutoutSubdesignType >>> sim_setup.cutout_subdesign_type = CutoutSubdesignType.Conformal Define the type of cutout used for computing the clippingextent polygon. CutoutSubdesignType.Conformal @@ -2009,7 +2008,7 @@ class SimulationConfiguration(object): taking the closest reference pin. The last configuration is more often used when users are creating ports on PDN (Power delivery Network) and want to connect all pins individually. - >>> from pyaedt.generic.constants import SweepType + >>> from pyedb.generic.constants import SweepType >>> sim_setup.sweep_type = SweepType.Linear Specify the frequency sweep type, Linear or Log sweep can be defined. @@ -2058,7 +2057,7 @@ class SimulationConfiguration(object): Define the frequency used for adaptive meshing (available for both HFSS and SIwave). - >>> from pyaedt.generic.constants import RadiationBoxType + >>> from pyedb.generic.constants import RadiationBoxType >>> sim_setup.radiation_box = RadiationBoxType.ConvexHull Defined the radiation box type, Conformal, Bounding box and ConvexHull are supported (HFSS only). @@ -2077,7 +2076,7 @@ class SimulationConfiguration(object): specify the minimum number of consecutive coberged passes. Setting to 2 is a good practice to avoid converging on local minima. - >>> from pyaedt.generic.constants import BasisOrder + >>> from pyedb.generic.constants import BasisOrder >>> sim_setup.basis_order = BasisOrder.Single Select the order basis (HFSS only), Zero, Single, Double and Mixed are supported. For Signal integrity Single or @@ -2285,7 +2284,7 @@ def batch_solve_settings(self): """ return self._batch_solve_settings - @pyaedt_function_handler() + @pyedb_function_handler() def build_simulation_project(self): """Build active simulation project. This method requires to be run inside Edb Class. @@ -2363,7 +2362,7 @@ def _get_list_value(self, value): # pragma: no cover prop_values = [value.strip()] return prop_values - @pyaedt_function_handler() + @pyedb_function_handler() def add_dc_ground_source_term(self, source_name=None, node_to_ground=1): """Add a dc ground source terminal for Siwave. @@ -2382,219 +2381,6 @@ def add_dc_ground_source_term(self, source_name=None, node_to_ground=1): if node_to_ground in [0, 1, 2]: self._dc_source_terms_to_ground[source_name] = node_to_ground - def _read_cfg(self): # pragma: no cover - """Configuration file reader. - - .. deprecated:: 0.6.78 - Use :func:`import_json` instead. - - Examples - -------- - - >>> from pyaedt import Edb - >>> from pyaedt.edb_core.edb_data.simulation_configuration import SimulationConfiguration - >>> config_file = path_configuration_file - >>> source_file = path_to_edb_folder - >>> edb = Edb(source_file) - >>> sim_setup = SimulationConfiguration(config_file) - >>> edb.build_simulation_project(sim_setup) - >>> edb.save_edb() - >>> edb.close_edb() - """ - - if not self.filename or not os.path.exists(self.filename): - # raise Exception("{} does not exist.".format(self.filename)) - return - - try: - with open(self.filename) as cfg_file: - cfg_lines = cfg_file.read().split("\n") - for line in cfg_lines: - if line.strip() != "": - if line.find("="): - i, prop_value = line.strip().split("=") - value = prop_value.replace("'", "").strip() - if i.lower().startswith("generatesolderballs"): - self.generate_solder_balls = self._get_bool_value(value) - elif i.lower().startswith("signalnets"): - self.signal_nets = value[1:-1].split(",") if value[0] == "[" else value.split(",") - self.signal_nets = [item.strip() for item in self.signal_nets] - elif i.lower().startswith("powernets"): - self.power_nets = value[1:-1].split(",") if value[0] == "[" else value.split(",") - self.power_nets = [item.strip() for item in self.power_nets] - elif i.lower().startswith("components"): - self.components = value[1:-1].split(",") if value[0] == "[" else value.split(",") - self.components = [item.strip() for item in self.components] - elif i.lower().startswith("coaxsolderballsdiams"): - self.coax_solder_ball_diameter = ( - value[1:-1].split(",") if value[0] == "[" else value.split(",") - ) - self.coax_solder_ball_diameter = [ - item.strip() for item in self.coax_solder_ball_diameter - ] - elif i.lower().startswith("usedefaultcoaxportradialextentfactor"): - self.signal_nets = self._get_bool_value(value) - elif i.lower().startswith("trimrefsize"): - self.trim_reference_size = self._get_bool_value(value) - elif i.lower().startswith("cutoutsubdesigntype"): - if value.lower().startswith("conformal"): - self.cutout_subdesign_type = CutoutSubdesignType.Conformal - elif value.lower().startswith("boundingbox"): - self.cutout_subdesign_type = CutoutSubdesignType.BoundingBox - else: - print("Unprocessed value for CutoutSubdesignType '{0}'".format(value)) - elif i.lower().startswith("cutoutsubdesignexpansion"): - self.cutout_subdesign_expansion = value - elif i.lower().startswith("cutoutsubdesignroundcorners"): - self.cutout_subdesign_round_corner = self._get_bool_value(value) - elif i.lower().startswith("sweepinterpolating"): - self.sweep_interpolating = self._get_bool_value(value) - elif i.lower().startswith("useq3dfordc"): - self.use_q3d_for_dc = self._get_bool_value(value) - elif i.lower().startswith("relativeerrors"): - self.relative_error = float(value) - elif i.lower().startswith("useerrorz0"): - self.use_error_z0 = self._get_bool_value(value) - elif i.lower().startswith("percenterrorz0"): - self.percentage_error_z0 = float(value) - elif i.lower().startswith("enforcecausality"): - self.enforce_causality = self._get_bool_value(value) - elif i.lower().startswith("enforcepassivity"): - self.enforce_passivity = self._get_bool_value(value) - elif i.lower().startswith("passivitytolerance"): - self.passivity_tolerance = float(value) - elif i.lower().startswith("sweepname"): - self.sweep_name = value - elif i.lower().startswith("radiationbox"): - if value.lower().startswith("conformal"): - self.radiation_box = RadiationBoxType.Conformal - elif value.lower().startswith("boundingbox"): - self.radiation_box = RadiationBoxType.BoundingBox - elif value.lower().startswith("convexhull"): - self.radiation_box = RadiationBoxType.ConvexHull - else: - print("Unprocessed value for RadiationBox '{0}'".format(value)) - elif i.lower().startswith("startfreq"): - self.start_freq = value - elif i.lower().startswith("stopfreq"): - self.stop_freq = value - elif i.lower().startswith("sweeptype"): - if value.lower().startswith("linear"): - self.sweep_type = SweepType.Linear - elif value.lower().startswith("logcount"): - self.sweep_type = SweepType.LogCount - else: - print("Unprocessed value for SweepType '{0}'".format(value)) - elif i.lower().startswith("stepfreq"): - self.step_freq = value - elif i.lower().startswith("decadecount"): - self.decade_count = int(value) - elif i.lower().startswith("mesh_freq"): - self.mesh_freq = value - elif i.lower().startswith("maxnumpasses"): - self.max_num_passes = int(value) - elif i.lower().startswith("maxmagdeltas"): - self.max_mag_delta_s = float(value) - elif i.lower().startswith("minnumpasses"): - self.min_num_passes = int(value) - elif i.lower().startswith("basisorder"): - if value.lower().startswith("mixed"): - self.basis_order = BasisOrder.Mixed - elif value.lower().startswith("zero"): - self.basis_order = BasisOrder.Zero - elif value.lower().startswith("first"): # single - self.basis_order = BasisOrder.Single - elif value.lower().startswith("second"): # double - self.basis_order = BasisOrder.Double - else: - print("Unprocessed value for BasisOrder '{0}'".format(value)) - elif i.lower().startswith("dolambdarefinement"): - self.do_lambda_refinement = self._get_bool_value(value) - elif i.lower().startswith("arcangle"): - self.arc_angle = value - elif i.lower().startswith("startazimuth"): - self.start_azimuth = float(value) - elif i.lower().startswith("maxarcpoints"): - self.max_arc_points = int(value) - elif i.lower().startswith("usearctochorderror"): - self.use_arc_to_chord_error = self._get_bool_value(value) - elif i.lower().startswith("arctochorderror"): - self.arc_to_chord_error = value - elif i.lower().startswith("defeatureabsLength"): - self.defeature_abs_length = value - elif i.lower().startswith("defeaturelayout"): - self.defeature_layout = self._get_bool_value(value) - elif i.lower().startswith("minimumvoidsurface"): - self.minimum_void_surface = float(value) - elif i.lower().startswith("maxsurfdev"): - self.max_suf_dev = float(value) - elif i.lower().startswith("processpadstackdefinitions"): - self.process_padstack_definitions = self._get_bool_value(value) - elif i.lower().startswith("returncurrentdistribution"): - self.return_current_distribution = self._get_bool_value(value) - elif i.lower().startswith("ignorenonfunctionalpads"): - self.ignore_non_functional_pads = self._get_bool_value(value) - elif i.lower().startswith("includeinterplanecoupling"): - self.include_inter_plane_coupling = self._get_bool_value(value) - elif i.lower().startswith("xtalkthreshold"): - self.xtalk_threshold = float(value) - elif i.lower().startswith("minvoidarea"): - self.min_void_area = value - elif i.lower().startswith("minpadareatomesh"): - self.min_pad_area_to_mesh = value - elif i.lower().startswith("snaplengththreshold"): - self.snap_length_threshold = value - elif i.lower().startswith("minplaneareatomesh"): - self.min_plane_area_to_mesh = value - elif i.lower().startswith("dcminplaneareatomesh"): - self.dc_min_plane_area_to_mesh = value - elif i.lower().startswith("maxinitmeshedgelength"): - self.max_init_mesh_edge_length = value - elif i.lower().startswith("signallayersproperties"): - self._parse_signal_layer_properties = value[1:-1] if value[0] == "[" else value - self._parse_signal_layer_properties = [ - item.strip() for item in self._parse_signal_layer_properties - ] - elif i.lower().startswith("coplanar_instances"): - self.coplanar_instances = value[1:-1] if value[0] == "[" else value - self.coplanar_instances = [item.strip() for item in self.coplanar_instances] - elif i.lower().startswith("signallayersetching"): - self.signal_layer_etching_instances = value[1:-1] if value[0] == "[" else value - self.signal_layer_etching_instances = [ - item.strip() for item in self.signal_layer_etching_instances - ] - elif i.lower().startswith("etchingfactor"): - self.etching_factor_instances = value[1:-1] if value[0] == "[" else value - self.etching_factor_instances = [item.strip() for item in self.etching_factor_instances] - elif i.lower().startswith("docutoutsubdesign"): - self.do_cutout_subdesign = self._get_bool_value(value) - elif i.lower().startswith("solvertype"): - if value.lower() == "hfss": - self.solver_type = 0 - if value.lower() == "hfss3dlayout": - self.solver_type = 6 - elif value.lower().startswith("siwavesyz"): - self.solver_type = 7 - elif value.lower().startswith("siwavedc"): - self.solver_type = 8 - elif value.lower().startswith("q3d"): - self.solver_type = 2 - elif value.lower().startswith("nexxim"): - self.solver_type = 4 - elif value.lower().startswith("maxwell"): - self.solver_type = 3 - elif value.lower().startswith("twinbuilder"): - self.solver_type = 5 - else: - self.solver_type = SolverType.Hfss3dLayout - else: - print("Unprocessed line in cfg file: {0}".format(line)) - else: - continue - except EnvironmentError as e: - print("Error reading cfg file: {}".format(e.message)) - raise - def _dict_to_json(self, dict_out, dict_in=None): exclude = ["_pedb", "SOLVER_TYPE"] for k, v in dict_in.items(): @@ -2626,7 +2412,7 @@ def _json_to_dict(self, json_dict): source._read_json(src) self.batch_solve_settings.sources.append(source) elif k == "dc_source_terms_to_ground": - dc_term_gnd = Dictionary[str, int]() + dc_term_gnd = {} for k1, v1 in json_dict[k]: # pragma: no cover dc_term_gnd[k1] = v1 self.dc_source_terms_to_ground = dc_term_gnd @@ -2635,7 +2421,7 @@ def _json_to_dict(self, json_dict): else: self.__setattr__(k, v) - @pyaedt_function_handler() + @pyedb_function_handler() def export_json(self, output_file): """Export Json file from SimulationConfiguration object. @@ -2652,7 +2438,7 @@ def export_json(self, output_file): Examples -------- - >>> from pyaedt.edb_core.edb_data.simulation_configuration import SimulationConfiguration + >>> from pyedb.grpc.edb_data.simulation_configuration import SimulationConfiguration >>> config = SimulationConfiguration() >>> config.export_json(r"C:\Temp\test_json\test.json") """ @@ -2665,7 +2451,7 @@ def export_json(self, output_file): else: return False - @pyaedt_function_handler() + @pyedb_function_handler() def import_json(self, input_file): """Import Json file into SimulationConfiguration object instance. @@ -2681,7 +2467,7 @@ def import_json(self, input_file): Examples -------- - >>> from pyaedt.edb_core.edb_data.simulation_configuration import SimulationConfiguration + >>> from pyedb.grpc.edb_data.simulation_configuration import SimulationConfiguration >>> test = SimulationConfiguration() >>> test.import_json(r"C:\Temp\test_json\test.json") """ @@ -2694,7 +2480,7 @@ def import_json(self, input_file): else: return False - @pyaedt_function_handler() + @pyedb_function_handler() def add_voltage_source( self, name="", @@ -2766,7 +2552,7 @@ def add_voltage_source( except: # pragma: no cover return False - @pyaedt_function_handler() + @pyedb_function_handler() def add_current_source( self, name="", @@ -2838,7 +2624,7 @@ def add_current_source( except: # pragma: no cover return False - @pyaedt_function_handler() + @pyedb_function_handler() def add_rlc( self, name="", diff --git a/src/pyedb/grpc/edb_data/siwave_simulation_setup_data.py b/src/pyedb/grpc/edb_data/siwave_simulation_setup_data.py index bcfb82a3fd..c7e6339b5d 100644 --- a/src/pyedb/grpc/edb_data/siwave_simulation_setup_data.py +++ b/src/pyedb/grpc/edb_data/siwave_simulation_setup_data.py @@ -1,9 +1,8 @@ -from pyaedt.edb_core.edb_data.hfss_simulation_setup_data import EdbFrequencySweep -from pyaedt.edb_core.general import convert_netdict_to_pydict -from pyaedt.edb_core.general import convert_pydict_to_netdict -from pyaedt.generic.general_methods import generate_unique_name -from pyaedt.generic.general_methods import is_linux -from pyaedt.generic.general_methods import pyaedt_function_handler +from pyedb.grpc.edb_data.hfss_simulation_setup_data import EdbFrequencySweep +from pyedb.generic.general_methods import generate_unique_name +from pyedb.generic.general_methods import pyedb_function_handler +from ansys.edb.simulation_setup.siwave_simulation_setup import SIWaveSimulationSetup +from ansys.edb.simulation_setup.siwave_simulation_setup import SimulationSetupType class SiwaveAdvancedSettings(object): @@ -25,7 +24,7 @@ def include_inter_plane_coupling(self): bool ``True`` if interplane coupling is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeInterPlaneCoupling + return self.sim_setup_info.simulation_settings.advanced.include_inter_plane_coupling @property def xtalk_threshold(self): @@ -36,7 +35,7 @@ def xtalk_threshold(self): ------- str """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.XtalkThreshold + return self.sim_setup_info.simulation_settings.advanced.cross_talk_threshold @property def min_void_area(self): @@ -46,7 +45,7 @@ def min_void_area(self): ------- bool """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.MinVoidArea + return self.sim_setup_info.simulation_settings.advanced.min_void_area @property def min_pad_area_to_mesh(self): @@ -56,7 +55,7 @@ def min_pad_area_to_mesh(self): ------- bool """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.MinPadAreaToMesh + return self.sim_setup_info.simulation_settings.advanced.min_pad_area_to_mesh @property def min_plane_area_to_mesh(self): @@ -66,7 +65,7 @@ def min_plane_area_to_mesh(self): ------- bool """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.MinPlaneAreaToMesh + return self.sim_setup_info.simulation_settings.advanced.min_plane_area_to_mesh @property def snap_length_threshold(self): @@ -76,7 +75,7 @@ def snap_length_threshold(self): ------- str """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.SnapLengthThreshold + return self.sim_setup_info.simulation_settings.advanced.snap_length_threshold @property def return_current_distribution(self): @@ -94,7 +93,7 @@ def return_current_distribution(self): bool ``True`` if return current distribution is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.ReturnCurrentDistribution + return self.sim_setup_info.simulation_settings.advanced.return_current_distribution @property def ignore_non_functional_pads(self): @@ -105,7 +104,7 @@ def ignore_non_functional_pads(self): bool `True`` if functional pads have to be ignored, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IgnoreNonFunctionalPads + return self.sim_setup_info.simulation_settings.advanced.ignore_non_functional_pads @property def include_coplane_coupling(self): @@ -121,7 +120,7 @@ def include_coplane_coupling(self): bool ``True`` if coplane coupling is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeCoPlaneCoupling + return self.sim_setup_info.simulation_settings.advanced.include_co_plane_coupling @property def include_fringe_coupling(self): @@ -133,7 +132,7 @@ def include_fringe_coupling(self): bool ``True`` if fringe coupling is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeFringeCoupling + return self.sim_setup_info.simulation_settings.advanced.include_fringe_coupling @property def include_split_plane_coupling(self): @@ -152,7 +151,7 @@ def include_split_plane_coupling(self): bool ``True`` if split plane coupling is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeSplitPlaneCoupling + return self.sim_setup_info.simulation_settings.advanced.include_split_plane_coupling @property def include_infinite_ground(self): @@ -164,7 +163,7 @@ def include_infinite_ground(self): bool ``True`` if infinite ground is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeInfGnd + return self.sim_setup_info.simulation_settings.advanced.include_inf_gnd @property def include_trace_coupling(self): @@ -176,7 +175,7 @@ def include_trace_coupling(self): bool ``True`` if trace coupling is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeTraceCoupling + return self.sim_setup_info.simulation_settings.advanced.include_trace_coupling @property def include_vi_sources(self): @@ -188,7 +187,7 @@ def include_vi_sources(self): bool ``True`` if vi sources is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeVISources + return self.sim_setup_info.simulation_settings.advanced.include_vi_sources @property def infinite_ground_location(self): @@ -198,7 +197,7 @@ def infinite_ground_location(self): ------- str """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.InfGndLocation + return self.sim_setup_info.simulation_settings.advanced.inf_gnd_location @property def max_coupled_lines(self): @@ -208,7 +207,7 @@ def max_coupled_lines(self): ------- int """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.MaxCoupledLines + return self.sim_setup_info.simulation_settings.advanced.max_coupled_lines @property def automatic_mesh(self): @@ -221,7 +220,7 @@ def automatic_mesh(self): bool ``True`` if automatic mesh is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.MeshAutoMatic + return self.sim_setup_info.simulation_settings.advanced.mesh_automatic @property def perform_erc(self): @@ -236,7 +235,7 @@ def perform_erc(self): bool ``True`` if perform erc is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.AdvancedSettings.PerformERC + return self.sim_setup_info.simulation_settings.advanced.perform_erc @property def mesh_frequency(self): @@ -246,115 +245,125 @@ def mesh_frequency(self): ------- str """ - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - return self.sim_setup_info.SimulationSettings.AdvancedSettings.MeshFrequency + return self.sim_setup_info.simulation_settings.advanced.mesh_frequency @include_inter_plane_coupling.setter def include_inter_plane_coupling(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeInterPlaneCoupling = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.include_inter_plane_coupling = value + self._parent._update_setup() @xtalk_threshold.setter def xtalk_threshold(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.XtalkThreshold = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.cross_talk_threshold = value + self._parent._update_setup() @min_void_area.setter def min_void_area(self, value): - self.sim_setup_info.SimulationSettings.AdvancedSettings.MinVoidArea = value + self.sim_setup_info.simulation_settings.advanced.min_void_area = value self._parent._update_setup() @min_pad_area_to_mesh.setter def min_pad_area_to_mesh(self, value): - self.sim_setup_info.SimulationSettings.AdvancedSettings.MinPadAreaToMesh = value + self.sim_setup_info.simulation_settings.advanced.min_pad_area_to_mesh = value self._parent._update_setup() @min_plane_area_to_mesh.setter def min_plane_area_to_mesh(self, value): - self.sim_setup_info.SimulationSettings.AdvancedSettings.MinPlaneAreaToMesh = value + self.sim_setup_info.simulation_settings.advanced.min_plane_area_to_mesh = value self._parent._update_setup() @snap_length_threshold.setter def snap_length_threshold(self, value): - self.sim_setup_info.SimulationSettings.AdvancedSettings.SnapLengthThreshold = value + self.sim_setup_info.simulation_settings.advanced.snap_length_threshold = value self._parent._update_setup() @return_current_distribution.setter def return_current_distribution(self, value): - self.sim_setup_info.SimulationSettings.AdvancedSettings.ReturnCurrentDistribution = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.advanced.return_current_distribution = value + self._parent._update_setup() @ignore_non_functional_pads.setter def ignore_non_functional_pads(self, value): - self.sim_setup_info.SimulationSettings.AdvancedSettings.IgnoreNonFunctionalPads = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.advanced.ignore_non_functional_pads = value + self._parent._update_setup() @include_coplane_coupling.setter def include_coplane_coupling(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeCoPlaneCoupling = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.include_co_plane_coupling = value + self._parent._update_setup() @include_fringe_coupling.setter def include_fringe_coupling(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeFringeCoupling = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.use_customer_settings = True + self.sim_setup_info.simulation_settings.advanced.include_fringe_coupling = value + self._parent._update_setup() @include_split_plane_coupling.setter def include_split_plane_coupling(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeSplitPlaneCoupling = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.include_split_plane_coupling = value + self._parent._update_setup() @include_infinite_ground.setter def include_infinite_ground(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeInfGnd = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.include_inf_gnd = value + self._parent._update_setup() @include_trace_coupling.setter def include_trace_coupling(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeTraceCoupling = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.include_trace_coupling = value + self._parent._update_setup() @include_vi_sources.setter def include_vi_sources(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.IncludeVISources = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.include_vi_sources = value + self._parent._update_setup() @infinite_ground_location.setter def infinite_ground_location(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.InfGndLocation = value + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.inf_gnd_location = value self._parent._update_setup() @max_coupled_lines.setter def max_coupled_lines(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.MaxCoupledLines = value + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.max_coupled_lines = value self._parent._update_setup() @automatic_mesh.setter def automatic_mesh(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.MeshAutoMatic = value + self.sim_setup_info.simulation_settings.use_custom_settings = True + self.sim_setup_info.simulation_settings.advanced.mesh_automatic = value self._parent._update_setup() @perform_erc.setter def perform_erc(self, value): - self.sim_setup_info.SimulationSettings.AdvancedSettings.PerformERC = value + self.sim_setup_info.simulation_settings.advanced.perform_erc = value self._parent._update_setup() @mesh_frequency.setter def mesh_frequency(self, value): - self.sim_setup_info.SimulationSettings.UseCustomSettings = True - self.sim_setup_info.SimulationSettings.AdvancedSettings.MeshFrequency = value - self._parent._update_setup() + if isinstance(value, bool): + self.sim_setup_info.SimulationSettings.UseCustomSettings = True + self.sim_setup_info.SimulationSettings.AdvancedSettings.MeshFrequency = value + self._parent._update_setup() class SiwaveDCAdvancedSettings(object): @@ -375,7 +384,7 @@ def min_void_area(self): ------- float """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.DcMinVoidAreaToMesh + return self.sim_setup_info.simulation_settings.dc_advanced.dc_min_void_area_to_mesh @property def min_plane_area(self): @@ -385,7 +394,7 @@ def min_plane_area(self): ------- float """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.DcMinPlaneAreaToMesh + return self.sim_setup_info.simulation_settings.dc_advanced.dc_min_plane_area_to_mesh @property def energy_error(self): @@ -395,7 +404,7 @@ def energy_error(self): ------- float """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.EnergyError + return self.sim_setup_info.simulation_settings.dc_advanced.energy_error @property def max_init_mesh_edge_length(self): @@ -405,7 +414,7 @@ def max_init_mesh_edge_length(self): ------- float """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MaxInitMeshEdgeLength + return self.sim_setup_info.simulation_settings.dc_advanced.max_init_mesh_edge_length @property def max_num_pass(self): @@ -415,7 +424,7 @@ def max_num_pass(self): ------- int """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MaxNumPasses + return self.sim_setup_info.simulation_settings.dc_advanced.max_num_passes @property def min_num_pass(self): @@ -425,7 +434,7 @@ def min_num_pass(self): ------- int """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MinNumPasses + return self.sim_setup_info.simulation_settings.dc_advanced.min_num_passes @property def mesh_bondwires(self): @@ -435,7 +444,7 @@ def mesh_bondwires(self): ------- bool """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshBws + return self.sim_setup_info.simulation_settings.dc_advanced.mesh_bws @property def mesh_vias(self): @@ -445,7 +454,7 @@ def mesh_vias(self): ------- bool """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshVias + return self.sim_setup_info.simulation_settings.dc_advanced.mesh_vias @property def num_bondwire_sides(self): @@ -455,7 +464,7 @@ def num_bondwire_sides(self): ------- int """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.NumBwSides + return self.sim_setup_info.simulation_settings.dc_advanced.num_bw_sides @property def num_via_sides(self): @@ -465,7 +474,7 @@ def num_via_sides(self): ------- int """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.NumViaSides + return self.sim_setup_info.simulation_settings.dc_advanced.num_via_sides @property def percent_local_refinement(self): @@ -475,7 +484,7 @@ def percent_local_refinement(self): ------- float """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.PercentLocalRefinement + return self.sim_setup_info.simulation_settings.dc_advanced.percent_local_refinement @property def perform_adaptive_refinement(self): @@ -486,7 +495,7 @@ def perform_adaptive_refinement(self): bool ``True`` if adaptive refinement is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.PerformAdaptiveRefinement + return self.sim_setup_info.simulation_settings.dc_advanced.perform_adaptive_refinement @property def refine_bondwires(self): @@ -497,7 +506,7 @@ def refine_bondwires(self): bool ``True`` if refine bondwires is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.RefineBws + return self.sim_setup_info.simulation_settings.dc_advanced.refine_bws @property def refine_vias(self): @@ -509,7 +518,7 @@ def refine_vias(self): ``True`` if via refinement is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.DCAdvancedSettings.RefineVias + return self.sim_setup_info.simulation_settings.dc_advanced.refine_vias @property def compute_inductance(self): @@ -520,7 +529,7 @@ def compute_inductance(self): bool ``True`` if inductances will be computed, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.DCSettings.ComputeInductance + return self.sim_setup_info.simulation_settings.dc.compute_inductance @property def contact_radius(self): @@ -530,7 +539,7 @@ def contact_radius(self): ------- str """ - return self.sim_setup_info.SimulationSettings.DCSettings.ContactRadius + return self.sim_setup_info.simulation_settings.dc.contact_radius @property def dc_slider_position(self): @@ -540,7 +549,7 @@ def dc_slider_position(self): ------- int """ - return self.sim_setup_info.SimulationSettings.DCSettings.DCSliderPos + return self.sim_setup_info.simulation_settings.dc.dc_slider_pos @property def use_dc_custom_settings(self): @@ -552,7 +561,7 @@ def use_dc_custom_settings(self): bool ``True`` if custom dc settings are used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings + return self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings @property def plot_jv(self): @@ -563,21 +572,21 @@ def plot_jv(self): bool ``True`` if plot JV is used, ``False`` otherwise. """ - return self.sim_setup_info.SimulationSettings.DCSettings.PlotJV + return self.sim_setup_info.simulation_settings.dc.plot_jv @plot_jv.setter def plot_jv(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.PlotJV = value + self.sim_setup_info.simulation_settings.dc.plot_jv = value self._parent._update_setup() @compute_inductance.setter def compute_inductance(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.ComputeInductance = value + self.sim_setup_info.simulation_settings.dc.compute_inductance = value self._parent._update_setup() @contact_radius.setter def contact_radius(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.ContactRadius = value + self.sim_setup_info.simulation_settings.dc.contact_radius = value self._parent._update_setup() @dc_slider_position.setter @@ -588,99 +597,99 @@ def dc_slider_position(self, value): 1- ``balanced`` 2- ``optimal accuracy``. """ - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = False - self.sim_setup_info.SimulationSettings.DCSettings.DCSliderPos = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = False + self.sim_setup_info.simulation_settings.dc.dc_slider_pos = value self._parent._update_setup() @use_dc_custom_settings.setter def use_dc_custom_settings(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = value self._parent._update_setup() @min_void_area.setter def min_void_area(self, value): - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.DcMinVoidAreaToMesh = value + self.sim_setup_info.simulation_settings.dc_advanced.dc_min_void_area_to_mesh = value self._parent._update_setup() @min_plane_area.setter def min_plane_area(self, value): - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.DcMinPlaneAreaToMesh = value + self.sim_setup_info.simulation_settings.dc_advanced.dc_min_plane_area_to_mesh = value self._parent._update_setup() @energy_error.setter def energy_error(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.EnergyError = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.energy_error = value self._parent._update_setup() @max_init_mesh_edge_length.setter def max_init_mesh_edge_length(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MaxInitMeshEdgeLength = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.max_init_mesh_edge_length = value self._parent._update_setup() @max_num_pass.setter def max_num_pass(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MaxNumPasses = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.max_num_passes = value self._parent._update_setup() @min_num_pass.setter def min_num_pass(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MinNumPasses = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.min_num_passes = value self._parent._update_setup() @mesh_bondwires.setter def mesh_bondwires(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshBws = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.mesh_bws = value self._parent._update_setup() @mesh_vias.setter def mesh_vias(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshVias = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.mesh_vias = value self._parent._update_setup() @num_bondwire_sides.setter def num_bondwire_sides(self, value): - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshBws = True - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.NumBwSides = value + self.sim_setup_info.simulation_settings.dc_advanced.mesh_bws = True + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.num_bw_sides = value self._parent._update_setup() @num_via_sides.setter def num_via_sides(self, value): - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshVias = True - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.NumViaSides = value + self.sim_setup_info.simulation_settings.dc_advanced.mesh_vias = True + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.num_via_sides = value self._parent._update_setup() @percent_local_refinement.setter def percent_local_refinement(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.PercentLocalRefinement = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.percent_local_refinement = value self._parent._update_setup() @perform_adaptive_refinement.setter def perform_adaptive_refinement(self, value): - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.PerformAdaptiveRefinement = value + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.perform_adaptive_refinement = value self._parent._update_setup() @refine_bondwires.setter def refine_bondwires(self, value): - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshBws = True - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.RefineBws = value + self.sim_setup_info.simulation_settings.dc_advanced.mesh_bws = True + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.refine_bws = value self._parent._update_setup() @refine_vias.setter def refine_vias(self, value): - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.MeshVias = True - self.sim_setup_info.SimulationSettings.DCSettings.UseDCCustomSettings = True - self.sim_setup_info.SimulationSettings.DCAdvancedSettings.RefineVias = value + self.sim_setup_info.simulation_settings.dc_advanced.mesh_vias = True + self.sim_setup_info.simulation_settings.dc.use_dc_custom_settings = True + self.sim_setup_info.simulation_settings.dc_advanced.refine_vias = value self._parent._update_setup() @@ -709,12 +718,12 @@ def edb_sim_setup_info(self): """EDB internal simulation setup object.""" return self._edb_sim_setup_info - @pyaedt_function_handler() + @pyedb_function_handler() def _update_setup(self): - self._edb_sim_setup = self._edb.edb_api.utility.utility.SIWaveSimulationSetup(self._edb_sim_setup_info) + self._edb_sim_setup = SIWaveSimulationSetup(self._edb_sim_setup_info) if self.name in self._edb.setups: - self._edb.layout.cell.DeleteSimulationSetup(self.name) - self._edb.layout.cell.AddSimulationSetup(self._edb_sim_setup) + self._edb.layout.cell.delete_simulation_setup(self.name) + self._edb.layout.cell.add_simulation_setup(self._edb_sim_setup) return True @property @@ -733,14 +742,14 @@ def frequency_sweeps(self): if self._sweep_data_list: return self._sweep_data_list self._sweep_data_list = {} - for i in list(self._edb_sim_setup_info.SweepDataList): + for i in list(self._edb_sim_setup_info.sweep_data): self._sweep_data_list[i.Name] = EdbFrequencySweep(self, None, i.Name, i) return self._sweep_data_list @property def name(self): """Setup name.""" - return self._edb_sim_setup_info.Name + return self._edb_sim_setup_info.name @name.setter def name(self, value): @@ -754,33 +763,33 @@ def name(self, value): @property def enabled(self): """Whether the setup is enabled.""" - return self._edb_sim_setup_info.SimulationSettings.Enabled + return self._edb_sim_setup_info.simulation_settings.enabled @property def pi_slider_postion(self): """PI solider position. Values are from ``1`` to ``3``.""" - return self._edb_sim_setup_info.SimulationSettings.PISliderPos + return self._edb_sim_setup_info.simulation_settings.pi_slider_pos @property def si_slider_postion(self): """SI solider position. Values are from ``1`` to ``3``.""" - return self._edb_sim_setup_info.SimulationSettings.SISliderPos + return self._edb_sim_setup_info.simulation_settings.si_slider_pos @enabled.setter def enabled(self, value): - self._edb_sim_setup_info.SimulationSettings.Enabled = value + self._edb_sim_setup_info.simulation_settings.enabled = value self._update_setup() @pi_slider_postion.setter def pi_slider_postion(self, value): - self._edb_sim_setup_info.SimulationSettings.UseCustomSettings = False - self._edb_sim_setup_info.SimulationSettings.PISliderPos = value + self._edb_sim_setup_info.simulation_settings.use_custom_settings = False + self._edb_sim_setup_info.simulation_settings.pi_slider_pos = value self._update_setup() @si_slider_postion.setter def si_slider_postion(self, value): - self._edb_sim_setup_info.SimulationSettings.UseCustomSettings = False - self._edb_sim_setup_info.SimulationSettings.SISliderPos = value + self._edb_sim_setup_info.simulation_settings.use_custom_settings = False + self._edb_sim_setup_info.simulation_settings.si_slider_pos = value self._update_setup() @property @@ -791,11 +800,11 @@ def use_custom_settings(self): ------- bool """ - return self._edb_sim_setup_info.SimulationSettings.UseCustomSettings + return self._edb_sim_setup_info.simulation_settings.use_custom_settings @use_custom_settings.setter def use_custom_settings(self, value): - self._edb_sim_setup_info.SimulationSettings.UseCustomSettings = value + self._edb_sim_setup_info.simulation_settings.use_custom_settings = value self._update_setup() @property @@ -806,15 +815,15 @@ def use_si_settings(self): ------- bool """ - return self._edb_sim_setup_info.SimulationSettings.UseSISettings + return self._edb_sim_setup_info.simulation_settings.use_si_settings @use_si_settings.setter def use_si_settings(self, value): - self._edb_sim_setup_info.SimulationSettings.UseCustomSettings = False - self._edb_sim_setup_info.SimulationSettings.UseSISettings = value + self._edb_sim_setup_info.simulation_settings.use_custom_settings = False + self._edb_sim_setup_info.simulation_settings.use_si_settings = value self._update_setup() - @pyaedt_function_handler() + @pyedb_function_handler() def add_frequency_sweep(self, name=None, frequency_sweep=None): """Add frequency sweep. @@ -880,11 +889,9 @@ def _parse_value(v): return pv -@pyaedt_function_handler() +@pyedb_function_handler() def _get_edb_setup_info(edb_siwave_sim_setup, edb_sim_setup_info): - string = edb_siwave_sim_setup.ToString().replace("\t", "").split("\r\n") - if is_linux: - string = string[0].split("\n") + string = str(edb_siwave_sim_setup).replace("\t", "").split("\r\n") keys = [i.split("=")[0] for i in string if len(i.split("=")) == 2 and "SourceTermsToGround" not in i] values = [i.split("=")[1] for i in string if len(i.split("=")) == 2 and "SourceTermsToGround" not in i] for val in string: @@ -896,26 +903,26 @@ def _get_edb_setup_info(edb_siwave_sim_setup, edb_sim_setup_info): for v in val: source = v.split("=") sources[source[0]] = source[1] - edb_sim_setup_info.SimulationSettings.DCIRSettings.SourceTermsToGround = convert_pydict_to_netdict(sources) + edb_sim_setup_info.simulation_settings.dc_ir_settings.source_terms_to_ground = sources break for k in keys: value = _parse_value(values[keys.index(k)]) setter = None - if k in dir(edb_sim_setup_info.SimulationSettings): - setter = edb_sim_setup_info.SimulationSettings - elif k in dir(edb_sim_setup_info.SimulationSettings.AdvancedSettings): - setter = edb_sim_setup_info.SimulationSettings.AdvancedSettings - - elif k in dir(edb_sim_setup_info.SimulationSettings.DCAdvancedSettings): - setter = edb_sim_setup_info.SimulationSettings.DCAdvancedSettings - elif "DCIRSettings" in dir(edb_sim_setup_info.SimulationSettings) and k in dir( - edb_sim_setup_info.SimulationSettings.DCIRSettings + if k in dir(edb_sim_setup_info.simulation_settings): + setter = edb_sim_setup_info.simulation_settings + elif k in dir(edb_sim_setup_info.simulation_settings.advanced_settings): + setter = edb_sim_setup_info.simulation_settings.advanced_settings + + elif k in dir(edb_sim_setup_info.simulation_settings.dc_advanced_settings): + setter = edb_sim_setup_info.simulation_settings.dc_advanced_settings + elif "DCIRSettings" in dir(edb_sim_setup_info.simulation_settings) and k in dir( + edb_sim_setup_info.simulation_settings.dc_ir_settings ): - setter = edb_sim_setup_info.SimulationSettings.DCIRSettings - elif k in dir(edb_sim_setup_info.SimulationSettings.DCSettings): - setter = edb_sim_setup_info.SimulationSettings.DCSettings - elif k in dir(edb_sim_setup_info.SimulationSettings.AdvancedSettings): - setter = edb_sim_setup_info.SimulationSettings.AdvancedSettings + setter = edb_sim_setup_info.simulation_settings.dc_ir_settings + elif k in dir(edb_sim_setup_info.simulation_settings.dc_settings): + setter = edb_sim_setup_info.simulation_settings.dc_settings + elif k in dir(edb_sim_setup_info.simulation_settings.advanced_settings): + setter = edb_sim_setup_info.simulation_settings.advanced_settings if setter: try: setter.__setattr__(k, value) @@ -932,17 +939,15 @@ class SiwaveDCSimulationSetup(SiwaveDCAdvancedSettings, object): def __init__(self, edb, name=None, edb_siwave_sim_setup=None): self._edb = edb self._mesh_operations = {} - self._edb_sim_setup_info = self._edb.simsetupdata.SimSetupInfo[ - self._edb.simsetupdata.SIwave.SIWDCIRSimulationSettings - ]() + self._edb_sim_setup_info = SiwaveDCSimulationSetup() if edb_siwave_sim_setup: _get_edb_setup_info(edb_siwave_sim_setup, self._edb_sim_setup_info) else: if not name: - self._edb_sim_setup_info.Name = generate_unique_name("siwave") + self._edb_sim_setup_info.name = generate_unique_name("siwave") else: - self._edb_sim_setup_info.Name = name + self._edb_sim_setup_info.name = name self._update_setup() self.setup_type = "kSIWaveDCIR" @@ -953,24 +958,24 @@ def edb_sim_setup_info(self): """EDB internal simulation setup object.""" return self._edb_sim_setup_info - @pyaedt_function_handler() + @pyedb_function_handler() def _update_setup(self): - edb_sim_setup = self._edb.edb_api.utility.utility.SIWaveDCIRSimulationSetup(self._edb_sim_setup_info) + edb_sim_setup = SiwaveDCSimulationSetup(self._edb_sim_setup_info) if self.name in self._edb.setups: - self._edb.layout.cell.DeleteSimulationSetup(self.name) - self._edb.active_cell.AddSimulationSetup(edb_sim_setup) + self._edb.layout.cell.delete_simulation_setupSetup(self.name) + self._edb.active_cell.add_simulation_setup(edb_sim_setup) return True @property def name(self): """Setup name.""" - return self._edb_sim_setup_info.Name + return self._edb_sim_setup_info.name @name.setter def name(self, value): """Set name of the setup.""" - legacy_name = self._edb_sim_setup_info.Name - self._edb_sim_setup_info.Name = value + legacy_name = self._edb_sim_setup_info.name + self._edb_sim_setup_info.name = value self._update_setup() if legacy_name in self._edb.setups: del self._edb._setups[legacy_name] @@ -978,11 +983,11 @@ def name(self, value): @property def enabled(self): """Whether setup is enabled.""" - return self._edb_sim_setup_info.SimulationSettings.Enabled + return self._edb_sim_setup_info.simulation_settings.enabled @enabled.setter def enabled(self, value): - self._edb_sim_setup_info.SimulationSettings.Enabled = value + self._edb_sim_setup_info.simulation_settings.enabled = value self._update_setup() @property @@ -995,7 +1000,7 @@ def source_terms_to_ground(self): {str, int}, keys is source name, value int 0 unspecified, 1 negative node, 2 positive one. """ - return convert_netdict_to_pydict(self._edb_sim_setup_info.SimulationSettings.DCIRSettings.SourceTermsToGround) + return self._edb_sim_setup_info.simulation_settings.dc_settings.source_terms_to_ground @pyaedt_function_handler() def add_source_terminal_to_ground(self, source_name, terminal=0): @@ -1019,7 +1024,5 @@ def add_source_terminal_to_ground(self, source_name, terminal=0): """ terminals = self.source_terms_to_ground terminals[source_name] = terminal - self._edb_sim_setup_info.SimulationSettings.DCIRSettings.SourceTermsToGround = convert_pydict_to_netdict( - terminals - ) + self._edb_sim_setup_info.simullation_settings.dc_ir.source_terms_to_ground = terminals return self._update_setup() diff --git a/src/pyedb/grpc/edb_data/sources.py b/src/pyedb/grpc/edb_data/sources.py index f7a3bc6c0a..43df72434e 100644 --- a/src/pyedb/grpc/edb_data/sources.py +++ b/src/pyedb/grpc/edb_data/sources.py @@ -1,6 +1,8 @@ -from pyaedt import pyaedt_function_handler -from pyaedt.generic.constants import NodeType -from pyaedt.generic.constants import SourceType +from pyedb.generic.general_methods import pyedb_function_handler +from pyedb.generic.constants import NodeType +from pyedb.generic.constants import SourceType +from ansys.edb.terminal.terminals import BoundaryType +from ansys.edb.utility.value import Value class Node(object): @@ -272,16 +274,16 @@ def net(self, value): @property def net_name(self): - return self._edb_pin_group.GetNet().GetName() + return self._edb_pin_group.net.name - @pyaedt_function_handler() + @pyedb_function_handler() def _create_pin_group_terminal(self, is_reference=False): - pg_term = self._edb_pin_group.GetPinGroupTerminal() - pin_group_net = self._edb_pin_group.GetNet() - if pin_group_net.IsNull(): # pragma: no cover - pin_group_net = list(self._edb_pin_group.GetPins())[0].GetNet() + pg_term = self._edb_pin_group.pin_group_terminal() + pin_group_net = self._edb_pin_group.net + if pin_group_net.is_null: # pragma: no cover + pin_group_net = self._edb_pin_group.pins[0].net if pg_term.IsNull(): - return self._pedb.edb_api.cell.terminal.PinGroupTerminal.Create( + return self._pedb.cell.terminal.pin_group_terminal.create( self._active_layout, pin_group_net, self.name, @@ -291,39 +293,39 @@ def _create_pin_group_terminal(self, is_reference=False): else: return pg_term - @pyaedt_function_handler() + @pyedb_function_handler() def create_current_source_terminal(self, magnitude=1, phase=0): terminal = self._create_pin_group_terminal() - terminal.SetBoundaryType(self._pedb.edb_api.cell.terminal.BoundaryType.kCurrentSource) - terminal.SetSourceAmplitude(self._pedb.edb_value(magnitude)) - terminal.SetSourcePhase(self._pedb.edb_api.utility.value(phase)) + terminal.boundary_type = BoundaryType.CURRENT_SOURCE + terminal.source_amplitude = Value(magnitude) + terminal.source_phase = Value(phase) return terminal - @pyaedt_function_handler() + @pyedb_function_handler() def create_voltage_source_terminal(self, magnitude=1, phase=0, impedance=0.001): terminal = self._create_pin_group_terminal() - terminal.SetBoundaryType(self._pedb.edb_api.cell.terminal.BoundaryType.kVoltageSource) - terminal.SetSourceAmplitude(self._pedb.edb_value(magnitude)) - terminal.SetSourcePhase(self._pedb.edb_api.utility.value(phase)) - terminal.SetImpedance(self._pedb.edb_value(impedance)) + terminal.boundary_type = BoundaryType.VOLTAGE_SOURCE + terminal.source_amplitude = Value(magnitude) + terminal.source_phase = Value(phase) + terminal.impedance = Value(impedance) return terminal - @pyaedt_function_handler() + @pyedb_function_handler() def create_voltage_probe_terminal(self, impedance=1000000): terminal = self._create_pin_group_terminal() - terminal.SetBoundaryType(self._pedb.edb_api.cell.terminal.BoundaryType.kVoltageProbe) - terminal.SetImpedance(self._pedb.edb_value(impedance)) + terminal.boundary_type = BoundaryType.VOLTAGE_PROBE + terminal.impedance = Value(impedance) return terminal - @pyaedt_function_handler() + @pyedb_function_handler() def create_port_terminal(self, impedance=50): terminal = self._create_pin_group_terminal() - terminal.SetBoundaryType(self._pedb.edb_api.cell.terminal.BoundaryType.PortBoundary) - terminal.SetImpedance(self._pedb.edb_value(impedance)) + terminal.boundary_type = BoundaryType.PORT + terminal.impedance = Value(impedance) terminal.SetIsCircuitPort(True) return terminal - @pyaedt_function_handler() + @pyedb_function_handler() def delete(self): """Delete active pin group. @@ -332,9 +334,9 @@ def delete(self): bool """ - terminals = self._edb_pin_group.GetPinGroupTerminal() - self._edb_pin_group.Delete() - terminals.Delete() + terminals = self._edb_pin_group.pin_group_terminal + self._edb_pin_group.delete() + terminals.delete() return True diff --git a/src/pyedb/grpc/layout.py b/src/pyedb/grpc/layout.py index 0b225fe2e7..7fd6599b0a 100644 --- a/src/pyedb/grpc/layout.py +++ b/src/pyedb/grpc/layout.py @@ -4,16 +4,15 @@ import math import warnings -from pyaedt.edb_core.dotnet.primitive import BondwireDotNet -from pyaedt.edb_core.dotnet.primitive import CircleDotNet -from pyaedt.edb_core.dotnet.primitive import PathDotNet -from pyaedt.edb_core.dotnet.primitive import PolygonDotNet -from pyaedt.edb_core.dotnet.primitive import RectangleDotNet -from pyaedt.edb_core.edb_data.primitives_data import EDBPrimitives -from pyaedt.edb_core.edb_data.primitives_data import cast -from pyaedt.edb_core.edb_data.utilities import EDBStatistics -from pyaedt.edb_core.general import convert_py_list_to_net_list -from pyaedt.generic.general_methods import pyaedt_function_handler +from ansys.edb.primitive import Bondwire +from ansys.edb.primitive import Circle +from ansys.edb.primitive import Path +from ansys.edb.primitive import Polygon +from ansys.edb.primitive import Rectangle +from edb_data.primitives_data import EDBPrimitives +from edb_data.primitives_data import cast +from edb_data.utilities import EDBStatistics +from pyedb.generic.general_methods import pyedb_function_handler class EdbLayout(object): @@ -21,7 +20,7 @@ class EdbLayout(object): Examples -------- - >>> from pyaedt import Edb + >>> from pyedb import Edb >>> edbapp = Edb("myaedbfolder", edbversion="2021.2") >>> edb_layout = edbapp.modeler """ diff --git a/src/pyedb/legacy/edb_core/padstack.py b/src/pyedb/legacy/edb_core/padstack.py index 082ab7ef3e..0365f19945 100644 --- a/src/pyedb/legacy/edb_core/padstack.py +++ b/src/pyedb/legacy/edb_core/padstack.py @@ -147,8 +147,6 @@ def int_to_geometry_type(self, val=0): return self._edb.definition.PadGeometryType.Square45 elif val == 11: return self._edb.definition.PadGeometryType.Square90 - elif val == 12: - return self._edb.definition.PadGeometryType.InvalidGeometry else: return val diff --git a/src/pyedb/grpc/modeler/geometry_operators.py b/src/pyedb/modeler/geometry_operators.py similarity index 100% rename from src/pyedb/grpc/modeler/geometry_operators.py rename to src/pyedb/modeler/geometry_operators.py