pyedb 0.27.0__py3-none-any.whl → 0.28.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_data.py +1 -1
- pyedb/configuration/cfg_operations.py +5 -3
- pyedb/configuration/cfg_padstacks.py +43 -36
- pyedb/configuration/cfg_pin_groups.py +7 -8
- pyedb/configuration/configuration.py +14 -3
- pyedb/dotnet/application/Variables.py +43 -41
- pyedb/dotnet/edb_core/cell/layout.py +4 -1
- pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py +3 -3
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +251 -45
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +2 -2
- pyedb/dotnet/edb_core/general.py +11 -0
- pyedb/dotnet/edb_core/modeler.py +5 -2
- pyedb/edb_logger.py +1 -1
- pyedb/siwave.py +33 -7
- {pyedb-0.27.0.dist-info → pyedb-0.28.0.dist-info}/METADATA +4 -4
- {pyedb-0.27.0.dist-info → pyedb-0.28.0.dist-info}/RECORD +19 -19
- {pyedb-0.27.0.dist-info → pyedb-0.28.0.dist-info}/LICENSE +0 -0
- {pyedb-0.27.0.dist-info → pyedb-0.28.0.dist-info}/WHEEL +0 -0
pyedb/__init__.py
CHANGED
pyedb/configuration/cfg_data.py
CHANGED
|
@@ -53,7 +53,7 @@ class CfgData(object):
|
|
|
53
53
|
|
|
54
54
|
self.components = CfgComponents(self._pedb, components_data=kwargs.get("components", []))
|
|
55
55
|
|
|
56
|
-
self.padstacks = CfgPadstacks(self, kwargs.get("padstacks", None))
|
|
56
|
+
self.padstacks = CfgPadstacks(self._pedb, kwargs.get("padstacks", None))
|
|
57
57
|
|
|
58
58
|
self.pin_groups = CfgPinGroups(self._pedb, pingroup_data=kwargs.get("pin_groups", []))
|
|
59
59
|
|
|
@@ -65,7 +65,7 @@ class CfgCutout(CfgBase):
|
|
|
65
65
|
|
|
66
66
|
self.reference_list = []
|
|
67
67
|
self.signal_list = net_names
|
|
68
|
-
|
|
68
|
+
return self.export_properties()
|
|
69
69
|
|
|
70
70
|
def export_properties(self):
|
|
71
71
|
return {
|
|
@@ -84,7 +84,7 @@ class CfgOperations(CfgBase):
|
|
|
84
84
|
"""Imports operation information from JSON."""
|
|
85
85
|
if self.op_cutout:
|
|
86
86
|
polygon_points = self._pedb.cutout(**self.op_cutout.get_attributes())
|
|
87
|
-
if
|
|
87
|
+
if "pyedb_cutout" not in self._pedb.stackup.all_layers:
|
|
88
88
|
self._pedb.stackup.add_document_layer(name="pyedb_cutout")
|
|
89
89
|
self._pedb.modeler.create_polygon(polygon_points, layer_name="pyedb_cutout", net_name="pyedb_cutout")
|
|
90
90
|
|
|
@@ -92,4 +92,6 @@ class CfgOperations(CfgBase):
|
|
|
92
92
|
|
|
93
93
|
def get_data_from_db(self):
|
|
94
94
|
self.op_cutout = CfgCutout(self._pedb)
|
|
95
|
-
|
|
95
|
+
data_from_db = self.op_cutout.get_data_from_db()
|
|
96
|
+
if data_from_db:
|
|
97
|
+
return {"cutout": data_from_db}
|
|
@@ -23,62 +23,69 @@
|
|
|
23
23
|
|
|
24
24
|
from enum import Enum
|
|
25
25
|
|
|
26
|
+
from pyedb.configuration.cfg_common import CfgBase
|
|
27
|
+
|
|
26
28
|
|
|
27
29
|
class CfgPadstacks:
|
|
28
30
|
"""Padstack data class."""
|
|
29
31
|
|
|
30
|
-
def __init__(self,
|
|
31
|
-
self._pedb =
|
|
32
|
+
def __init__(self, pedb, padstack_dict=None):
|
|
33
|
+
self._pedb = pedb
|
|
32
34
|
self.definitions = []
|
|
33
35
|
self.instances = []
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
if self._padstack_dict.get("instances", None):
|
|
40
|
-
self._instances_dict = self._padstack_dict.get("instances", "")
|
|
41
|
-
self.instances = [Instance(pdata, inst) for inst in self._instances_dict]
|
|
36
|
+
if padstack_dict:
|
|
37
|
+
for pdef in padstack_dict.get("definitions", []):
|
|
38
|
+
self.definitions.append(Definition(**pdef))
|
|
39
|
+
for inst in padstack_dict.get("instances", []):
|
|
40
|
+
self.instances.append(Instance(self._pedb, inst))
|
|
42
41
|
|
|
43
42
|
def apply(self):
|
|
44
43
|
"""Apply padstack definition and instances on layout."""
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
padstack_defs_layout = self._pedb.padstacks.definitions
|
|
45
|
+
for pdef in self.definitions:
|
|
46
|
+
pdef_layout = padstack_defs_layout[pdef.name]
|
|
47
|
+
pdef_layout.set_properties(**pdef.get_attributes())
|
|
47
48
|
for instance in self.instances:
|
|
48
49
|
instance.apply()
|
|
49
50
|
|
|
51
|
+
def get_data_from_db(self):
|
|
52
|
+
self.definitions = []
|
|
53
|
+
for pdef_name, pdef in self._pedb.padstacks.definitions.items():
|
|
54
|
+
self.definitions.append(
|
|
55
|
+
Definition(
|
|
56
|
+
name=pdef_name,
|
|
57
|
+
hole_plating_thickness=pdef.hole_plating_thickness,
|
|
58
|
+
hole_material=pdef.material,
|
|
59
|
+
hole_range=pdef.hole_range,
|
|
60
|
+
pad_parameters=pdef.pad_parameters,
|
|
61
|
+
hole_parameters=pdef.hole_parameters,
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
data = {}
|
|
65
|
+
definitions = []
|
|
66
|
+
for i in self.definitions:
|
|
67
|
+
definitions.append(i.get_attributes())
|
|
68
|
+
data["definitions"] = definitions
|
|
69
|
+
return data
|
|
70
|
+
|
|
50
71
|
|
|
51
|
-
class Definition:
|
|
72
|
+
class Definition(CfgBase):
|
|
52
73
|
"""Padstack definition data class."""
|
|
53
74
|
|
|
54
|
-
def __init__(self,
|
|
55
|
-
self.
|
|
56
|
-
self.
|
|
57
|
-
self.
|
|
58
|
-
self.
|
|
59
|
-
self.
|
|
60
|
-
self.
|
|
61
|
-
self.hole_range = self._definition_dict.get("hole_range", None)
|
|
62
|
-
|
|
63
|
-
def apply(self):
|
|
64
|
-
"""Apply padstack definition on layout."""
|
|
65
|
-
padstack_defs = self._pedb.padstacks.definitions
|
|
66
|
-
pdef = padstack_defs[self.name]
|
|
67
|
-
if self.hole_diameter:
|
|
68
|
-
pdef.hole_diameter = self.hole_diameter
|
|
69
|
-
if self.hole_plating_thickness:
|
|
70
|
-
pdef.hole_plating_thickness = self.hole_plating_thickness
|
|
71
|
-
if self.hole_material:
|
|
72
|
-
pdef.material = self.hole_material
|
|
73
|
-
if self.hole_range:
|
|
74
|
-
pdef.hole_range = self.hole_range
|
|
75
|
+
def __init__(self, **kwargs):
|
|
76
|
+
self.name = kwargs.get("name", None)
|
|
77
|
+
self.hole_plating_thickness = kwargs.get("hole_plating_thickness", None)
|
|
78
|
+
self.material = kwargs.get("hole_material", None)
|
|
79
|
+
self.hole_range = kwargs.get("hole_range", None)
|
|
80
|
+
self.pad_parameters = kwargs.get("pad_parameters", None)
|
|
81
|
+
self.hole_parameters = kwargs.get("hole_parameters", None)
|
|
75
82
|
|
|
76
83
|
|
|
77
84
|
class Instance:
|
|
78
85
|
"""Instance data class."""
|
|
79
86
|
|
|
80
|
-
def __init__(self,
|
|
81
|
-
self._pedb =
|
|
87
|
+
def __init__(self, pedb, instances_dict):
|
|
88
|
+
self._pedb = pedb
|
|
82
89
|
self._instances_dict = instances_dict
|
|
83
90
|
self.name = self._instances_dict.get("name", "")
|
|
84
91
|
self.backdrill_top = None
|
|
@@ -36,12 +36,14 @@ class CfgPinGroups:
|
|
|
36
36
|
|
|
37
37
|
def get_data_from_db(self):
|
|
38
38
|
self.pin_groups = []
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
layout_pin_groups = self._pedb.siwave.pin_groups
|
|
40
|
+
for pg_name, pg_obj in layout_pin_groups.items():
|
|
41
|
+
pins = list(pg_obj.pins.keys())
|
|
42
|
+
refdes = list(pg_obj.pins.values())[0].component.name
|
|
41
43
|
cfg_pg = CfgPinGroup(
|
|
42
44
|
self._pedb,
|
|
43
|
-
name=
|
|
44
|
-
reference_designator=
|
|
45
|
+
name=pg_name,
|
|
46
|
+
reference_designator=refdes,
|
|
45
47
|
pins=pins,
|
|
46
48
|
)
|
|
47
49
|
self.pin_groups.append(cfg_pg)
|
|
@@ -65,10 +67,7 @@ class CfgPinGroup(CfgBase):
|
|
|
65
67
|
def create(self):
|
|
66
68
|
"""Apply pin group on layout."""
|
|
67
69
|
if self.pins:
|
|
68
|
-
|
|
69
|
-
self._pedb.modeler.create_pin_group(self.name, pins_by_aedt_name=self.pins)
|
|
70
|
-
else:
|
|
71
|
-
self._pedb.siwave.create_pin_group(self.reference_designator, list(self.pins), self.name)
|
|
70
|
+
self._pedb.siwave.create_pin_group(self.reference_designator, list(self.pins), self.name)
|
|
72
71
|
elif self.net:
|
|
73
72
|
if self.reference_designator in self._pedb.components.instances:
|
|
74
73
|
comp = self._pedb.components.instances[self.reference_designator]
|
|
@@ -74,7 +74,7 @@ class Configuration:
|
|
|
74
74
|
elif config_file.endswith(".toml"):
|
|
75
75
|
data = toml.load(f)
|
|
76
76
|
else: # pragma: no cover
|
|
77
|
-
|
|
77
|
+
raise RuntimeError(f"File {config_file} does not exist.")
|
|
78
78
|
|
|
79
79
|
if not append: # pragma: no cover
|
|
80
80
|
self.data = {}
|
|
@@ -103,7 +103,7 @@ class Configuration:
|
|
|
103
103
|
self._pedb.open_edb()
|
|
104
104
|
return self.cfg_data
|
|
105
105
|
|
|
106
|
-
def run(self):
|
|
106
|
+
def run(self, **kwargs):
|
|
107
107
|
"""Apply configuration settings to the current design"""
|
|
108
108
|
|
|
109
109
|
# Configure boundary settings
|
|
@@ -134,7 +134,16 @@ class Configuration:
|
|
|
134
134
|
self.cfg_data.setups.apply()
|
|
135
135
|
|
|
136
136
|
# Configure stackup
|
|
137
|
-
|
|
137
|
+
if kwargs.get("fix_padstack_def"):
|
|
138
|
+
pedb_defs = self._pedb.padstacks.definitions
|
|
139
|
+
temp = {}
|
|
140
|
+
for name, pdef in pedb_defs.items():
|
|
141
|
+
temp[name] = pdef.get_properties()
|
|
142
|
+
self.cfg_data.stackup.apply()
|
|
143
|
+
for name, pdef_p in temp.items():
|
|
144
|
+
pedb_defs[name].set_properties(**pdef_p)
|
|
145
|
+
else:
|
|
146
|
+
self.cfg_data.stackup.apply()
|
|
138
147
|
|
|
139
148
|
# Configure S-parameter
|
|
140
149
|
for s_parameter_model in self.cfg_data.s_parameters:
|
|
@@ -282,6 +291,8 @@ class Configuration:
|
|
|
282
291
|
data["pin_groups"] = self.cfg_data.pin_groups.get_data_from_db()
|
|
283
292
|
if kwargs.get("operations", False):
|
|
284
293
|
data["operations"] = self.cfg_data.operations.get_data_from_db()
|
|
294
|
+
if kwargs.get("padstacks", False):
|
|
295
|
+
data["padstacks"] = self.cfg_data.padstacks.get_data_from_db()
|
|
285
296
|
|
|
286
297
|
return data
|
|
287
298
|
|
|
@@ -27,7 +27,7 @@ This module is used to create and edit design and project variables in the 3D to
|
|
|
27
27
|
|
|
28
28
|
Examples
|
|
29
29
|
--------
|
|
30
|
-
>>> from
|
|
30
|
+
>>> from ansys.aedt.core import Hfss
|
|
31
31
|
>>> hfss = Hfss()
|
|
32
32
|
>>> hfss["$d"] = "5mm"
|
|
33
33
|
>>> hfss["d"] = "5mm"
|
|
@@ -415,8 +415,8 @@ class VariableManager(object):
|
|
|
415
415
|
Examples
|
|
416
416
|
--------
|
|
417
417
|
|
|
418
|
-
>>> from
|
|
419
|
-
>>> from
|
|
418
|
+
>>> from ansys.aedt.core.maxwell import Maxwell3d
|
|
419
|
+
>>> from ansys.aedt.core.desktop import Desktop
|
|
420
420
|
>>> d = Desktop()
|
|
421
421
|
>>> aedtapp = Maxwell3d()
|
|
422
422
|
|
|
@@ -1765,40 +1765,42 @@ class Variable(object):
|
|
|
1765
1765
|
def __mul__(self, other): # pragma: no cover
|
|
1766
1766
|
"""Multiply the variable with a number or another variable and return a new object.
|
|
1767
1767
|
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
import
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1768
|
+
Parameters
|
|
1769
|
+
----------
|
|
1770
|
+
other : numbers.Number or variable
|
|
1771
|
+
Object to be multiplied.
|
|
1772
|
+
|
|
1773
|
+
Returns
|
|
1774
|
+
-------
|
|
1775
|
+
type
|
|
1776
|
+
Variable.
|
|
1777
|
+
|
|
1778
|
+
Examples
|
|
1779
|
+
--------
|
|
1780
|
+
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1781
|
+
|
|
1782
|
+
Multiply ``'Length1'`` by unitless ``'None'``` to obtain ``'Length'``.
|
|
1783
|
+
A numerical value is also considered to be unitless.
|
|
1784
|
+
|
|
1785
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1786
|
+
>>> v1 = Variable("10mm")
|
|
1787
|
+
>>> v2 = Variable(3)
|
|
1788
|
+
>>> result_1 = v1 * v2
|
|
1789
|
+
>>> result_2 = v1 * 3
|
|
1790
|
+
>>> assert result_1.numeric_value == 30.0
|
|
1791
|
+
>>> assert result_1.unit_system == "Length"
|
|
1792
|
+
>>> assert result_2.numeric_value == result_1.numeric_value
|
|
1793
|
+
>>> assert result_2.unit_system == "Length"
|
|
1794
|
+
|
|
1795
|
+
Multiply voltage times current to obtain power.
|
|
1796
|
+
|
|
1797
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1798
|
+
>>> v3 = Variable("3mA")
|
|
1799
|
+
>>> v4 = Variable("40V")
|
|
1800
|
+
>>> result_3 = v3 * v4
|
|
1801
|
+
>>> assert result_3.numeric_value == 0.12
|
|
1802
|
+
>>> assert result_3.units == "W"
|
|
1803
|
+
>>> assert result_3.unit_system == "Power"
|
|
1802
1804
|
|
|
1803
1805
|
"""
|
|
1804
1806
|
assert is_number(other) or isinstance(other, Variable), "Multiplier must be a scalar quantity or a variable."
|
|
@@ -1836,7 +1838,7 @@ class Variable(object):
|
|
|
1836
1838
|
Examples
|
|
1837
1839
|
--------
|
|
1838
1840
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1839
|
-
>>> import
|
|
1841
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1840
1842
|
>>> v1 = Variable("3mA")
|
|
1841
1843
|
>>> v2 = Variable("10A")
|
|
1842
1844
|
>>> result = v1 + v2
|
|
@@ -1876,7 +1878,7 @@ class Variable(object):
|
|
|
1876
1878
|
Examples
|
|
1877
1879
|
--------
|
|
1878
1880
|
|
|
1879
|
-
>>> import
|
|
1881
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1880
1882
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1881
1883
|
>>> v3 = Variable("3mA")
|
|
1882
1884
|
>>> v4 = Variable("10A")
|
|
@@ -1922,7 +1924,7 @@ class Variable(object):
|
|
|
1922
1924
|
resolve the new units to ``"A"``.
|
|
1923
1925
|
|
|
1924
1926
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1925
|
-
>>> import
|
|
1927
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1926
1928
|
>>> v1 = Variable("10W")
|
|
1927
1929
|
>>> v2 = Variable("40V")
|
|
1928
1930
|
>>> result = v1 / v2
|
|
@@ -1964,7 +1966,7 @@ class Variable(object):
|
|
|
1964
1966
|
Divide a number by a variable with units ``"s"`` and automatically determine that
|
|
1965
1967
|
the result is in ``"Hz"``.
|
|
1966
1968
|
|
|
1967
|
-
>>> import
|
|
1969
|
+
>>> import ansys.aedt.core.generic.constants
|
|
1968
1970
|
>>> from pyedb.dotnet.application.Variables import Variable
|
|
1969
1971
|
>>> v = Variable("1s")
|
|
1970
1972
|
>>> result = 3.0 / v
|
|
@@ -323,7 +323,10 @@ class Layout(ObjBase):
|
|
|
323
323
|
|
|
324
324
|
"""
|
|
325
325
|
obj = self._pedb._edb.Cell.Net.FindByName(self._edb_object, value)
|
|
326
|
-
|
|
326
|
+
if obj.IsNull():
|
|
327
|
+
raise ValueError(f"Net {value} doesn't exist")
|
|
328
|
+
else:
|
|
329
|
+
return EDBNetsData(obj, self._pedb)
|
|
327
330
|
|
|
328
331
|
def find_component_by_name(self, value: str):
|
|
329
332
|
"""Find a component object by name. Component name is the reference designator in layout.
|
|
@@ -47,10 +47,10 @@ class PinGroupTerminal(Terminal):
|
|
|
47
47
|
-------
|
|
48
48
|
:class:`pyedb.dotnet.edb_core.edb_data.terminals.PinGroupTerminal`
|
|
49
49
|
"""
|
|
50
|
-
net_obj = self._pedb.
|
|
50
|
+
net_obj = self._pedb.layout.find_net_by_name(net_name)
|
|
51
51
|
term = self._pedb.edb_api.cell.terminal.PinGroupTerminal.Create(
|
|
52
52
|
self._pedb.active_layout,
|
|
53
|
-
net_obj.
|
|
53
|
+
net_obj._edb_object,
|
|
54
54
|
name,
|
|
55
55
|
self._pedb.siwave.pin_groups[pin_group_name]._edb_object,
|
|
56
56
|
is_ref,
|
|
@@ -60,7 +60,7 @@ class PinGroupTerminal(Terminal):
|
|
|
60
60
|
msg = f"Failed to create terminal. "
|
|
61
61
|
if name in self._pedb.terminals:
|
|
62
62
|
msg += f"Terminal {name} already exists."
|
|
63
|
-
raise
|
|
63
|
+
raise ValueError(msg)
|
|
64
64
|
else:
|
|
65
65
|
return term
|
|
66
66
|
|
|
@@ -29,7 +29,12 @@ from pyedb.dotnet.clr_module import String
|
|
|
29
29
|
from pyedb.dotnet.edb_core.cell.primitive.primitive import Primitive
|
|
30
30
|
from pyedb.dotnet.edb_core.dotnet.database import PolygonDataDotNet
|
|
31
31
|
from pyedb.dotnet.edb_core.edb_data.edbvalue import EdbValue
|
|
32
|
-
from pyedb.dotnet.edb_core.general import
|
|
32
|
+
from pyedb.dotnet.edb_core.general import (
|
|
33
|
+
PadGeometryTpe,
|
|
34
|
+
convert_py_list_to_net_list,
|
|
35
|
+
pascal_to_snake,
|
|
36
|
+
snake_to_pascal,
|
|
37
|
+
)
|
|
33
38
|
from pyedb.generic.general_methods import generate_unique_name
|
|
34
39
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
35
40
|
|
|
@@ -406,19 +411,231 @@ class EDBPadstack(object):
|
|
|
406
411
|
>>> edb_padstack = edb.padstacks.definitions["MyPad"]
|
|
407
412
|
"""
|
|
408
413
|
|
|
414
|
+
PAD_SHAPE_PARAMETERS = {
|
|
415
|
+
"circle": ["diameter"],
|
|
416
|
+
"square": ["size"],
|
|
417
|
+
"rectangle": ["x_size", "y_size"],
|
|
418
|
+
"oval": ["x_size", "y_size", "corner_radius"],
|
|
419
|
+
"bullet": ["x_size", "y_size", "corner_radius"],
|
|
420
|
+
"round45": ["inner", "channel_width", "isolation_gap"],
|
|
421
|
+
"round90": ["inner", "channel_width", "isolation_gap"],
|
|
422
|
+
"no_geometry": [],
|
|
423
|
+
}
|
|
424
|
+
|
|
409
425
|
def __init__(self, edb_padstack, ppadstack):
|
|
426
|
+
self._edb_object = edb_padstack
|
|
410
427
|
self.edb_padstack = edb_padstack
|
|
411
428
|
self._ppadstack = ppadstack
|
|
412
|
-
self.pad_by_layer = {}
|
|
413
|
-
self.antipad_by_layer = {}
|
|
414
|
-
self.thermalpad_by_layer = {}
|
|
415
429
|
self._bounding_box = []
|
|
416
430
|
self._hole_params = None
|
|
431
|
+
|
|
432
|
+
@property
|
|
433
|
+
def pad_by_layer(self):
|
|
434
|
+
"""Regular pad property."""
|
|
435
|
+
temp = {}
|
|
417
436
|
for layer in self.via_layers:
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
437
|
+
temp[layer] = EDBPadProperties(self._edb_object, layer, 0, self)
|
|
438
|
+
return temp
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def antipad_by_layer(self):
|
|
442
|
+
"""Anti pad property."""
|
|
443
|
+
temp = {}
|
|
444
|
+
for layer in self.via_layers:
|
|
445
|
+
temp[layer] = EDBPadProperties(self._edb_object, layer, 1, self)
|
|
446
|
+
return temp
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def thermalpad_by_layer(self):
|
|
450
|
+
"""Thermal pad property."""
|
|
451
|
+
temp = {}
|
|
452
|
+
for layer in self.via_layers:
|
|
453
|
+
temp[layer] = EDBPadProperties(self._edb_object, layer, 2, self)
|
|
454
|
+
return temp
|
|
455
|
+
|
|
456
|
+
@property
|
|
457
|
+
def _padstack_def_data(self):
|
|
458
|
+
"""Get padstack definition data.
|
|
459
|
+
|
|
460
|
+
Returns
|
|
461
|
+
-------
|
|
462
|
+
|
|
463
|
+
"""
|
|
464
|
+
pstack_data = self._edb_object.GetData()
|
|
465
|
+
return self._edb.definition.PadstackDefData(pstack_data)
|
|
466
|
+
|
|
467
|
+
@_padstack_def_data.setter
|
|
468
|
+
def _padstack_def_data(self, value):
|
|
469
|
+
self._edb_object.SetData(value)
|
|
470
|
+
|
|
471
|
+
@property
|
|
472
|
+
def pad_parameters(self) -> dict:
|
|
473
|
+
"""Pad parameters.
|
|
474
|
+
|
|
475
|
+
Returns
|
|
476
|
+
-------
|
|
477
|
+
dict
|
|
478
|
+
params = {
|
|
479
|
+
'regular_pad': [
|
|
480
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0.1mm', 'offset_y': '0', 'rotation': '0',
|
|
481
|
+
'diameter': '0.5mm'}
|
|
482
|
+
],
|
|
483
|
+
'anti_pad': [
|
|
484
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
485
|
+
'diameter': '1mm'}
|
|
486
|
+
],
|
|
487
|
+
'thermal_pad': [
|
|
488
|
+
{'layer_name': '1_Top', 'shape': 'round90', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
489
|
+
'inner': '1mm', 'channel_width': '0.2mm', 'isolation_gap': '0.3mm'},
|
|
490
|
+
],
|
|
491
|
+
'hole': [
|
|
492
|
+
{'layer_name': '1_Top', 'shape': 'circle', 'offset_x': '0', 'offset_y': '0', 'rotation': '0',
|
|
493
|
+
'diameter': '0.1499997mm'},
|
|
494
|
+
]
|
|
495
|
+
}
|
|
496
|
+
"""
|
|
497
|
+
pdef_data = self._padstack_def_data
|
|
498
|
+
pad_type_list = [
|
|
499
|
+
self._ppadstack._pedb._edb.Definition.PadType.RegularPad,
|
|
500
|
+
self._ppadstack._pedb._edb.Definition.PadType.AntiPad,
|
|
501
|
+
self._ppadstack._pedb._edb.Definition.PadType.ThermalPad,
|
|
502
|
+
self._ppadstack._pedb._edb.Definition.PadType.Hole,
|
|
503
|
+
]
|
|
504
|
+
data = {}
|
|
505
|
+
for pad_type in pad_type_list:
|
|
506
|
+
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
507
|
+
temp_list = []
|
|
508
|
+
for lyr_name in list(pdef_data.GetLayerNames()):
|
|
509
|
+
result = pdef_data.GetPadParametersValue(lyr_name, pad_type)
|
|
510
|
+
_, pad_shape, params, offset_x, offset_y, rotation = result
|
|
511
|
+
pad_shape = pascal_to_snake(pad_shape.ToString())
|
|
512
|
+
|
|
513
|
+
pad_params = {}
|
|
514
|
+
pad_params["layer_name"] = lyr_name
|
|
515
|
+
pad_params["shape"] = pad_shape
|
|
516
|
+
pad_params["offset_x"] = offset_x.ToString()
|
|
517
|
+
pad_params["offset_y"] = offset_y.ToString()
|
|
518
|
+
pad_params["rotation"] = rotation.ToString()
|
|
519
|
+
|
|
520
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[pad_shape]):
|
|
521
|
+
pad_params[i] = params[idx].ToString()
|
|
522
|
+
temp_list.append(pad_params)
|
|
523
|
+
data[pad_type_name] = temp_list
|
|
524
|
+
return data
|
|
525
|
+
|
|
526
|
+
@pad_parameters.setter
|
|
527
|
+
def pad_parameters(self, params: dict):
|
|
528
|
+
original_params = self.pad_parameters
|
|
529
|
+
pdef_data = self._padstack_def_data
|
|
530
|
+
|
|
531
|
+
pad_type_list = [
|
|
532
|
+
self._ppadstack._pedb._edb.Definition.PadType.RegularPad,
|
|
533
|
+
self._ppadstack._pedb._edb.Definition.PadType.AntiPad,
|
|
534
|
+
self._ppadstack._pedb._edb.Definition.PadType.ThermalPad,
|
|
535
|
+
self._ppadstack._pedb._edb.Definition.PadType.Hole,
|
|
536
|
+
]
|
|
537
|
+
for pad_type in pad_type_list:
|
|
538
|
+
pad_type_name = pascal_to_snake(pad_type.ToString())
|
|
539
|
+
rpp = params.get(pad_type_name, [])
|
|
540
|
+
for idx, layer_data in enumerate(rpp):
|
|
541
|
+
# Get geometry type from kwargs
|
|
542
|
+
p = layer_data.get("shape")
|
|
543
|
+
temp_param = []
|
|
544
|
+
|
|
545
|
+
# Handle Circle geometry type
|
|
546
|
+
if p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Circle.ToString()):
|
|
547
|
+
temp_param.append(layer_data["diameter"])
|
|
548
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Circle
|
|
549
|
+
|
|
550
|
+
# Handle Square geometry type
|
|
551
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Square.ToString()):
|
|
552
|
+
temp_param.append(layer_data["size"])
|
|
553
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Square
|
|
554
|
+
|
|
555
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Rectangle.ToString()):
|
|
556
|
+
temp_param.append(layer_data["x_size"])
|
|
557
|
+
temp_param.append(layer_data["y_size"])
|
|
558
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Rectangle
|
|
559
|
+
|
|
560
|
+
# Handle Oval geometry type
|
|
561
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Oval.ToString()):
|
|
562
|
+
temp_param.append(layer_data["x_size"])
|
|
563
|
+
temp_param.append(layer_data["y_size"])
|
|
564
|
+
temp_param.append(layer_data["corner_radius"])
|
|
565
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Oval
|
|
566
|
+
|
|
567
|
+
# Handle Bullet geometry type
|
|
568
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Bullet.ToString()):
|
|
569
|
+
temp_param.append(layer_data["x_size"])
|
|
570
|
+
temp_param.append(layer_data["y_size"])
|
|
571
|
+
temp_param.append(layer_data["corner_radius"])
|
|
572
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Bullet
|
|
573
|
+
|
|
574
|
+
# Handle Round45 geometry type
|
|
575
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Round45.ToString()):
|
|
576
|
+
temp_param.append(layer_data["inner"])
|
|
577
|
+
temp_param.append(layer_data["channel_width"])
|
|
578
|
+
temp_param.append(layer_data["isolation_gap"])
|
|
579
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Round45
|
|
580
|
+
|
|
581
|
+
# Handle Round90 geometry type
|
|
582
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.Round90.ToString()):
|
|
583
|
+
temp_param.append(layer_data["inner"])
|
|
584
|
+
temp_param.append(layer_data["channel_width"])
|
|
585
|
+
temp_param.append(layer_data["isolation_gap"])
|
|
586
|
+
pad_shape = self._ppadstack._pedb._edb.Definition.PadGeometryType.Round90
|
|
587
|
+
elif p == pascal_to_snake(self._ppadstack._pedb._edb.Definition.PadGeometryType.NoGeometry.ToString()):
|
|
588
|
+
continue
|
|
589
|
+
|
|
590
|
+
# Set pad parameters for the current layer
|
|
591
|
+
default = original_params[pad_type_name]
|
|
592
|
+
pdef_data.SetPadParameters(
|
|
593
|
+
layer_data["layer_name"],
|
|
594
|
+
pad_type,
|
|
595
|
+
pad_shape,
|
|
596
|
+
convert_py_list_to_net_list([self._ppadstack._pedb.edb_value(i) for i in temp_param]),
|
|
597
|
+
self._ppadstack._pedb.edb_value(layer_data.get("offset_x", default[idx].get("offset_x", 0))),
|
|
598
|
+
self._ppadstack._pedb.edb_value(layer_data.get("offset_y", default[idx].get("offset_y", 0))),
|
|
599
|
+
self._ppadstack._pedb.edb_value(layer_data.get("rotation", default[idx].get("rotation", 0))),
|
|
600
|
+
)
|
|
601
|
+
self._padstack_def_data = pdef_data
|
|
602
|
+
|
|
603
|
+
@property
|
|
604
|
+
def hole_parameters(self):
|
|
605
|
+
pdef_data = self._padstack_def_data
|
|
606
|
+
_, hole_shape, params, offset_x, offset_y, rotation = pdef_data.GetHoleParametersValue()
|
|
607
|
+
hole_shape = pascal_to_snake(hole_shape.ToString())
|
|
608
|
+
|
|
609
|
+
hole_params = {}
|
|
610
|
+
hole_params["shape"] = hole_shape
|
|
611
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[hole_shape]):
|
|
612
|
+
hole_params[i] = params[idx].ToString()
|
|
613
|
+
hole_params["offset_x"] = offset_x.ToString()
|
|
614
|
+
hole_params["offset_y"] = offset_y.ToString()
|
|
615
|
+
hole_params["rotation"] = rotation.ToString()
|
|
616
|
+
return hole_params
|
|
617
|
+
|
|
618
|
+
@hole_parameters.setter
|
|
619
|
+
def hole_parameters(self, params: dict):
|
|
620
|
+
original_params = self.hole_parameters
|
|
621
|
+
pdef_data = self._padstack_def_data
|
|
622
|
+
|
|
623
|
+
temp_param = []
|
|
624
|
+
shape = params["shape"]
|
|
625
|
+
if shape == "no_geometry":
|
|
626
|
+
return # .net api doesn't tell how to set no_geometry shape.
|
|
627
|
+
for idx, i in enumerate(self.PAD_SHAPE_PARAMETERS[shape]):
|
|
628
|
+
temp_param.append(params[i])
|
|
629
|
+
pedb_shape = getattr(self._ppadstack._pedb._edb.Definition.PadGeometryType, snake_to_pascal(shape))
|
|
630
|
+
|
|
631
|
+
pdef_data.SetHoleParameters(
|
|
632
|
+
pedb_shape,
|
|
633
|
+
convert_py_list_to_net_list([self._ppadstack._pedb.edb_value(i) for i in temp_param]),
|
|
634
|
+
self._ppadstack._pedb.edb_value(params.get("offset_x", original_params.get("offset_x", 0))),
|
|
635
|
+
self._ppadstack._pedb.edb_value(params.get("offset_y", original_params.get("offset_y", 0))),
|
|
636
|
+
self._ppadstack._pedb.edb_value(params.get("rotation", original_params.get("rotation", 0))),
|
|
637
|
+
)
|
|
638
|
+
self._padstack_def_data = pdef_data
|
|
422
639
|
|
|
423
640
|
@property
|
|
424
641
|
def instances(self):
|
|
@@ -455,7 +672,7 @@ class EDBPadstack(object):
|
|
|
455
672
|
list
|
|
456
673
|
List of layers.
|
|
457
674
|
"""
|
|
458
|
-
return self.
|
|
675
|
+
return self._padstack_def_data.GetLayerNames()
|
|
459
676
|
|
|
460
677
|
@property
|
|
461
678
|
def via_start_layer(self):
|
|
@@ -488,7 +705,7 @@ class EDBPadstack(object):
|
|
|
488
705
|
return self._hole_params
|
|
489
706
|
|
|
490
707
|
@property
|
|
491
|
-
def
|
|
708
|
+
def _hole_parameters(self):
|
|
492
709
|
"""Hole parameters.
|
|
493
710
|
|
|
494
711
|
Returns
|
|
@@ -496,8 +713,7 @@ class EDBPadstack(object):
|
|
|
496
713
|
list
|
|
497
714
|
List of the hole parameters.
|
|
498
715
|
"""
|
|
499
|
-
|
|
500
|
-
return self._hole_parameters
|
|
716
|
+
return self.hole_params[2]
|
|
501
717
|
|
|
502
718
|
@property
|
|
503
719
|
def hole_diameter(self):
|
|
@@ -540,7 +756,7 @@ class EDBPadstack(object):
|
|
|
540
756
|
if not hole_type:
|
|
541
757
|
hole_type = self.hole_type
|
|
542
758
|
if not params:
|
|
543
|
-
params = self.
|
|
759
|
+
params = self._hole_parameters
|
|
544
760
|
if isinstance(params, list):
|
|
545
761
|
params = convert_py_list_to_net_list(params)
|
|
546
762
|
if not offsetx:
|
|
@@ -709,14 +925,13 @@ class EDBPadstack(object):
|
|
|
709
925
|
str
|
|
710
926
|
Material of the hole.
|
|
711
927
|
"""
|
|
712
|
-
return self.
|
|
928
|
+
return self._padstack_def_data.GetMaterial()
|
|
713
929
|
|
|
714
930
|
@material.setter
|
|
715
931
|
def material(self, materialname):
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
self.edb_padstack.SetData(newPadstackDefinitionData)
|
|
932
|
+
pdef_data = self._padstack_def_data
|
|
933
|
+
pdef_data.SetMaterial(materialname)
|
|
934
|
+
self._padstack_def_data = pdef_data
|
|
720
935
|
|
|
721
936
|
@property
|
|
722
937
|
def padstack_instances(self):
|
|
@@ -736,36 +951,15 @@ class EDBPadstack(object):
|
|
|
736
951
|
-------
|
|
737
952
|
str
|
|
738
953
|
Possible returned values are ``"through"``, ``"begin_on_upper_pad"``,
|
|
739
|
-
``"end_on_lower_pad"``, ``"upper_pad_to_lower_pad"``, and ``"
|
|
954
|
+
``"end_on_lower_pad"``, ``"upper_pad_to_lower_pad"``, and ``"unknown_range"``.
|
|
740
955
|
"""
|
|
741
|
-
|
|
742
|
-
hole_ange_type = int(cloned_padstackdef_data.GetHoleRange())
|
|
743
|
-
if hole_ange_type == 0: # pragma no cover
|
|
744
|
-
return "through"
|
|
745
|
-
elif hole_ange_type == 1: # pragma no cover
|
|
746
|
-
return "begin_on_upper_pad"
|
|
747
|
-
elif hole_ange_type == 2: # pragma no cover
|
|
748
|
-
return "end_on_lower_pad"
|
|
749
|
-
elif hole_ange_type == 3: # pragma no cover
|
|
750
|
-
return "upper_pad_to_lower_pad"
|
|
751
|
-
else: # pragma no cover
|
|
752
|
-
return "undefined"
|
|
956
|
+
return pascal_to_snake(self._padstack_def_data.GetHoleRange().ToString())
|
|
753
957
|
|
|
754
958
|
@hole_range.setter
|
|
755
959
|
def hole_range(self, value):
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.Through)
|
|
760
|
-
elif value == "begin_on_upper_pad": # pragma no cover
|
|
761
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.BeginOnUpperPad)
|
|
762
|
-
elif value == "end_on_lower_pad": # pragma no cover
|
|
763
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.EndOnLowerPad)
|
|
764
|
-
elif value == "upper_pad_to_lower_pad": # pragma no cover
|
|
765
|
-
cloned_padstackdef_data.SetHoleRange(self._edb.definition.PadstackHoleRange.UpperPadToLowerPad)
|
|
766
|
-
else: # pragma no cover
|
|
767
|
-
return
|
|
768
|
-
self.edb_padstack.SetData(cloned_padstackdef_data)
|
|
960
|
+
pdef_data = self._padstack_def_data
|
|
961
|
+
pdef_data.SetHoleRange(getattr(self._edb.definition.PadstackHoleRange, snake_to_pascal(value)))
|
|
962
|
+
self._padstack_def_data = pdef_data
|
|
769
963
|
|
|
770
964
|
def convert_to_3d_microvias(self, convert_only_signal_vias=True, hole_wall_angle=15, delete_padstack_def=True):
|
|
771
965
|
"""Convert actual padstack instance to microvias 3D Objects with a given aspect ratio.
|
|
@@ -984,7 +1178,7 @@ class EDBPadstack(object):
|
|
|
984
1178
|
)
|
|
985
1179
|
new_padstack_definition_data.SetHoleParameters(
|
|
986
1180
|
self.hole_type,
|
|
987
|
-
self.
|
|
1181
|
+
self._hole_parameters,
|
|
988
1182
|
self._get_edb_value(self.hole_offset_x),
|
|
989
1183
|
self._get_edb_value(self.hole_offset_y),
|
|
990
1184
|
self._get_edb_value(self.hole_rotation),
|
|
@@ -1128,6 +1322,18 @@ class EDBPadstack(object):
|
|
|
1128
1322
|
self.edb_padstack.SetData(new_padstack_data)
|
|
1129
1323
|
return True
|
|
1130
1324
|
|
|
1325
|
+
def set_properties(self, **kwargs):
|
|
1326
|
+
for k in ["hole_plating_thickness", "material", "hole_range", "pad_parameters", "hole_parameters"]:
|
|
1327
|
+
value = kwargs.get(k, False)
|
|
1328
|
+
if value:
|
|
1329
|
+
setattr(self, k, value)
|
|
1330
|
+
|
|
1331
|
+
def get_properties(self):
|
|
1332
|
+
kwargs = {}
|
|
1333
|
+
for k in ["hole_plating_thickness", "material", "hole_range", "pad_parameters", "hole_parameters"]:
|
|
1334
|
+
kwargs[k] = getattr(self, k)
|
|
1335
|
+
return kwargs
|
|
1336
|
+
|
|
1131
1337
|
|
|
1132
1338
|
class EDBPadstackInstance(Primitive):
|
|
1133
1339
|
"""Manages EDB functionalities for a padstack.
|
|
@@ -158,7 +158,7 @@ class EdbPolygon(Primitive):
|
|
|
158
158
|
|
|
159
159
|
Examples
|
|
160
160
|
--------
|
|
161
|
-
>>> edbapp =
|
|
161
|
+
>>> edbapp = ansys.aedt.core.Edb("myproject.aedb")
|
|
162
162
|
>>> top_layer_polygon = [poly for poly in edbapp.modeler.polygons if poly.layer_name == "Top Layer"]
|
|
163
163
|
>>> for polygon in top_layer_polygon:
|
|
164
164
|
>>> polygon.move(vector=["2mm", "100um"])
|
|
@@ -191,7 +191,7 @@ class EdbPolygon(Primitive):
|
|
|
191
191
|
|
|
192
192
|
Examples
|
|
193
193
|
--------
|
|
194
|
-
>>> edbapp =
|
|
194
|
+
>>> edbapp = ansys.aedt.core.Edb("myproject.aedb")
|
|
195
195
|
>>> top_layer_polygon = [poly for poly in edbapp.modeler.polygons if poly.layer_name == "Top Layer"]
|
|
196
196
|
>>> for polygon in top_layer_polygon:
|
|
197
197
|
>>> polygon.rotate(angle=45)
|
pyedb/dotnet/edb_core/general.py
CHANGED
|
@@ -28,6 +28,7 @@ This module contains EDB general methods and related methods.
|
|
|
28
28
|
from __future__ import absolute_import # noreorder
|
|
29
29
|
|
|
30
30
|
import logging
|
|
31
|
+
import re
|
|
31
32
|
|
|
32
33
|
from pyedb.dotnet.clr_module import Dictionary, List, Tuple
|
|
33
34
|
|
|
@@ -140,6 +141,16 @@ def convert_net_list_to_py_list(netlist):
|
|
|
140
141
|
return pylist
|
|
141
142
|
|
|
142
143
|
|
|
144
|
+
def pascal_to_snake(s):
|
|
145
|
+
# Convert PascalCase to snake_case
|
|
146
|
+
return re.sub(r"(?<!^)(?=[A-Z])", "_", s).lower()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def snake_to_pascal(s):
|
|
150
|
+
# Split the string at underscores and capitalize the first letter of each part
|
|
151
|
+
return "".join(word.capitalize() for word in s.split("_"))
|
|
152
|
+
|
|
153
|
+
|
|
143
154
|
class PadGeometryTpe(Enum): # pragma: no cover
|
|
144
155
|
Circle = 1
|
|
145
156
|
Square = 2
|
pyedb/dotnet/edb_core/modeler.py
CHANGED
|
@@ -1460,6 +1460,9 @@ class Modeler(object):
|
|
|
1460
1460
|
self._pedb.active_layout, name, convert_py_list_to_net_list(pins)
|
|
1461
1461
|
)
|
|
1462
1462
|
if obj.IsNull():
|
|
1463
|
-
|
|
1464
|
-
|
|
1463
|
+
raise RuntimeError(f"Failed to create pin group {name}.")
|
|
1464
|
+
else:
|
|
1465
|
+
net_obj = [i.GetNet() for i in pins if not i.GetNet().IsNull()]
|
|
1466
|
+
if net_obj:
|
|
1467
|
+
obj.SetNet(net_obj[0])
|
|
1465
1468
|
return self._pedb.siwave.pin_groups[name]
|
pyedb/edb_logger.py
CHANGED
|
@@ -417,7 +417,7 @@ class EdbLogger(object):
|
|
|
417
417
|
|
|
418
418
|
logger = logging.getLogger("Global")
|
|
419
419
|
if any("aedt_logger" in str(i) for i in logger.filters):
|
|
420
|
-
from
|
|
420
|
+
from ansys.aedt.core.generic.settings import settings as pyaedt_settings
|
|
421
421
|
|
|
422
422
|
from pyedb.generic.settings import settings as pyaedb_settings
|
|
423
423
|
|
pyedb/siwave.py
CHANGED
|
@@ -15,6 +15,7 @@ import shutil
|
|
|
15
15
|
import sys
|
|
16
16
|
import tempfile
|
|
17
17
|
import time
|
|
18
|
+
from typing import Optional, Union
|
|
18
19
|
import warnings
|
|
19
20
|
|
|
20
21
|
from pyedb import Edb
|
|
@@ -53,6 +54,15 @@ def wait_export_folder(flag, folder_path, time_sleep=0.5):
|
|
|
53
54
|
time.sleep(time_sleep)
|
|
54
55
|
|
|
55
56
|
|
|
57
|
+
def parser_file_path(file_path):
|
|
58
|
+
if isinstance(file_path, Path):
|
|
59
|
+
file_path = str(file_path)
|
|
60
|
+
|
|
61
|
+
if not Path(file_path).root:
|
|
62
|
+
file_path = str(Path().cwd() / file_path)
|
|
63
|
+
return file_path
|
|
64
|
+
|
|
65
|
+
|
|
56
66
|
class Siwave(object): # pragma no cover
|
|
57
67
|
"""Initializes SIwave based on the inputs provided and manages SIwave release and closing.
|
|
58
68
|
|
|
@@ -264,9 +274,9 @@ class Siwave(object): # pragma no cover
|
|
|
264
274
|
``True`` when successful, ``False`` when failed.
|
|
265
275
|
|
|
266
276
|
"""
|
|
267
|
-
|
|
268
|
-
if os.path.exists(
|
|
269
|
-
open_result = self.oSiwave.OpenProject(
|
|
277
|
+
file_path = parser_file_path(proj_path)
|
|
278
|
+
if os.path.exists(file_path):
|
|
279
|
+
open_result = self.oSiwave.OpenProject(file_path)
|
|
270
280
|
self._oproject = self.oSiwave.GetActiveProject()
|
|
271
281
|
return open_result
|
|
272
282
|
else:
|
|
@@ -306,6 +316,22 @@ class Siwave(object): # pragma no cover
|
|
|
306
316
|
self.oproject.Save()
|
|
307
317
|
return True
|
|
308
318
|
|
|
319
|
+
def save(self, file_path: Optional[Union[str, Path]]):
|
|
320
|
+
"""Save the project.
|
|
321
|
+
|
|
322
|
+
Parameters
|
|
323
|
+
----------
|
|
324
|
+
file_path : str, optional
|
|
325
|
+
Full path to the project. The default is ``None``.
|
|
326
|
+
"""
|
|
327
|
+
|
|
328
|
+
if file_path:
|
|
329
|
+
file_path = parser_file_path(file_path)
|
|
330
|
+
file_path = str(Path(file_path).with_suffix(".siw"))
|
|
331
|
+
self.oproject.ScrSaveProjectAs(file_path)
|
|
332
|
+
else:
|
|
333
|
+
self.oproject.Save()
|
|
334
|
+
|
|
309
335
|
def close_project(self, save_project=False):
|
|
310
336
|
"""Close the project.
|
|
311
337
|
|
|
@@ -494,6 +520,8 @@ class Siwave(object): # pragma no cover
|
|
|
494
520
|
"""
|
|
495
521
|
if isinstance(file_path, Path):
|
|
496
522
|
file_path = str(file_path)
|
|
523
|
+
if not Path(file_path).root:
|
|
524
|
+
file_path = str(Path().cwd() / file_path)
|
|
497
525
|
flag = self.oproject.ScrImportEDB(file_path)
|
|
498
526
|
# self.save_project(self.di)
|
|
499
527
|
if flag == 0:
|
|
@@ -510,8 +538,7 @@ class Siwave(object): # pragma no cover
|
|
|
510
538
|
file_path : str
|
|
511
539
|
Path to the configuration file.
|
|
512
540
|
"""
|
|
513
|
-
|
|
514
|
-
file_path = str(file_path)
|
|
541
|
+
file_path = parser_file_path(file_path)
|
|
515
542
|
|
|
516
543
|
# temp_folder = tempfile.TemporaryDirectory(suffix=".ansys")
|
|
517
544
|
# temp_edb = os.path.join(temp_folder.name, "temp.aedb")
|
|
@@ -536,8 +563,7 @@ class Siwave(object): # pragma no cover
|
|
|
536
563
|
file_path : str
|
|
537
564
|
Path to the configuration file.
|
|
538
565
|
"""
|
|
539
|
-
|
|
540
|
-
file_path = str(file_path)
|
|
566
|
+
file_path = parser_file_path(file_path)
|
|
541
567
|
|
|
542
568
|
temp_folder = tempfile.TemporaryDirectory(suffix=".ansys")
|
|
543
569
|
temp_edb = os.path.join(temp_folder.name, "temp.aedb")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyedb
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.28.0
|
|
4
4
|
Summary: Higher-Level Pythonic Ansys Electronics Data Base
|
|
5
5
|
Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
|
|
6
6
|
Maintainer-email: PyEDB developers <simon.vandenbrouck@ansys.com>
|
|
@@ -19,9 +19,9 @@ Requires-Dist: cffi>=1.16.0,<1.18; platform_system=='Linux'
|
|
|
19
19
|
Requires-Dist: pywin32 >= 303;platform_system=='Windows'
|
|
20
20
|
Requires-Dist: ansys-pythonnet >= 3.1.0rc3
|
|
21
21
|
Requires-Dist: dotnetcore2 ==3.1.23;platform_system=='Linux'
|
|
22
|
-
Requires-Dist: numpy>=1.20.0,<2
|
|
22
|
+
Requires-Dist: numpy>=1.20.0,<2
|
|
23
23
|
Requires-Dist: pandas>=1.1.0,<2.3
|
|
24
|
-
Requires-Dist: pydantic>=2.6.4,<2.
|
|
24
|
+
Requires-Dist: pydantic>=2.6.4,<2.10
|
|
25
25
|
Requires-Dist: Rtree >= 1.2.0
|
|
26
26
|
Requires-Dist: toml == 0.10.2
|
|
27
27
|
Requires-Dist: scikit-rf
|
|
@@ -37,7 +37,7 @@ Requires-Dist: numpydoc>=1.5.0,<1.9 ; extra == "doc"
|
|
|
37
37
|
Requires-Dist: pypandoc>=1.10.0,<1.14 ; extra == "doc"
|
|
38
38
|
Requires-Dist: recommonmark ; extra == "doc"
|
|
39
39
|
Requires-Dist: Sphinx>=7.1.0,<8.1 ; extra == "doc"
|
|
40
|
-
Requires-Dist: sphinx-autobuild==
|
|
40
|
+
Requires-Dist: sphinx-autobuild==2021.3.14 ; extra == "doc" and ( python_version == '3.8')
|
|
41
41
|
Requires-Dist: sphinx-autobuild==2024.2.4 ; extra == "doc" and ( python_version > '3.8')
|
|
42
42
|
Requires-Dist: sphinx-copybutton>=0.5.0,<0.6 ; extra == "doc"
|
|
43
43
|
Requires-Dist: sphinx-gallery>=0.14.0,<0.18 ; extra == "doc"
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
pyedb/__init__.py,sha256=
|
|
2
|
-
pyedb/edb_logger.py,sha256=
|
|
1
|
+
pyedb/__init__.py,sha256=i2Y8_oZHdAU8T5kqsiHeENkfm9LyD8AcJUy50FaBecM,1521
|
|
2
|
+
pyedb/edb_logger.py,sha256=7KXPvAMCKzlzJ5zioiNO5A3zkqbpCHhWHB4aXKfgu5Y,14959
|
|
3
3
|
pyedb/exceptions.py,sha256=n94xluzUks6BA24vd_L6HkrvoP_H_l6__hQmqzdCyPo,111
|
|
4
|
-
pyedb/siwave.py,sha256=
|
|
4
|
+
pyedb/siwave.py,sha256=6SL3PnklGMbVOsstvJJ1fx3D3YkBWr27pYDUG-U4VB8,17520
|
|
5
5
|
pyedb/workflow.py,sha256=Y0ya4FUHwlSmoLP45zjdYLsSpyKduHUSpT9GGK9MGd8,814
|
|
6
6
|
pyedb/component_libraries/ansys_components.py,sha256=O3ypt832IHY9zG2AD_yrRrbH2KH9P1yFaoi1EO6Zllw,4830
|
|
7
7
|
pyedb/configuration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
pyedb/configuration/cfg_boundaries.py,sha256=ckb-OfaObItwy-xc0LqkHJyeCfKC5vg668olPjZbaKo,6647
|
|
9
9
|
pyedb/configuration/cfg_common.py,sha256=5ne78TTA0wHpbi804nsUd9SPxNKZvut_X_Miu-xDRgk,1982
|
|
10
10
|
pyedb/configuration/cfg_components.py,sha256=XGWvttmVpz7zHh9fpKFjsMiMy6KTP_GGsR3UGv8xuoI,7683
|
|
11
|
-
pyedb/configuration/cfg_data.py,sha256=
|
|
11
|
+
pyedb/configuration/cfg_data.py,sha256=MQJJ-ztmxI1Gzii2xoepKSb7IWImnyeFBMCpWeAHGvs,3637
|
|
12
12
|
pyedb/configuration/cfg_general.py,sha256=0dtd-rkQt2aYR3EOL0c3sNuDuJs7htRos1OWck3rxaI,1626
|
|
13
13
|
pyedb/configuration/cfg_nets.py,sha256=18NezeNh0ZOwk2ehz3zWJF_xYR7IYCqGlpDfDt7Ilho,2349
|
|
14
|
-
pyedb/configuration/cfg_operations.py,sha256
|
|
14
|
+
pyedb/configuration/cfg_operations.py,sha256=iT7GW2XggtDjfS4vI4-2gS47Nai7mxfpKjG7V_8IM_0,4541
|
|
15
15
|
pyedb/configuration/cfg_package_definition.py,sha256=f_RRT9R-3H5kHBlc4QSpjq9uQgYbaKQ78XXXrc_r3kg,5296
|
|
16
|
-
pyedb/configuration/cfg_padstacks.py,sha256=
|
|
17
|
-
pyedb/configuration/cfg_pin_groups.py,sha256=
|
|
16
|
+
pyedb/configuration/cfg_padstacks.py,sha256=yRHWZJ1E6vcVxK-l1No_p33sEdPIOyqZvN5stNMqSLQ,5605
|
|
17
|
+
pyedb/configuration/cfg_pin_groups.py,sha256=b0H6NaPKJ5zlcXL9W2Q8_HbiLB8-OxaqjsM4wlqP2ic,3768
|
|
18
18
|
pyedb/configuration/cfg_ports_sources.py,sha256=G2mX057QB3H3JUxAL0wDMDaHgabKFnht3iIyhTJvJU4,16356
|
|
19
19
|
pyedb/configuration/cfg_s_parameter_models.py,sha256=NzS3eBjBSnd7ZDk_TsX04dqRcRXompjx1DxCe1UzWMw,2855
|
|
20
20
|
pyedb/configuration/cfg_setup.py,sha256=SPpNRLJusB-Cz2fDQkc6gkdilUqIlbNngoxF3zySt6g,10115
|
|
21
21
|
pyedb/configuration/cfg_spice_models.py,sha256=Q_5j2-V6cepSFcnijot8iypTqzanLp7HOz-agmnwKns,2570
|
|
22
22
|
pyedb/configuration/cfg_stackup.py,sha256=CX7uNN5QRoYW_MOObknP8003YchTS7PH9Oee7FG0VKU,6589
|
|
23
|
-
pyedb/configuration/configuration.py,sha256=
|
|
23
|
+
pyedb/configuration/configuration.py,sha256=I-ivhVqnqEmDShTSACNqfZ0l49yJdNfyxNwHY-cMtkg,13502
|
|
24
24
|
pyedb/dotnet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
pyedb/dotnet/clr_module.py,sha256=Mo13Of3DVSA5HR-5xZEXOiHApIKy52CUxtJ2gPkEu1A,3406
|
|
26
26
|
pyedb/dotnet/edb.py,sha256=B7HYfgZkc-ezrdMIm3wInWAd5zw6ZMM5KdBG3H6y7L0,181695
|
|
27
|
-
pyedb/dotnet/application/Variables.py,sha256=
|
|
27
|
+
pyedb/dotnet/application/Variables.py,sha256=awNhyiLASBYrNjWIyW8IJowgqt7FfFPKF9UElRWyjZg,77750
|
|
28
28
|
pyedb/dotnet/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
29
|
pyedb/dotnet/edb_core/__init__.py,sha256=nIRLJ8VZLcMAp12zmGsnZ5x2BEEl7q_Kj_KAOXxVjpQ,52
|
|
30
30
|
pyedb/dotnet/edb_core/components.py,sha256=g2hPrTotCtHWA7y79ej1fw3UoY5KrgDwur3H3m-Vmfg,111194
|
|
31
|
-
pyedb/dotnet/edb_core/general.py,sha256=
|
|
31
|
+
pyedb/dotnet/edb_core/general.py,sha256=k2Bcr5VV-QUzEZlYorqYCX1ZchHBH7WqUvc8maMxId0,4716
|
|
32
32
|
pyedb/dotnet/edb_core/hfss.py,sha256=C6-to6YKoruQjRWedLY7agkTVQv4Hb2U2qX-iPzHOI0,68655
|
|
33
33
|
pyedb/dotnet/edb_core/layout_obj_instance.py,sha256=Pd8rfdO3b6HLFGwXBMw-tfE4LPIcW_9_X5KEdFaiito,1407
|
|
34
34
|
pyedb/dotnet/edb_core/layout_validation.py,sha256=HxRPHEs9yMyz0XgIegWsb4nSV7hNYbO-xBJ-eFyNnQw,12609
|
|
35
35
|
pyedb/dotnet/edb_core/materials.py,sha256=zzYWIJ5dvOIO2H2vREpRnwGDx0hEa5QhCsg_EJkydww,43222
|
|
36
|
-
pyedb/dotnet/edb_core/modeler.py,sha256=
|
|
36
|
+
pyedb/dotnet/edb_core/modeler.py,sha256=87amEA3xHszL52ae8i-7fAJzWL4Ntqp72omocNO5XAw,55442
|
|
37
37
|
pyedb/dotnet/edb_core/net_class.py,sha256=4U6Cc1Gn7ZJ_ub9uKmtrsoz5wD1XS42afci3Y3ewRp0,11354
|
|
38
38
|
pyedb/dotnet/edb_core/nets.py,sha256=WMKC9aKkmGP_NFqAkQpM8b4AjgDgjhrRXOz8VrN4yj8,41429
|
|
39
39
|
pyedb/dotnet/edb_core/padstack.py,sha256=P4WqnMy_mRHHPNvLCG96eGGB8_8bSZPBVziStxGNd5I,63567
|
|
@@ -41,7 +41,7 @@ pyedb/dotnet/edb_core/siwave.py,sha256=4duoAsFCuPMNLxtMTEEVJCUaHKNkdbLDmtTXiD93V
|
|
|
41
41
|
pyedb/dotnet/edb_core/stackup.py,sha256=b56leXg7X7dEVPP2DUD9n8LZIakWcjIsjiqqkIWsyZU,120035
|
|
42
42
|
pyedb/dotnet/edb_core/cell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
pyedb/dotnet/edb_core/cell/connectable.py,sha256=gc5jhWx4DX718T7koL6oZZzfS4EdQNTiFX76ZJ2c83E,2864
|
|
44
|
-
pyedb/dotnet/edb_core/cell/layout.py,sha256=
|
|
44
|
+
pyedb/dotnet/edb_core/cell/layout.py,sha256=1BZ5j5sD7cuomG3-mV7Z7UBtfko39m6xm6Fjgwvn0zo,12696
|
|
45
45
|
pyedb/dotnet/edb_core/cell/layout_obj.py,sha256=S42rdiI6gVqO77DV3ikc4YxTNufTuqW_X1G-2zkWArA,2765
|
|
46
46
|
pyedb/dotnet/edb_core/cell/voltage_regulator.py,sha256=-uAzuyERV6ca0bFRzdH4SllcpGY2D9JEdpS7RYaQt6c,5387
|
|
47
47
|
pyedb/dotnet/edb_core/cell/hierarchy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -60,7 +60,7 @@ pyedb/dotnet/edb_core/cell/terminal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
|
|
|
60
60
|
pyedb/dotnet/edb_core/cell/terminal/bundle_terminal.py,sha256=qM0wEXkZ-DpoJ6vlVa560Ce8IgOdp4vyIJPedvoa3O0,1977
|
|
61
61
|
pyedb/dotnet/edb_core/cell/terminal/edge_terminal.py,sha256=lafPRrvsDPYKcysvrkO-5tEZXF3h4IcTXdeJgTjleuI,2158
|
|
62
62
|
pyedb/dotnet/edb_core/cell/terminal/padstack_instance_terminal.py,sha256=XI7NiP1qT2aft7hjPK4gX42RzreiZ66aHXIHFPwUghs,3999
|
|
63
|
-
pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py,sha256=
|
|
63
|
+
pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py,sha256=Xupr55vseJsAR6y62Ekv1Kie_ILc6RVNzT3Sgxdi7X4,2753
|
|
64
64
|
pyedb/dotnet/edb_core/cell/terminal/point_terminal.py,sha256=S3aCAuFc_QA36PVn2Cdb9L4dO3T4IikwyEVcP1FOW3I,2597
|
|
65
65
|
pyedb/dotnet/edb_core/cell/terminal/terminal.py,sha256=WoNS05-wSktF93MvDUjNQw9MMC3e18UGcsBKsy2fo68,19130
|
|
66
66
|
pyedb/dotnet/edb_core/definition/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -79,9 +79,9 @@ pyedb/dotnet/edb_core/edb_data/edbvalue.py,sha256=Vj_11HXsQUNavizKp5FicORm6cjhXR
|
|
|
79
79
|
pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py,sha256=hKFHWUl0_OCMEZJbQn5c8Y1a-BYKr8nAycIlrCoeufk,13005
|
|
80
80
|
pyedb/dotnet/edb_core/edb_data/layer_data.py,sha256=2K1rvBXAWg3s8paNU6TPNb5tC1B3bRHmiUZjVsoX_Z8,26001
|
|
81
81
|
pyedb/dotnet/edb_core/edb_data/nets_data.py,sha256=Ifi5uSfnOuTLwesO9TS3_F-qa_8rpPXrJy6W5lvIWik,9684
|
|
82
|
-
pyedb/dotnet/edb_core/edb_data/padstacks_data.py,sha256=
|
|
82
|
+
pyedb/dotnet/edb_core/edb_data/padstacks_data.py,sha256=W6yX4KxDdD7OiPQjuLEsXivKNp3yDoCzWNliEDHeRaM,85380
|
|
83
83
|
pyedb/dotnet/edb_core/edb_data/ports.py,sha256=wr2RQi8VExuNIVmnp7c4VpTIhODgthmJmHr01zO4ueo,8873
|
|
84
|
-
pyedb/dotnet/edb_core/edb_data/primitives_data.py,sha256=
|
|
84
|
+
pyedb/dotnet/edb_core/edb_data/primitives_data.py,sha256=zDgVbOcvgc7fbpLnCcCHURV9_ePYT4R129kAhSJRy9A,15467
|
|
85
85
|
pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py,sha256=P37-OIsc8TuTC_s3CXRmvZcJqxAftHA7SATfEyoAnMM,20953
|
|
86
86
|
pyedb/dotnet/edb_core/edb_data/simulation_configuration.py,sha256=Z_Iuh7qgj9s0PwmlOOdBOC47imBTgWPAWt8KxGNZmZQ,100432
|
|
87
87
|
pyedb/dotnet/edb_core/edb_data/sources.py,sha256=jzC6p-fiuPEvZn3b9z1-X5UexW5jd48jZRamXillnXI,15700
|
|
@@ -185,7 +185,7 @@ pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py,sha256=YmYI6WTQulL5Uf8Wx
|
|
|
185
185
|
pyedb/misc/siw_feature_config/xtalk_scan/td_xtalk_config.py,sha256=KHa-UqcXuabiVfT2CV-UvWl5Q2qGYHF2Ye9azcAlnXc,3966
|
|
186
186
|
pyedb/modeler/geometry_operators.py,sha256=g_Sy7a6R23sP6RtboJn1rl8uTuo8oeLmMF21rNkzwjk,74198
|
|
187
187
|
pyedb/siwave_core/icepak.py,sha256=WnZ-t8mik7LDY06V8hZFV-TxRZJQWK7bu_8Ichx-oBs,5206
|
|
188
|
-
pyedb-0.
|
|
189
|
-
pyedb-0.
|
|
190
|
-
pyedb-0.
|
|
191
|
-
pyedb-0.
|
|
188
|
+
pyedb-0.28.0.dist-info/LICENSE,sha256=qQWivZ12ETN5l3QxvTARY-QI5eoRRlyHdwLlAj0Bg5I,1089
|
|
189
|
+
pyedb-0.28.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
190
|
+
pyedb-0.28.0.dist-info/METADATA,sha256=12aP4dKjrhx21He3-0FQDDWfpDMkTHmpM8b1IF2pckU,8388
|
|
191
|
+
pyedb-0.28.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|