pyedb 0.11.2__py3-none-any.whl → 0.12.1__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 CHANGED
@@ -44,7 +44,7 @@ deprecation_warning()
44
44
  #
45
45
 
46
46
  pyedb_path = os.path.dirname(__file__)
47
- __version__ = "0.11.2"
47
+ __version__ = "0.12.1"
48
48
  version = __version__
49
49
 
50
50
  #
@@ -27,25 +27,25 @@ class CfgBoundaries:
27
27
  def __init__(self, pdata, boundaries_dict):
28
28
  self._pedb = pdata.pedb
29
29
  self._boundaries_dict = boundaries_dict
30
- self.open_region = self._boundaries_dict.get("open_region", True)
30
+ self.open_region = self._boundaries_dict.get("open_region", None)
31
31
  self._map_open_region_type()
32
- self.pml_visible = self._boundaries_dict.get("pml_visible", False)
33
- self.pml_operation_frequency = self._boundaries_dict.get("pml_operation_frequency", "5GHz")
34
- self.pml_radiation_factor = self._boundaries_dict.get("pml_radiation_factor", 10)
32
+ self.pml_visible = self._boundaries_dict.get("pml_visible", None)
33
+ self.pml_operation_frequency = self._boundaries_dict.get("pml_operation_frequency", None)
34
+ self.pml_radiation_factor = self._boundaries_dict.get("pml_radiation_factor", None)
35
35
  self._map_dielectric_extend_type()
36
- self.dielectric_base_polygon = self._boundaries_dict.get("dielectric_base_polygon", "")
37
- self.horizontal_padding = self._boundaries_dict.get("horizontal_padding", 0.0)
36
+ self.dielectric_base_polygon = self._boundaries_dict.get("dielectric_base_polygon", None)
37
+ self.horizontal_padding = self._boundaries_dict.get("horizontal_padding", None)
38
38
  self.honor_primitives_on_dielectric_layers = self._boundaries_dict.get(
39
39
  "honor_primitives_on_dielectric_layers", False
40
40
  )
41
41
  self._map_air_box_extend_type()
42
- self.air_box_base_polygon = self._boundaries_dict.get("air_box_base_polygon", "")
42
+ self.air_box_base_polygon = self._boundaries_dict.get("air_box_base_polygon", None)
43
43
  self.air_box_truncate_model_ground_layers = self._boundaries_dict.get(
44
- "air_box_truncate_model_ground_layers", False
44
+ "air_box_truncate_model_ground_layers", None
45
45
  )
46
- self.air_box_horizontal_padding = self._boundaries_dict.get("air_box_horizontal_padding", 0.15)
47
- self.air_box_positive_vertical_padding = self._boundaries_dict.get("air_box_positive_vertical_padding", 1)
48
- self.air_box_negative_vertical_padding = self._boundaries_dict.get("air_box_negative_vertical_padding", 1)
46
+ self.air_box_horizontal_padding = self._boundaries_dict.get("air_box_horizontal_padding", None)
47
+ self.air_box_positive_vertical_padding = self._boundaries_dict.get("air_box_positive_vertical_padding", None)
48
+ self.air_box_negative_vertical_padding = self._boundaries_dict.get("air_box_negative_vertical_padding", None)
49
49
 
50
50
  def _map_air_box_extend_type(self):
51
51
  air_box_type = self._boundaries_dict.get("air_box_extents_type", None)
@@ -94,22 +94,32 @@ class CfgBoundaries:
94
94
 
95
95
  def apply(self):
96
96
  """Imports boundary information from JSON."""
97
- self._pedb.hfss.hfss_extent_info.use_open_region = self.open_region
97
+ if self.open_region is not None:
98
+ self._pedb.hfss.hfss_extent_info.use_open_region = self.open_region
98
99
  self._pedb.hfss.hfss_extent_info.open_region_type = self.open_region_type.name.lower()
99
- self._pedb.hfss.hfss_extent_info.is_pml_visible = self.pml_visible
100
- self._pedb.hfss.hfss_extent_info.operating_freq = self.pml_operation_frequency
101
- self._pedb.hfss.hfss_extent_info.radiation_level = self.pml_radiation_factor
100
+ if self.pml_visible is not None:
101
+ self._pedb.hfss.hfss_extent_info.is_pml_visible = self.pml_visible
102
+ if self.pml_operation_frequency:
103
+ self._pedb.hfss.hfss_extent_info.operating_freq = self.pml_operation_frequency
104
+ if self.pml_radiation_factor:
105
+ self._pedb.hfss.hfss_extent_info.radiation_level = self.pml_radiation_factor
102
106
  self._pedb.hfss.hfss_extent_info.extent_type = self.dielectric_extents_type.name.lower()
103
107
  if self.dielectric_base_polygon:
104
108
  self._pedb.hfss.hfss_extent_info.dielectric_base_polygon = self.dielectric_base_polygon
105
- self._pedb.hfss.hfss_extent_info.dielectric_extent_size = float(self.horizontal_padding)
106
- self._pedb.hfss.hfss_extent_info.honor_user_dielectric = self.honor_primitives_on_dielectric_layers
109
+ if self.horizontal_padding:
110
+ self._pedb.hfss.hfss_extent_info.dielectric_extent_size = float(self.horizontal_padding)
111
+ if self.honor_primitives_on_dielectric_layers is not None:
112
+ self._pedb.hfss.hfss_extent_info.honor_user_dielectric = self.honor_primitives_on_dielectric_layers
107
113
  self._pedb.hfss.hfss_extent_info.extent_type = self.air_box_extents_type.name.lower()
108
- self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground = self.air_box_truncate_model_ground_layers
109
- self._pedb.hfss.hfss_extent_info.air_box_horizontal_extent = float(self.air_box_horizontal_padding)
110
- self._pedb.hfss.hfss_extent_info.air_box_positive_vertical_extent = float(
111
- self.air_box_positive_vertical_padding
112
- )
113
- self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent = float(
114
- self.air_box_negative_vertical_padding
115
- )
114
+ if self.air_box_truncate_model_ground_layers is not None:
115
+ self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground = self.air_box_truncate_model_ground_layers
116
+ if self.air_box_horizontal_padding:
117
+ self._pedb.hfss.hfss_extent_info.air_box_horizontal_extent = float(self.air_box_horizontal_padding)
118
+ if self.air_box_positive_vertical_padding:
119
+ self._pedb.hfss.hfss_extent_info.air_box_positive_vertical_extent = float(
120
+ self.air_box_positive_vertical_padding
121
+ )
122
+ if self.air_box_negative_vertical_padding:
123
+ self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent = float(
124
+ self.air_box_negative_vertical_padding
125
+ )
@@ -39,30 +39,42 @@ class CfgData(object):
39
39
  self.pedb = pedb
40
40
  self.edb_comps = self.pedb.components.components
41
41
  self.general = CfgGeneral(self, kwargs.get("general", None))
42
+
42
43
  self.boundaries = {}
43
44
  if kwargs.get("boundaries", None):
44
45
  self.boundaries = CfgBoundaries(self, kwargs.get("boundaries", None))
45
- self.nets = CfgNets(self)
46
+
47
+ self.nets = None
46
48
  if kwargs.get("nets"):
47
49
  self.nets = CfgNets(
48
50
  self, kwargs.get("nets", {}).get("signal_nets", []), kwargs.get("nets", {}).get("power_ground_nets", [])
49
51
  )
52
+
50
53
  self.components = [CfgComponent(self, **component) for component in kwargs.get("components", [])]
54
+
51
55
  self.padstacks = CfgPadstacks(self, kwargs.get("padstacks", None))
56
+
52
57
  self.pin_groups = [CfgPinGroup(self, pin_group) for pin_group in kwargs.get("pin_groups", [])]
58
+
53
59
  self.ports = [CfgPort(self, **port) for port in kwargs.get("ports", [])]
60
+
54
61
  self.sources = [CfgSources(self, **source) for source in kwargs.get("sources", [])]
55
- self.setups = [CfgSetup(self)]
62
+
63
+ self.setups = []
56
64
  if kwargs.get("setups", None):
57
65
  self.setups = [CfgSetup(self, setup) for setup in kwargs.get("setups", [])]
66
+
58
67
  self.stackup = None
68
+
59
69
  self.s_parameters = [
60
70
  CfgSParameterModel(self, self.general.s_parameter_library, sparam_model)
61
71
  for sparam_model in kwargs.get("s_parameters", [])
62
72
  ]
73
+
63
74
  self.spice_models = [
64
75
  CfgSpiceModel(self, self.general.spice_model_library, spice_model)
65
76
  for spice_model in kwargs.get("spice_models", [])
66
77
  ]
78
+
67
79
  self.package_definition = None
68
80
  self.operations = None
@@ -54,20 +54,24 @@ class Definition:
54
54
  def __init__(self, pdata, definition_dict):
55
55
  self._pedb = pdata.pedb
56
56
  self._definition_dict = definition_dict
57
- self.name = self._definition_dict.get("name", "")
58
- self.hole_diameter = self._definition_dict.get("hole_diameter", "")
59
- self.hole_plating_thickness = self._definition_dict.get("hole_plating_thickness", "")
60
- self.hole_material = self._definition_dict.get("hole_material", "")
61
- self.hole_range = self._definition_dict.get("hole_range", "")
57
+ self.name = self._definition_dict.get("name", None)
58
+ self.hole_diameter = self._definition_dict.get("hole_diameter", None)
59
+ self.hole_plating_thickness = self._definition_dict.get("hole_plating_thickness", None)
60
+ self.hole_material = self._definition_dict.get("hole_material", None)
61
+ self.hole_range = self._definition_dict.get("hole_range", None)
62
62
 
63
63
  def apply(self):
64
64
  """Apply padstack definition on layout."""
65
65
  padstack_defs = self._pedb.padstacks.definitions
66
66
  pdef = padstack_defs[self.name]
67
- pdef.hole_diameter = self.hole_diameter
68
- pdef.hole_plating_thickness = self.hole_plating_thickness
69
- pdef.material = self.hole_material
70
- pdef.hole_range = self.hole_range
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
71
75
 
72
76
 
73
77
  class Instance:
@@ -36,7 +36,7 @@ class CfgPinGroup:
36
36
  """Apply pin group on layout."""
37
37
  if self.pins:
38
38
  if not self._pedb.siwave.create_pin_group(self.reference_designator, list(self.pins), self.name):
39
- self._pedb.loogger.error(f"Failed to create pin group on pins {self.pins}")
39
+ self._pedb.logger.error(f"Failed to create pin group on pins {self.pins}")
40
40
  return False
41
41
  self._pedb.logger.info(f"Pin group {self.name} created.")
42
42
  return True
@@ -41,8 +41,8 @@ class CfgCircuitElement:
41
41
  self.neg_term_info = kwargs.get("negative_terminal", None)
42
42
 
43
43
  @pyedb_function_handler
44
- def _create(self):
45
- """Create step 1."""
44
+ def _create_terminals(self):
45
+ """Create step 1. Collect positive and negative terminals."""
46
46
  pos_term_info = self.pos_term_info
47
47
  if pos_term_info:
48
48
  pos_type, pos_value = [[i, j] for i, j in pos_term_info.items()][0]
@@ -71,16 +71,26 @@ class CfgCircuitElement:
71
71
  self.neg_terminal = None
72
72
  if neg_term_info:
73
73
  neg_type, neg_value = [[i, j] for i, j in neg_term_info.items()][0]
74
- if neg_type == "pin_group":
75
- pin_group = {neg_value: self.pedb.siwave.pin_groups[neg_value]}
74
+ if neg_type == "nearest_pin":
75
+ ref_net = neg_value.get("reference_net", "GND")
76
+ search_radius = neg_value.get("search_radius", "5e-3")
77
+ temp = dict()
78
+ for i, j in pos_objs.items():
79
+ temp[i] = self._pdata.pedb.padstacks.get_reference_pins(j, ref_net, search_radius, max_limit=1)[0]
80
+ self.neg_terminal = {
81
+ i: j.create_terminal(i + "_ref") if not j.terminal else j.terminal for i, j in temp.items()
82
+ }
76
83
  else:
77
- # Get pins
78
- pins = self._get_pins(neg_type, neg_value) # terminal type pin or net
79
- # create pin group
80
- pin_group = self._create_pin_group(pins, True)
81
- self.neg_terminal = [j.create_terminal(i) if not j.terminal else j.terminal for i, j in pin_group.items()][
82
- 0
83
- ]
84
+ if neg_type == "pin_group":
85
+ pin_group = {neg_value: self.pedb.siwave.pin_groups[neg_value]}
86
+ else:
87
+ # Get pins
88
+ pins = self._get_pins(neg_type, neg_value) # terminal type pin or net
89
+ # create pin group
90
+ pin_group = self._create_pin_group(pins, True)
91
+ self.neg_terminal = [
92
+ j.create_terminal(i) if not j.terminal else j.terminal for i, j in pin_group.items()
93
+ ][0]
84
94
 
85
95
  @pyedb_function_handler
86
96
  def _get_pins(self, terminal_type, terminal_value):
@@ -125,11 +135,14 @@ class CfgPort(CfgCircuitElement):
125
135
  @pyedb_function_handler
126
136
  def create(self):
127
137
  """Create port."""
128
- self._create()
138
+ self._create_terminals()
129
139
  is_circuit_port = True if self.type == "circuit" else False
130
140
  circuit_elements = []
131
- for _, j in self.pos_terminals.items():
132
- elem = self.pedb.create_port(j, self.neg_terminal, is_circuit_port)
141
+ for name, j in self.pos_terminals.items():
142
+ if isinstance(self.neg_terminal, dict):
143
+ elem = self.pedb.create_port(j, self.neg_terminal[name], is_circuit_port)
144
+ else:
145
+ elem = self.pedb.create_port(j, self.neg_terminal, is_circuit_port)
133
146
  if not self.distributed:
134
147
  elem.name = self.name
135
148
  circuit_elements.append(elem)
@@ -148,12 +161,15 @@ class CfgSources(CfgCircuitElement):
148
161
  @pyedb_function_handler
149
162
  def create(self):
150
163
  """Create sources."""
151
- self._create()
164
+ self._create_terminals()
152
165
  is_circuit_port = True if self.type == "circuit" else False
153
166
  circuit_elements = []
154
167
  method = self.pedb.create_current_source if self.type == "current" else self.pedb.create_voltage_source
155
- for _, j in self.pos_terminals.items():
156
- elem = method(j, self.neg_terminal)
168
+ for name, j in self.pos_terminals.items():
169
+ if isinstance(self.neg_terminal, dict):
170
+ elem = method(j, self.neg_terminal[name])
171
+ else:
172
+ elem = method(j, self.neg_terminal)
157
173
  if not self.distributed:
158
174
  elem.name = self.name
159
175
  elem.magnitude = self.magnitude
@@ -27,7 +27,6 @@ import toml
27
27
 
28
28
  from pyedb.configuration.cfg_data import CfgData
29
29
  from pyedb.dotnet.edb_core.definition.package_def import PackageDef
30
- from pyedb.dotnet.edb_core.stackup import LayerCollection
31
30
  from pyedb.generic.general_methods import pyedb_function_handler
32
31
 
33
32
 
@@ -182,56 +181,44 @@ class Configuration:
182
181
  layers = data.get("layers")
183
182
 
184
183
  if layers:
185
- lc = self._pedb.stackup
186
184
  input_signal_layers = [i for i in layers if i["type"].lower() == "signal"]
187
- if not len(input_signal_layers) == len(lc.signal_layers):
185
+ if not len(input_signal_layers) == len(self._pedb.stackup.signal_layers):
188
186
  self._pedb.logger.error("Input signal layer count do not match.")
189
187
  return False
190
188
 
191
- layer_clones = []
192
- doc_layer_clones = []
193
- for name, obj in lc.layers.items():
194
- if obj.is_stackup_layer:
195
- if obj.type == "signal": # keep signal layers
196
- layer_clones.append(obj)
197
- else:
198
- doc_layer_clones.append(obj)
199
-
200
- lc_new = LayerCollection(self._pedb)
201
- lc_new.auto_refresh = False
202
- signal_layer_ids = {}
203
- top_layer_clone = None
204
-
205
- # add all signal layers
189
+ removal_list = []
190
+ lc_signal_layers = []
191
+ for name, obj in self._pedb.stackup.all_layers.items():
192
+ if obj.type == "dielectric":
193
+ removal_list.append(name)
194
+ elif obj.type == "signal":
195
+ lc_signal_layers.append(obj.id)
196
+ for l in removal_list:
197
+ self._pedb.stackup.remove_layer(l)
198
+
199
+ # update all signal layers
200
+ id_name = {i[0]: i[1] for i in self._pedb.stackup.layers_by_id}
201
+ signal_idx = 0
206
202
  for l in layers:
207
203
  if l["type"] == "signal":
208
- clone = layer_clones.pop(0)
209
- clone.update(**l)
210
- lc_new.add_layer_bottom(name=clone.name, layer_clone=clone)
211
- signal_layer_ids[clone.name] = clone.id
212
-
213
- # add all document layers at bottom
214
- for l in doc_layer_clones:
215
- doc_layer = lc_new.add_document_layer(name=l.name, layer_clone=l)
216
- first_doc_layer_name = doc_layer.name
204
+ layer_id = lc_signal_layers[signal_idx]
205
+ layer_name = id_name[layer_id]
206
+ self._pedb.stackup.layers[layer_name].update(**l)
207
+ signal_idx = signal_idx + 1
217
208
 
218
209
  # add all dielectric layers. Dielectric layers must be added last. Otherwise,
219
210
  # dielectric layer will occupy signal and document layer id.
220
211
  prev_layer_clone = None
221
212
  l = layers.pop(0)
222
213
  if l["type"] == "signal":
223
- prev_layer_clone = lc_new.layers[l["name"]]
214
+ prev_layer_clone = self._pedb.stackup.layers[l["name"]]
224
215
  else:
225
- prev_layer_clone = lc_new.add_layer_top(**l)
216
+ prev_layer_clone = self._pedb.stackup.add_layer_top(**l)
226
217
  for idx, l in enumerate(layers):
227
218
  if l["type"] == "dielectric":
228
- prev_layer_clone = lc_new.add_layer_below(base_layer_name=prev_layer_clone.name, **l)
229
- else:
230
- prev_layer_clone = lc_new.layers[l["name"]]
231
-
232
- lc._edb_object = lc_new._edb_object
233
- lc_new.auto_refresh = True
234
- lc.update_layout()
219
+ prev_layer_clone = self._pedb.stackup.add_layer_below(base_layer_name=prev_layer_clone.name, **l)
220
+ elif l["type"] == "signal":
221
+ prev_layer_clone = self._pedb.stackup.layers[l["name"]]
235
222
 
236
223
  @pyedb_function_handler
237
224
  def _load_operations(self):
pyedb/dotnet/edb.py CHANGED
@@ -846,9 +846,7 @@ class Edb(Database):
846
846
  >>> edbapp.stackup.layers["TOP"].thickness == 4e-05
847
847
  >>> edbapp.stackup.add_layer("Diel", "GND", layer_type="dielectric", thickness="0.1mm", material="FR4_epoxy")
848
848
  """
849
- if not self._stackup2 and self.active_db:
850
- self._stackup2 = Stackup(self, self.layout.layer_collection)
851
- return self._stackup2
849
+ return Stackup(self, self.layout.layer_collection)
852
850
 
853
851
  @property
854
852
  def materials(self):
@@ -3702,12 +3700,10 @@ class Edb(Database):
3702
3700
  self.logger.error("Setup name already used in the layout")
3703
3701
  return False
3704
3702
  version = self.edbversion.split(".")
3705
- if int(version[0]) == 2024 and int(version[-1]) >= 2 or int(version[0]) > 2024:
3706
- setup = HFSSPISimulationSetup(self).create(name)
3707
- return setup
3708
- else:
3703
+ if float(self.edbversion) < 2024.2:
3709
3704
  self.logger.error("HFSSPI simulation only supported with Ansys release 2024R2 and higher")
3710
3705
  return False
3706
+ return HFSSPISimulationSetup(self).create(name)
3711
3707
 
3712
3708
  @pyedb_function_handler()
3713
3709
  def create_siwave_syz_setup(self, name=None):
@@ -977,19 +977,18 @@ class ViaSettings(object):
977
977
  -------
978
978
  bool
979
979
  """
980
- if self._parent._pedb.version[0] >= 10:
981
- return self._via_settings.ViaMeshPlating
982
- else:
980
+ if float(self._parent._pedb.edbversion) < 2024.1:
983
981
  self._parent._pedb.logger.error("Property only supported on Ansys release 2024R1 and later")
984
982
  return False
983
+ return self._via_settings.ViaMeshPlating
985
984
 
986
985
  @via_mesh_plating.setter
987
986
  def via_mesh_plating(self, value):
988
- if self._parent._pedb.version[0] >= 10:
987
+ if float(self._parent._pedb.edbversion) < 2024.1:
988
+ self._parent._pedb.logger.error("Property only supported on Ansys release 2024R1 and later")
989
+ else:
989
990
  self._via_settings.ViaMeshPlating = value
990
991
  self._parent._update_setup()
991
- else:
992
- self._parent._pedb.logger.error("Property only supported on Ansys release 2024R1 and later")
993
992
 
994
993
  @property
995
994
  def via_material(self):
@@ -257,8 +257,8 @@ class StackupLayerEdbClass(LayerEdbClass):
257
257
  self._lower_elevation = 0.0
258
258
 
259
259
  def _create(self, layer_type):
260
- layer_type = self._layer_name_mapping[layer_type]
261
- layer_type = self._layer_type_mapping[layer_type]
260
+ layer_type_edb_name = self._layer_name_mapping[layer_type]
261
+ layer_type = self._layer_type_mapping[layer_type_edb_name]
262
262
  self._edb_object = self._pedb.edb_api.cell._cell.StackupLayer(
263
263
  self._name,
264
264
  layer_type,
@@ -1183,7 +1183,7 @@ class EDBPadstackInstance(EDBPrimitivesMain):
1183
1183
  -------
1184
1184
  :class:`pyedb.dotnet.edb_core.edb_data.terminals`
1185
1185
  """
1186
-
1186
+ warnings.warn("Use new property :func:`terminal` instead.", DeprecationWarning)
1187
1187
  if create_new_terminal:
1188
1188
  term = self._create_terminal(name)
1189
1189
  else:
@@ -1195,6 +1195,14 @@ class EDBPadstackInstance(EDBPrimitivesMain):
1195
1195
  if not term.is_null:
1196
1196
  return term
1197
1197
 
1198
+ @property
1199
+ def terminal(self):
1200
+ """Terminal."""
1201
+ from pyedb.dotnet.edb_core.edb_data.terminals import PadstackInstanceTerminal
1202
+
1203
+ term = PadstackInstanceTerminal(self._pedb, self._edb_object.GetPadstackInstanceTerminal())
1204
+ return term if not term.is_null else None
1205
+
1198
1206
  @pyedb_function_handler()
1199
1207
  def _create_terminal(self, name=None):
1200
1208
  """Create a padstack instance terminal"""
@@ -1259,6 +1259,7 @@ class EdbSiwave(object):
1259
1259
  )
1260
1260
 
1261
1261
  if edb_pingroup.IsNull(): # pragma: no cover
1262
+ self._logger.error(f"Failed to create pin group {group_name}.")
1262
1263
  return False
1263
1264
  else:
1264
1265
  names = [i for i in pins if i.GetNet().GetName()]
@@ -69,8 +69,6 @@ logger = logging.getLogger(__name__)
69
69
 
70
70
 
71
71
  class LayerCollection(object):
72
- auto_refresh = True
73
-
74
72
  def __init__(self, pedb, edb_object=None):
75
73
  self._pedb = pedb
76
74
 
@@ -91,17 +89,21 @@ class LayerCollection(object):
91
89
  "multizone": self._pedb.edb_api.cell._cell.LayerCollectionMode.MultiZone,
92
90
  }
93
91
 
94
- def update_layout(self, stackup=None):
92
+ def update_layout(self):
95
93
  """Set layer collection into edb.
96
94
 
97
95
  Parameters
98
96
  ----------
99
97
  stackup
100
98
  """
101
- if stackup:
102
- self._edb_object = stackup._edb_object
103
99
  self._pedb.layout.layer_collection = self._edb_object
104
100
 
101
+ @pyedb_function_handler()
102
+ def refresh_layer_collection(self):
103
+ """Refresh layer collection from Edb. This method is run on demand after all edit operations on stackup."""
104
+ self._edb_object = self._pedb.edb_api.cell._cell.LayerCollection(self._pedb.layout.layer_collection)
105
+ self._lc = self._edb_object
106
+
105
107
  @pyedb_function_handler
106
108
  def _add_layer(self, add_method, base_layer_name="", **kwargs):
107
109
  """Add a layer to edb.
@@ -115,7 +117,13 @@ class LayerCollection(object):
115
117
  if layer_clone:
116
118
  obj = layer_clone
117
119
  else:
118
- obj = StackupLayerEdbClass(self._pedb, edb_object=None, **kwargs)
120
+ layer_type = kwargs.get("layer_type", None)
121
+ if not layer_type:
122
+ layer_type = kwargs["type"]
123
+ if layer_type in ["signal", "dielectric"]:
124
+ obj = StackupLayerEdbClass(self._pedb, edb_object=None, **kwargs)
125
+ else:
126
+ obj = LayerEdbClass(self._pedb, edb_object=None, **kwargs)
119
127
  method_top_bottom = None
120
128
  method_above_below = None
121
129
  if add_method == "add_layer_top":
@@ -134,8 +142,7 @@ class LayerCollection(object):
134
142
  obj = obj if method_top_bottom(obj._edb_object) else False
135
143
  elif method_above_below:
136
144
  obj = obj if method_above_below(obj._edb_object, base_layer_name) else False
137
- if self.auto_refresh:
138
- self.update_layout()
145
+ self.update_layout()
139
146
  return obj
140
147
 
141
148
  @pyedb_function_handler
@@ -268,8 +275,7 @@ class LayerCollection(object):
268
275
  lc.AddLayerBottom(i._edb_object)
269
276
 
270
277
  self._edb_object = lc
271
- if self.auto_refresh:
272
- self.update_layout()
278
+ self.update_layout()
273
279
 
274
280
  if not obj:
275
281
  logger.info("Layer clone was not found in stackup or non stackup layers.")
@@ -278,33 +284,32 @@ class LayerCollection(object):
278
284
  @property
279
285
  def stackup_layers(self):
280
286
  """Retrieve the dictionary of signal and dielectric layers."""
281
- temp = list(self._edb_object.Layers((self._pedb.edb_api.cell.layer_type_set.StackupLayerSet)))
282
- layers = OrderedDict()
283
- for i in temp:
284
- name = i.GetName()
285
- layers[name] = StackupLayerEdbClass(self._pedb, i.Clone(), name=name)
286
- return layers
287
+ warnings.warn("Use new property :func:`layers` instead.", DeprecationWarning)
288
+ return self.layers
287
289
 
288
290
  @property
289
291
  def non_stackup_layers(self):
290
292
  """Retrieve the dictionary of signal layers."""
291
- temp = list(self._edb_object.Layers(self._layer_type_set_mapping["non_stackup_layer_set"]))
292
- layers = OrderedDict()
293
- for i in temp:
294
- name = i.GetName()
295
- layers[name] = LayerEdbClass(self._pedb, i, name=name)
296
- return layers
293
+ return {name: obj for name, obj in self.all_layers.items() if not obj.is_stackup_layer}
297
294
 
298
295
  @property
299
- def layers_by_id(self):
300
- """Retrieve the list of layers with their ids."""
301
- layer_list = list(self._layer_collection.Layers(self._pedb.edb_api.cell.layer_type_set.AllLayerSet))
302
- temp = []
296
+ def all_layers(self):
297
+ self.refresh_layer_collection()
298
+ layer_list = list(self._edb_object.Layers(self._pedb.edb_api.cell.layer_type_set.AllLayerSet))
299
+ temp = dict()
303
300
  for i in layer_list:
304
- obj = StackupLayerEdbClass(self._pedb, i.Clone(), name=i.GetName)
305
- temp.append([obj.id, obj.name])
301
+ if i.IsStackupLayer():
302
+ obj = StackupLayerEdbClass(self._pedb, i.Clone(), name=i.GetName())
303
+ else:
304
+ obj = LayerEdbClass(self._pedb, i.Clone(), name=i.GetName())
305
+ temp[obj.name] = obj
306
306
  return temp
307
307
 
308
+ @property
309
+ def layers_by_id(self):
310
+ """Retrieve the list of layers with their ids."""
311
+ return [[obj.id, name] for name, obj in self.all_layers.items()]
312
+
308
313
  @property
309
314
  def layers(self):
310
315
  """Retrieve the dictionary of layers.
@@ -313,22 +318,14 @@ class LayerCollection(object):
313
318
  -------
314
319
  Dict[str, :class:`pyedb.dotnet.edb_core.edb_data.layer_data.LayerEdbClass`]
315
320
  """
316
- _lays = OrderedDict()
317
- layer_list = list(self._edb_object.Layers(self._pedb.edb_api.cell.layer_type_set.AllLayerSet))
318
- for l in layer_list:
319
- name = l.GetName()
320
- if not l.IsStackupLayer():
321
- _lays[name] = LayerEdbClass(self._pedb, l, name=name)
322
- else:
323
- _lays[name] = StackupLayerEdbClass(self._pedb, l, name=name)
324
- return _lays
321
+ return {name: obj for name, obj in self.all_layers.items() if obj.is_stackup_layer}
325
322
 
326
323
 
327
324
  class Stackup(LayerCollection):
328
325
  """Manages EDB methods for stackup accessible from `Edb.stackup` property."""
329
326
 
330
327
  def __getitem__(self, item):
331
- return self.layers[item]
328
+ return self.all_layers[item]
332
329
 
333
330
  def __init__(self, pedb, edb_object=None):
334
331
  super().__init__(pedb, edb_object)
@@ -576,12 +573,6 @@ class Stackup(LayerCollection):
576
573
  )
577
574
  return True
578
575
 
579
- @pyedb_function_handler()
580
- def refresh_layer_collection(self):
581
- """Refresh layer collection from Edb. This method is run on demand after all edit operations on stackup."""
582
- self._lc = self._pedb.edb_api.cell._cell.LayerCollection(self._pedb.layout.layer_collection)
583
- self._edb_object = self._lc
584
-
585
576
  @property
586
577
  def _layer_collection(self):
587
578
  """Copy of EDB layer collection.
@@ -591,8 +582,7 @@ class Stackup(LayerCollection):
591
582
  :class:`Ansys.Ansoft.Edb.Cell.LayerCollection`
592
583
  Collection of layers.
593
584
  """
594
- if not self._lc:
595
- self.refresh_layer_collection()
585
+ self.refresh_layer_collection()
596
586
  return self._lc
597
587
 
598
588
  @property
@@ -620,7 +610,7 @@ class Stackup(LayerCollection):
620
610
  self._layer_collection.SetMode(mode.Overlapping)
621
611
  elif value == 2 or value == mode.MultiZone or value == "MultiZone":
622
612
  self._layer_collection.SetMode(mode.MultiZone)
623
- self._pedb.layout.layer_collection = self._layer_collection
613
+ self.update_layout()
624
614
 
625
615
  @property
626
616
  def stackup_mode(self):
@@ -744,9 +734,8 @@ class Stackup(LayerCollection):
744
734
  _lc.AddStackupLayerAtElevation(layer_clone)
745
735
  elif operation == "non_stackup":
746
736
  _lc.AddLayerBottom(layer_clone)
747
- if self.auto_refresh:
748
- self._pedb.layout.layer_collection = _lc
749
- self.refresh_layer_collection()
737
+ self._pedb.layout.layer_collection = _lc
738
+ self.refresh_layer_collection()
750
739
  return True
751
740
 
752
741
  @pyedb_function_handler()
@@ -814,17 +803,7 @@ class Stackup(LayerCollection):
814
803
  bool
815
804
  "True" if successful, ``False`` if failed.
816
805
  """
817
- outlineLayer = self._pedb.edb_api.cell.layer.FindByName(self._pedb.layout.layer_collection, outline_name)
818
- if outlineLayer.IsNull():
819
- return self.add_layer(
820
- outline_name,
821
- layer_type="outline",
822
- material="",
823
- fillMaterial="",
824
- thickness="",
825
- )
826
- else:
827
- return False
806
+ return self.add_document_layer(name="Outline", layer_type="outline")
828
807
 
829
808
  # TODO: Update optional argument material into material_name and fillMaterial into fill_material_name
830
809
  @pyedb_function_handler()
@@ -36,6 +36,7 @@ class BaseSimulationSetup(object):
36
36
  EDB object.
37
37
  """
38
38
 
39
+ @pyedb_function_handler
39
40
  def __init__(self, pedb, edb_setup=None):
40
41
  self._pedb = pedb
41
42
  self._edb_object = edb_setup
@@ -59,7 +60,7 @@ class BaseSimulationSetup(object):
59
60
  }
60
61
 
61
62
  version = self._pedb.edbversion.split(".")
62
- if int(version[0]) == 2024 and int(version[1]) == 2 or int(version[0]) > 2024:
63
+ if float(self._pedb.edbversion) >= 2024.2:
63
64
  self._setup_type_mapping.update(
64
65
  {
65
66
  "kRaptorX": self._pedb.simsetupdata.RaptorX.RaptorXSimulationSettings,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyedb
3
- Version: 0.11.2
3
+ Version: 0.12.1
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>
@@ -1,23 +1,23 @@
1
- pyedb/__init__.py,sha256=C795I8bcWORZf5IJiI-M1ZRxjImvymTFp4TDMevi0j0,1521
1
+ pyedb/__init__.py,sha256=6XNbzc6ACi5_YyN4AHoYcryfduYa2LhbWMGddPbk0aQ,1521
2
2
  pyedb/edb_logger.py,sha256=yNkXnoL2me7ubLT6O6r6ElVnkZ1g8fmfFYC_2XJZ1Sw,14950
3
3
  pyedb/exceptions.py,sha256=n94xluzUks6BA24vd_L6HkrvoP_H_l6__hQmqzdCyPo,111
4
4
  pyedb/siwave.py,sha256=c2stPkGPdM9c0wJ19SJq_uiYTdW3sp-uO8MVA_iDw30,12548
5
5
  pyedb/configuration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- pyedb/configuration/cfg_boundaries.py,sha256=ABjSlQCRMJNw1YX2B4aADNlLrrFbdyv7UWewiXVdxTk,6105
6
+ pyedb/configuration/cfg_boundaries.py,sha256=iThJw52omnGikp20uNVgW4w0VcrzF68dXUaMb2MfOt4,6646
7
7
  pyedb/configuration/cfg_components.py,sha256=cvQfMjh6HBTVzVuDI7A8zkEhtgraG25dJqHRH-FbkTA,8789
8
- pyedb/configuration/cfg_data.py,sha256=ZThr2rpCj4axwrBr-aQWtiTztEhRAZb1pX-S3_92aJQ,3483
8
+ pyedb/configuration/cfg_data.py,sha256=uSgyJaKMzw8f_-uWc5bp0MnXnoWRZHxSipIkA_4pSQY,3472
9
9
  pyedb/configuration/cfg_general.py,sha256=dB5Tpird4uiyrseOe8-QlWKsat15TjMLar5I8VZME3c,1625
10
10
  pyedb/configuration/cfg_nets.py,sha256=mJvN_ON4Qw5psNV3agXCQAhVJbRnBpRZu1Ti3b7QnMw,1879
11
- pyedb/configuration/cfg_padstacks.py,sha256=dcZku_OuZ2XaL5Vs8BEJvdcdi1N8F0EMAYNwBSdkbt0,5412
12
- pyedb/configuration/cfg_pin_groups.py,sha256=BAv-u1e8aPXSTBwUBzDkzRiXB2mfCqb60I5tTrwgI7Y,2877
13
- pyedb/configuration/cfg_ports_sources.py,sha256=iY5GH_ff50bt3muz2w_k9_3VTj_Yigk8Iqfh37a7vRU,6816
11
+ pyedb/configuration/cfg_padstacks.py,sha256=5ta0xkdSaf4qk5lXjM-U4GB2vNS31nhEGsZwwRlhPUI,5568
12
+ pyedb/configuration/cfg_pin_groups.py,sha256=bW_RqTYNFE7i-C74pWY2pUIWoSKMQY-TWW17FIftfQk,2876
13
+ pyedb/configuration/cfg_ports_sources.py,sha256=kicbrgw1YLB2m7xJhrjo9LcfcbwTncGguuzEjZ2pUcQ,7787
14
14
  pyedb/configuration/cfg_s_parameter_models.py,sha256=HPo4sgF5tVefUwgzlP8pDBVSZ1x_pY2EiOtA0-QXjc8,2854
15
15
  pyedb/configuration/cfg_setup.py,sha256=zhq285s5P4s90Dm5s550ldwyIVO8aXiPjAwy87ipRXU,8791
16
16
  pyedb/configuration/cfg_spice_models.py,sha256=5gr28-4u4uj4qY8vgYFAI_PgzOQp-wPgTMMc_WcAN_w,2434
17
- pyedb/configuration/configuration.py,sha256=ykDlI3v8w8x-qWuV8PrwIAHVe9jmBwCb8OeJLfBF4lk,10965
17
+ pyedb/configuration/configuration.py,sha256=hPyUzdOJlMGPaI-Ie3Q1jJpmzpzrAy6XgWjSv8LQ8Q0,10628
18
18
  pyedb/dotnet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  pyedb/dotnet/clr_module.py,sha256=Mo13Of3DVSA5HR-5xZEXOiHApIKy52CUxtJ2gPkEu1A,3406
20
- pyedb/dotnet/edb.py,sha256=I9mgl1CZbJ-_hQNWPct3f3P7m4Sm1KTsMN6Ko6njXmw,172980
20
+ pyedb/dotnet/edb.py,sha256=jSt794srQBzaxt3-iZqcv4ziOgNThWn46k3-V3svJqc,172798
21
21
  pyedb/dotnet/application/Variables.py,sha256=nov1kIyJO25iz8pvbU3MK1meMpRLwtISmzYqJhc7Ouo,79042
22
22
  pyedb/dotnet/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  pyedb/dotnet/edb_core/__init__.py,sha256=nIRLJ8VZLcMAp12zmGsnZ5x2BEEl7q_Kj_KAOXxVjpQ,52
@@ -31,8 +31,8 @@ pyedb/dotnet/edb_core/net_class.py,sha256=lr-7Z0Q1A2fshxwjrIOmQSZnEBYe0NoxuUuJT6
31
31
  pyedb/dotnet/edb_core/nets.py,sha256=ZQ5sk7cgTQJTbHd7JQa7MmBBV_crsWGtcLhKpSbfYMw,44042
32
32
  pyedb/dotnet/edb_core/obj_base.py,sha256=lufR0sZj0QfZ2wlNvLL6aM1KVqCNY2A7taPPdWcK20w,3312
33
33
  pyedb/dotnet/edb_core/padstack.py,sha256=PqXkSfyLRtdehm72sYiVMBUkNlDkivJ-eRoQWCzwNgw,57439
34
- pyedb/dotnet/edb_core/siwave.py,sha256=481ePzP0il60Bu_FqL2NcdcFTWNIBXd8OKnSigPefw8,62419
35
- pyedb/dotnet/edb_core/stackup.py,sha256=rg2LnxUyfd9Nnrj9uAd-0dkr65TQk7iMe0lS6cglaFc,122900
34
+ pyedb/dotnet/edb_core/siwave.py,sha256=4v68zlCO-Czv8A3qtckfQ94jRFbMxM4kuoEDVRo_cmM,62495
35
+ pyedb/dotnet/edb_core/stackup.py,sha256=Zko2gaotcJnILv_4SlZYzFc-NGblmTFBmEua7BSLcHU,122186
36
36
  pyedb/dotnet/edb_core/cell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  pyedb/dotnet/edb_core/cell/hierarchy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  pyedb/dotnet/edb_core/cell/hierarchy/model.py,sha256=cJzNJLiuuoesfCL8-jWo8LbgGbfXrTYNQqmeeE38ieM,3309
@@ -54,10 +54,10 @@ pyedb/dotnet/edb_core/edb_data/design_options.py,sha256=RO9ip-T5Bfxpsl97_QEk0qDZ
54
54
  pyedb/dotnet/edb_core/edb_data/edbvalue.py,sha256=Vj_11HXsQUNavizKp5FicORm6cjhXRh9uvxhv_D_RJc,1977
55
55
  pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py,sha256=5koQSKdYC6Deh4haLUDAxnHlRa-j5S6g4eyAfiGgZP8,13190
56
56
  pyedb/dotnet/edb_core/edb_data/hfss_pi_simulation_setup_data.py,sha256=v3z3h_27v3jRmDXqUjBS8P6UZMi-zuZQrZiYbE-RDw4,15657
57
- pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py,sha256=rXzh95N_jLf6a3OEEJRm50qFX0rM6lS5B5osnKlVzf4,49037
58
- pyedb/dotnet/edb_core/edb_data/layer_data.py,sha256=HVPmE_Rny29J1c8qlJ3TSNZaMOTSxTgE9_vIiQJG0cE,25900
57
+ pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py,sha256=naka5Bm9Ditb6Cj_F1KMrxwGk8Cn2fPtnXlyGb9IY9E,49039
58
+ pyedb/dotnet/edb_core/edb_data/layer_data.py,sha256=N3OIxdx1oeX3Lg1nmM-UcJ_8NQdaQD-_XgUEVlGLzOI,25918
59
59
  pyedb/dotnet/edb_core/edb_data/nets_data.py,sha256=iBegT3fa5DwvjD0Wfd-wlJztFrb33I5v6nzSUhNS6-I,10099
60
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py,sha256=5qq4QohTLkwo-xfk2lXFM8Pria8ZYfZRc5B3XgdboGE,79342
60
+ pyedb/dotnet/edb_core/edb_data/padstacks_data.py,sha256=IiF_wS9ZnyW-8W3wbcvinPAaL0LVuPGU74tHFZgZ1ZQ,79729
61
61
  pyedb/dotnet/edb_core/edb_data/ports.py,sha256=FYxB2rDUtN_OsYAbodXbc5mA_d0BUebmin_B5kkUw3U,9223
62
62
  pyedb/dotnet/edb_core/edb_data/primitives_data.py,sha256=veMDPCb6T84KZ_xgo52g7vHxObsx-Y2ysWXBS2CqZpQ,48155
63
63
  pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py,sha256=Km1sjDVA0vSBOn8u2mMASPEGULQb3h-ZeSK-0Kymzqk,20962
@@ -75,7 +75,7 @@ pyedb/dotnet/edb_core/sim_setup_data/data/__init__.py,sha256=8jByHkoaowAYQTCww-z
75
75
  pyedb/dotnet/edb_core/sim_setup_data/data/siw_dc_ir_settings.py,sha256=b7Zpg6nNQArYxvdxlVhXDzvvCSC5sKFvdt10b0MHkvc,8605
76
76
  pyedb/dotnet/edb_core/utilities/__init__.py,sha256=8jByHkoaowAYQTCww-zRrTQmN061fLz_OHjTLSrzQQY,58
77
77
  pyedb/dotnet/edb_core/utilities/heatsink.py,sha256=7G7Yx9TxbL5EAiR51MnhdRiAQBVf-d0hKsXDw5OYX2Q,2220
78
- pyedb/dotnet/edb_core/utilities/simulation_setup.py,sha256=CsJxL8Q-tdgsybubB_HqIs9q8qJ675xp-ie9qh8kikE,25264
78
+ pyedb/dotnet/edb_core/utilities/simulation_setup.py,sha256=ZU-HFdIqJ0DBQJqUHzU4-nzCHQ620h2ev7uR89ZFnqk,25256
79
79
  pyedb/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  pyedb/generic/constants.py,sha256=prWLZH0-SeBIVK6LHZ4SGZFQCofuym2TuQYfdqwhuSQ,28956
81
81
  pyedb/generic/data_handlers.py,sha256=oyYFwdjt0CxdOxgFDmnBlOFICt2twFLsMyELuQ1kFjE,7137
@@ -148,7 +148,7 @@ pyedb/misc/siw_feature_config/emc/tag_library.py,sha256=yUK4w3hequU017E2DbkA4KE2
148
148
  pyedb/misc/siw_feature_config/emc/xml_generic.py,sha256=55X-V0OxWq-v7FTiDVjaZif8V_2xxsvJlJ8bs9Bf61I,2521
149
149
  pyedb/modeler/geometry_operators.py,sha256=LDqEaeerw9H8Yva-SJhX3Afdni08OciO9t5G0c_tdqs,66820
150
150
  pyedb/siwave_core/icepak.py,sha256=WnZ-t8mik7LDY06V8hZFV-TxRZJQWK7bu_8Ichx-oBs,5206
151
- pyedb-0.11.2.dist-info/LICENSE,sha256=qQWivZ12ETN5l3QxvTARY-QI5eoRRlyHdwLlAj0Bg5I,1089
152
- pyedb-0.11.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
153
- pyedb-0.11.2.dist-info/METADATA,sha256=0SFV34c7Ruuce3RSxmS8ChPUdCVNsKZyhjja6m_2FXM,8354
154
- pyedb-0.11.2.dist-info/RECORD,,
151
+ pyedb-0.12.1.dist-info/LICENSE,sha256=qQWivZ12ETN5l3QxvTARY-QI5eoRRlyHdwLlAj0Bg5I,1089
152
+ pyedb-0.12.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
153
+ pyedb-0.12.1.dist-info/METADATA,sha256=sofDicuqDqxk_dG81zNz64hW00SYd41gY6FRyviOzpY,8354
154
+ pyedb-0.12.1.dist-info/RECORD,,
File without changes