pyedb 0.34.2__py3-none-any.whl → 0.35.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 CHANGED
@@ -44,7 +44,7 @@ deprecation_warning()
44
44
  #
45
45
 
46
46
  pyedb_path = os.path.dirname(__file__)
47
- __version__ = "0.34.2"
47
+ __version__ = "0.35.0"
48
48
  version = __version__
49
49
 
50
50
  #
@@ -201,7 +201,7 @@ class CfgComponent(CfgBase):
201
201
  if height:
202
202
  port_prop.SetReferenceHeight(self._pedb.edb_value(height))
203
203
  reference_size_auto = self.port_properties.get("reference_size_auto")
204
- if reference_size_auto:
204
+ if reference_size_auto is not None:
205
205
  port_prop.SetReferenceSizeAuto(reference_size_auto)
206
206
  reference_size_x = self.port_properties.get("reference_size_x", 0)
207
207
  reference_size_y = self.port_properties.get("reference_size_y", 0)
@@ -210,10 +210,10 @@ class CfgComponent(CfgBase):
210
210
  self._pyedb_obj.component_property = cp
211
211
 
212
212
  def set_parameters_to_edb(self):
213
- if self.enabled:
214
- self._pyedb_obj.enabled = self.enabled
215
213
  if self.type:
216
214
  self._pyedb_obj.type = self.type
215
+ if self.enabled:
216
+ self._pyedb_obj.enabled = self.enabled
217
217
 
218
218
  self._set_model_properties_to_edb()
219
219
  if self._pyedb_obj.type.lower() == "ic":
@@ -97,6 +97,7 @@ class CfgModeler:
97
97
  for p in self.padstack_instances:
98
98
  p_inst = self._pedb.padstacks.place(
99
99
  via_name=p.name,
100
+ net_name=p.net_name,
100
101
  position=p.position,
101
102
  definition_name=p.definition,
102
103
  )
@@ -124,6 +124,15 @@ class CfgPadstackDefinition(CfgBase):
124
124
  if self.solder_ball_parameters:
125
125
  self._set_solder_parameters_to_edb(self.solder_ball_parameters)
126
126
 
127
+ def retrieve_parameters_from_edb(self):
128
+ self.name = self._pyedb_obj.name
129
+ self.hole_plating_thickness = self._pyedb_obj.hole_plating_thickness
130
+ self.material = self._pyedb_obj.material
131
+ self.hole_range = self._pyedb_obj.hole_range
132
+ self.pad_parameters = self._get_pad_parameters_from_edb()
133
+ self.hole_parameters = self._get_hole_parameters_from_edb()
134
+ self.solder_ball_parameters = self._get_solder_parameters_from_edb()
135
+
127
136
  def _set_solder_parameters_to_edb(self, parameters):
128
137
  pdef_data = self._pyedb_obj._padstack_def_data
129
138
 
@@ -158,15 +167,6 @@ class CfgPadstackDefinition(CfgBase):
158
167
  }
159
168
  return parameters
160
169
 
161
- def retrieve_parameters_from_edb(self):
162
- self.name = self._pyedb_obj.name
163
- self.hole_plating_thickness = self._pyedb_obj.hole_plating_thickness
164
- self.material = self._pyedb_obj.material
165
- self.hole_range = self._pyedb_obj.hole_range
166
- self.pad_parameters = self._get_pad_parameters_from_edb()
167
- self.hole_parameters = self._get_hole_parameters_from_edb()
168
- self.solder_ball_parameters = self._get_solder_parameters_from_edb()
169
-
170
170
  def _get_pad_parameters_from_edb(self):
171
171
  """Pad parameters.
172
172
 
@@ -67,17 +67,16 @@ class CfgPinGroup(CfgBase):
67
67
  def create(self):
68
68
  """Apply pin group on layout."""
69
69
  if self.pins:
70
- self._pedb.siwave.create_pin_group(self.reference_designator, list(self.pins), self.name)
70
+ pins = self.pins if isinstance(self.pins, list) else [self.pins]
71
+ self._pedb.siwave.create_pin_group(self.reference_designator, pins, self.name)
71
72
  elif self.net:
72
- if self.reference_designator in self._pedb.components.instances:
73
- comp = self._pedb.components.instances[self.reference_designator]
74
- else:
75
- raise f"Component not found for creating pin group {self.name}."
76
- pins = [p for p, obj in comp.pins.items() if obj.net_name in self.net]
73
+ nets = self.net if isinstance(self.net, list) else [self.net]
74
+ comp = self._pedb.components.instances[self.reference_designator]
75
+ pins = [p for p, obj in comp.pins.items() if obj.net_name in nets]
77
76
  if not self._pedb.siwave.create_pin_group(self.reference_designator, pins, self.name):
78
- self._pedb.logger.error(f"Failed to create pin group {self.name}")
77
+ raise RuntimeError(f"Failed to create pin group {self.name}")
79
78
  else:
80
- self._pedb.logger.error(f"No net and pins defined for defining pin group {self.name}")
79
+ raise RuntimeError(f"No net and pins defined for defining pin group {self.name}")
81
80
 
82
81
  def export_properties(self):
83
82
  if self.pins:
@@ -265,7 +265,7 @@ class CfgCircuitElement(CfgBase):
265
265
  pins = {pos_value: self._pedb.components.instances[self.reference_designator].pins[pos_value]}
266
266
  pos_objs.update(pins)
267
267
  else:
268
- raise f"Wrong positive terminal type {pos_type}"
268
+ raise Exception(f"Wrong positive terminal type {pos_type}.")
269
269
 
270
270
  self.pos_terminals = {i: j.create_terminal(i) for i, j in pos_objs.items()}
271
271
  self.pos_terminals.update(pos_coor_terminal)
@@ -297,9 +297,12 @@ class CfgCircuitElement(CfgBase):
297
297
  # create pin group
298
298
  neg_obj = self._create_pin_group(pins, True)
299
299
  elif neg_type == "pin":
300
- neg_obj = {neg_value: self._pedb.components.instances[self.reference_designator].pins[neg_value]}
300
+ terminal_name = f"{self.reference_designator}_{neg_value}"
301
+ neg_obj = {
302
+ terminal_name: self._pedb.components.instances[self.reference_designator].pins[neg_value]
303
+ }
301
304
  else:
302
- raise f"Wrong negative terminal type {neg_type}"
305
+ raise Exception(f"Wrong negative terminal type {neg_type}.")
303
306
  self.neg_terminal = [
304
307
  j.create_terminal(i) if not j.terminal else j.terminal for i, j in neg_obj.items()
305
308
  ][0]
@@ -45,6 +45,7 @@ class CfgLayer(CfgBase):
45
45
  self.fill_material = kwargs.get("fill_material", None)
46
46
  self.thickness = kwargs.get("thickness", None)
47
47
  self.roughness = kwargs.get("roughness", None)
48
+ self.etching = kwargs.get("etching", None)
48
49
 
49
50
 
50
51
  class CfgStackup:
@@ -134,13 +134,17 @@ class Configuration:
134
134
 
135
135
  # Configure stackup
136
136
  if kwargs.get("fix_padstack_def"):
137
+ from pyedb.configuration.cfg_padstacks import CfgPadstackDefinition
138
+
137
139
  pedb_defs = self._pedb.padstacks.definitions
138
- temp = {}
139
- for name, pdef in pedb_defs.items():
140
- temp[name] = pdef.get_properties()
140
+ temp = []
141
+ for _, pdef in pedb_defs.items():
142
+ cfg_def = CfgPadstackDefinition(self._pedb, pdef)
143
+ cfg_def.retrieve_parameters_from_edb()
144
+ temp.append(cfg_def)
141
145
  self.cfg_data.stackup.apply()
142
- for name, pdef_p in temp.items():
143
- pedb_defs[name].set_properties(**pdef_p)
146
+ for cfg_pdef in temp:
147
+ cfg_pdef.set_parameters_to_edb()
144
148
  else:
145
149
  self.cfg_data.stackup.apply()
146
150
 
@@ -45,7 +45,7 @@ if is_linux: # pragma: no cover
45
45
 
46
46
  runtime = get_coreclr()
47
47
  load(runtime)
48
- os.environ["DOTNET_ROOT"] = str(runtime.dotnet_root)
48
+ os.environ["DOTNET_ROOT"] = runtime.dotnet_root.as_posix()
49
49
  is_clr = True
50
50
  # TODO: Fall backing to dotnetcore2 should be removed in a near future.
51
51
  except Exception:
@@ -83,7 +83,7 @@ if is_linux: # pragma: no cover
83
83
  if dotnet_root is not None and runtime_config is not None:
84
84
  try:
85
85
  load("coreclr", runtime_config=str(runtime_config), dotnet_root=str(dotnet_root))
86
- os.environ["DOTNET_ROOT"] = dotnet_root
86
+ os.environ["DOTNET_ROOT"] = dotnet_root.as_posix()
87
87
  if "mono" not in os.getenv("LD_LIBRARY_PATH", ""):
88
88
  warnings.warn("LD_LIBRARY_PATH needs to be setup to use pyedb.")
89
89
  warnings.warn("export ANSYSEM_ROOT242=/path/to/AnsysEM/v242/Linux64")
pyedb/dotnet/edb.py CHANGED
@@ -4564,6 +4564,7 @@ class Edb(Database):
4564
4564
  port_poly = cloned_edb.modeler.create_polygon(
4565
4565
  main_shape=void_info[0].polygon_data._edb_object, layer_name="ref", net_name="GND"
4566
4566
  )
4567
+ port_poly.scale(1.1)
4567
4568
  pec_poly = cloned_edb.modeler.create_polygon(
4568
4569
  main_shape=port_poly.polygon_data._edb_object, layer_name="port_pec", net_name="GND"
4569
4570
  )
@@ -66,7 +66,7 @@ class PinPair(object): # pragma: no cover
66
66
  @resistance.setter
67
67
  def resistance(self, value):
68
68
  self._pin_pair_rlc.R = value
69
- self._set_comp_prop(self._pin_pair_rlc) # pragma: no cover
69
+ self._set_comp_prop() # pragma: no cover
70
70
 
71
71
  @property
72
72
  def inductance(self):
@@ -75,7 +75,7 @@ class PinPair(object): # pragma: no cover
75
75
  @inductance.setter
76
76
  def inductance(self, value):
77
77
  self._pin_pair_rlc.L = value
78
- self._set_comp_prop(self._pin_pair_rlc) # pragma: no cover
78
+ self._set_comp_prop() # pragma: no cover
79
79
 
80
80
  @property
81
81
  def capacitance(self):
@@ -84,7 +84,7 @@ class PinPair(object): # pragma: no cover
84
84
  @capacitance.setter
85
85
  def capacitance(self, value):
86
86
  self._pin_pair_rlc.C = value
87
- self._set_comp_prop(self._pin_pair_rlc) # pragma: no cover
87
+ self._set_comp_prop() # pragma: no cover
88
88
 
89
89
  @property
90
90
  def rlc_values(self): # pragma: no cover
@@ -101,3 +101,15 @@ class PadstackInstanceTerminal(Terminal):
101
101
  def padstack_instance(self):
102
102
  p_inst, _ = self._get_parameters()
103
103
  return self._pedb.layout.find_object_by_id(p_inst.GetId())
104
+
105
+ @property
106
+ def layer(self):
107
+ """Get layer of the terminal."""
108
+ _, _, layer = self._edb_object.GetParameters()
109
+ return self._pedb.stackup.all_layers[layer.GetName()]
110
+
111
+ @layer.setter
112
+ def layer(self, value):
113
+ layer = self._pedb.stackup.layers[value]._edb_layer
114
+ point_data = self._pedb.point_data(*self.location)
115
+ self._edb_object.SetParameters(point_data, layer)
@@ -66,3 +66,15 @@ class PointTerminal(Terminal):
66
66
  raise Exception(msg)
67
67
  else:
68
68
  return terminal
69
+
70
+ @property
71
+ def layer(self):
72
+ """Get layer of the terminal."""
73
+ _, _, layer = self._edb_object.GetParameters()
74
+ return self._pedb.stackup.all_layers[layer.GetName()]
75
+
76
+ @layer.setter
77
+ def layer(self, value):
78
+ layer = self._pedb.stackup.layers[value]._edb_layer
79
+ point_data = self._pedb.point_data(*self.location)
80
+ self._edb_object.SetParameters(point_data, layer)
@@ -105,25 +105,16 @@ class Terminal(Connectable):
105
105
  @property
106
106
  def layer(self):
107
107
  """Get layer of the terminal."""
108
- point_data = self._pedb.point_data(0, 0)
109
- layer = list(self._pedb.stackup.layers.values())[0]._edb_layer
110
- if self._edb_object.GetParameters(point_data, layer):
111
- return self._pedb.stackup.all_layers[layer.GetName()]
112
- else:
113
- self._pedb.logger.warning(f"No pad parameters found for terminal {self.name}")
114
-
115
- @layer.setter
116
- def layer(self, value):
117
- layer = self._pedb.stackup.layers[value]._edb_layer
118
- point_data = self._pedb.point_data(*self.location)
119
- self._edb_object.SetParameters(point_data, layer)
108
+ return self._pedb.logger.error("Cannot determine terminal layer")
120
109
 
121
110
  @property
122
111
  def location(self):
123
112
  """Location of the terminal."""
124
- layer = list(self._pedb.stackup.layers.values())[0]._edb_layer
125
- _, point_data, _ = self._edb_object.GetParameters(None, layer)
126
- return [point_data.X.ToDouble(), point_data.Y.ToDouble()]
113
+ try:
114
+ _, point_data, _ = self._edb_object.GetParameters()
115
+ return [point_data.X.ToDouble(), point_data.Y.ToDouble()]
116
+ except:
117
+ self._pedb.logger.error("Cannot determine terminal location")
127
118
 
128
119
  @location.setter
129
120
  def location(self, value):
@@ -111,16 +111,9 @@ class Components(object):
111
111
 
112
112
  def __init__(self, p_edb):
113
113
  self._pedb = p_edb
114
- self._cmp = {}
115
- self._res = {}
116
- self._cap = {}
117
- self._ind = {}
118
- self._ios = {}
119
- self._ics = {}
120
- self._others = {}
114
+ self.refresh_components()
121
115
  self._pins = {}
122
116
  self._comps_by_part = {}
123
- self._init_parts()
124
117
  self._padstack = EdbPadstacks(self._pedb)
125
118
 
126
119
  @property
@@ -132,16 +125,6 @@ class Components(object):
132
125
  def _edb(self):
133
126
  return self._pedb.edb_api
134
127
 
135
- def _init_parts(self):
136
- a = self.instances
137
- a = self.resistors
138
- a = self.ICs
139
- a = self.Others
140
- a = self.inductors
141
- a = self.IOs
142
- a = self.components_by_partname
143
- return True
144
-
145
128
  def _get_edb_value(self, value):
146
129
  return self._pedb.edb_value(value)
147
130
 
@@ -205,8 +188,6 @@ class Components(object):
205
188
  >>> edbapp.components.instances
206
189
 
207
190
  """
208
- if not self._cmp:
209
- self.refresh_components()
210
191
  return self._cmp
211
192
 
212
193
  @property
@@ -310,10 +291,29 @@ class Components(object):
310
291
 
311
292
  def refresh_components(self):
312
293
  """Refresh the component dictionary."""
313
- # self._logger.info("Refreshing the Components dictionary.")
314
294
  self._cmp = {}
295
+ self._res = {}
296
+ self._ind = {}
297
+ self._cap = {}
298
+ self._ics = {}
299
+ self._ios = {}
300
+ self._others = {}
315
301
  for i in self._pedb.layout.groups:
316
302
  self._cmp[i.name] = i
303
+ if i.type == "Resistor":
304
+ self._res[i.name] = i
305
+ elif i.type == "Capacitor":
306
+ self._cap[i.name] = i
307
+ elif i.type == "Inductor":
308
+ self._ind[i.name] = i
309
+ elif i.type == "IC":
310
+ self._ics[i.name] = i
311
+ elif i.type == "IO":
312
+ self._ios[i.name] = i
313
+ elif i.type == "Other":
314
+ self._others[i.name] = i
315
+ else:
316
+ self._logger.warning(f"Unknown component type {i.name} found while refreshing components, will ignore")
317
317
  return True
318
318
 
319
319
  @property
@@ -332,10 +332,6 @@ class Components(object):
332
332
  >>> edbapp = Edb("myaedbfolder")
333
333
  >>> edbapp.components.resistors
334
334
  """
335
- self._res = {}
336
- for el, val in self.instances.items():
337
- if val.type == "Resistor":
338
- self._res[el] = val
339
335
  return self._res
340
336
 
341
337
  @property
@@ -354,10 +350,6 @@ class Components(object):
354
350
  >>> edbapp = Edb("myaedbfolder")
355
351
  >>> edbapp.components.capacitors
356
352
  """
357
- self._cap = {}
358
- for el, val in self.instances.items():
359
- if val.type == "Capacitor":
360
- self._cap[el] = val
361
353
  return self._cap
362
354
 
363
355
  @property
@@ -377,10 +369,6 @@ class Components(object):
377
369
  >>> edbapp.components.inductors
378
370
 
379
371
  """
380
- self._ind = {}
381
- for el, val in self.instances.items():
382
- if val.type == "Inductor":
383
- self._ind[el] = val
384
372
  return self._ind
385
373
 
386
374
  @property
@@ -400,10 +388,6 @@ class Components(object):
400
388
  >>> edbapp.components.ICs
401
389
 
402
390
  """
403
- self._ics = {}
404
- for el, val in self.instances.items():
405
- if val.type == "IC":
406
- self._ics[el] = val
407
391
  return self._ics
408
392
 
409
393
  @property
@@ -423,10 +407,6 @@ class Components(object):
423
407
  >>> edbapp.components.IOs
424
408
 
425
409
  """
426
- self._ios = {}
427
- for el, val in self.instances.items():
428
- if val.type == "IO":
429
- self._ios[el] = val
430
410
  return self._ios
431
411
 
432
412
  @property
@@ -446,10 +426,6 @@ class Components(object):
446
426
  >>> edbapp.components.others
447
427
 
448
428
  """
449
- self._others = {}
450
- for el, val in self.instances.items():
451
- if val.type == "Other":
452
- self._others[el] = val
453
429
  return self._others
454
430
 
455
431
  @property
@@ -60,6 +60,8 @@ class LayerEdbClass(object):
60
60
  self.__setattr__(k, v)
61
61
  elif k == "roughness":
62
62
  self.properties = {"roughness": v}
63
+ elif k == "etching":
64
+ self.properties = {"etching": v}
63
65
  else:
64
66
  self._pedb.logger.error(f"{k} is not a valid layer attribute")
65
67
 
@@ -792,6 +794,15 @@ class StackupLayerEdbClass(LayerEdbClass):
792
794
  data["thickness"] = self._edb_object.GetThicknessValue().ToString()
793
795
  data["color"] = self.color
794
796
 
797
+ data["etching"] = {
798
+ "factor": self._edb_layer.GetEtchFactor().ToString(),
799
+ "enabled": self._edb_layer.IsEtchFactorEnabled(),
800
+ }
801
+ if self._pedb.edbversion >= "2024.2":
802
+ etch_power_ground_nets = int(self._edb_layer.GetEtchNetClass())
803
+ etch_power_ground_nets = False if etch_power_ground_nets else True
804
+ data["etching"]["etch_power_ground_nets"] = etch_power_ground_nets
805
+
795
806
  roughness = {}
796
807
  for region in ["top", "bottom", "side"]:
797
808
  temp = {}
@@ -851,5 +862,14 @@ class StackupLayerEdbClass(LayerEdbClass):
851
862
  getattr(self._pedb._edb.Cell.RoughnessModel.Region, region.capitalize()), r_model
852
863
  )
853
864
  self._pedb.stackup._set_layout_stackup(layer_clone, "change_attribute")
854
-
855
- layer_clone.SetRoughnessEnabled(True)
865
+ etching = params.get("etching")
866
+ if etching:
867
+ layer_clone = self._edb_layer
868
+ layer_clone.SetEtchFactorEnabled(etching["enabled"])
869
+ layer_clone.SetEtchFactor(self._pedb.stackup._edb_value(float(etching["factor"])))
870
+ if self._pedb.edbversion >= "2024.2":
871
+ if etching["etch_power_ground_nets"]:
872
+ layer_clone.SetEtchNetClass(self._pedb._edb.Cell.EtchNetClass.NoEtchPowerGroundNets)
873
+ else:
874
+ layer_clone.SetEtchNetClass(self._pedb._edb.Cell.EtchNetClass.EtchAllNets)
875
+ self._pedb.stackup._set_layout_stackup(layer_clone, "change_attribute")
@@ -272,7 +272,7 @@ class LayoutValidation:
272
272
  bool
273
273
  """
274
274
  if not net_list:
275
- net_list = list(self._pedb.nets.keys())
275
+ net_list = list(self._pedb.nets.nets.keys())
276
276
  elif isinstance(net_list, str):
277
277
  net_list = [net_list]
278
278
  new_prims = []
@@ -26,7 +26,9 @@ This module contains the `EdbPadstacks` class.
26
26
  import math
27
27
  import warnings
28
28
 
29
+ import numpy as np
29
30
  import rtree
31
+ from scipy.spatial import ConvexHull
30
32
 
31
33
  from pyedb.dotnet.clr_module import Array
32
34
  from pyedb.dotnet.edb_core.edb_data.padstacks_data import (
@@ -1553,7 +1555,7 @@ class EdbPadstacks(object):
1553
1555
  padstack_instances_index.insert(inst.id, inst.position)
1554
1556
  return padstack_instances_index
1555
1557
 
1556
- def get_padstack_instances_intersecting_bounding_box(self, bounding_box, nets=None):
1558
+ def get_padstack_instances_id_intersecting_polygon(self, points, nets=None, padstack_instances_index=None):
1557
1559
  """Returns the list of padstack instances ID intersecting a given bounding box and nets.
1558
1560
 
1559
1561
  Parameters
@@ -1563,6 +1565,38 @@ class EdbPadstacks(object):
1563
1565
  nets : str or list, optional
1564
1566
  net name of list of nets name applying filtering on padstack instances selection. If ``None`` is provided
1565
1567
  all instances are included in the index. Default value is ``None``.
1568
+ padstack_instances_index : optional, Rtree object.
1569
+ Can be provided optionally to prevent computing padstack instances Rtree index again.
1570
+
1571
+ Returns
1572
+ -------
1573
+ List of padstack instances ID intersecting the bounding box.
1574
+ """
1575
+ if not points:
1576
+ raise Exception("No points defining polygon was provided")
1577
+ if not padstack_instances_index:
1578
+ padstack_instances_index = {}
1579
+ for inst in self.instances:
1580
+ padstack_instances_index[inst.id] = inst.position
1581
+ _x = [pt[0] for pt in points]
1582
+ _y = [pt[1] for pt in points]
1583
+ points = [_x, _y]
1584
+ return [
1585
+ ind for ind, pt in padstack_instances_index.items() if GeometryOperators.is_point_in_polygon(pt, points)
1586
+ ]
1587
+
1588
+ def get_padstack_instances_intersecting_bounding_box(self, bounding_box, nets=None, padstack_instances_index=None):
1589
+ """Returns the list of padstack instances ID intersecting a given bounding box and nets.
1590
+
1591
+ Parameters
1592
+ ----------
1593
+ bounding_box : tuple or list.
1594
+ bounding box, [x1, y1, x2, y2]
1595
+ nets : str or list, optional
1596
+ net name of list of nets name applying filtering on padstack instances selection. If ``None`` is provided
1597
+ all instances are included in the index. Default value is ``None``.
1598
+ padstack_instances_index : optional, Rtree object.
1599
+ Can be provided optionally to prevent computing padstack instances Rtree index again.
1566
1600
 
1567
1601
  Returns
1568
1602
  -------
@@ -1570,15 +1604,104 @@ class EdbPadstacks(object):
1570
1604
  """
1571
1605
  if not bounding_box:
1572
1606
  raise Exception("No bounding box was provided")
1573
- index = self.get_padstack_instances_rtree_index(nets=nets)
1607
+ if not padstack_instances_index:
1608
+ index = self.get_padstack_instances_rtree_index(nets=nets)
1609
+ else:
1610
+ index = padstack_instances_index
1574
1611
  if not len(bounding_box) == 4:
1575
1612
  raise Exception("The bounding box length must be equal to 4")
1576
1613
  if isinstance(bounding_box, list):
1577
1614
  bounding_box = tuple(bounding_box)
1578
1615
  return list(index.intersection(bounding_box))
1579
1616
 
1617
+ def merge_via(self, contour_boxes, net_filter=None, start_layer=None, stop_layer=None):
1618
+ """Evaluate padstack instances included on the provided point list and replace all by single instance.
1619
+
1620
+ Parameters
1621
+ ----------
1622
+ contour_boxes : List[List[List[float, float]]]
1623
+ Nested list of polygon with points [x,y].
1624
+ net_filter : optional
1625
+ List[str: net_name] apply a net filter, nets included in the filter are excluded from the via merge.
1626
+ start_layer : optional, str
1627
+ Padstack instance start layer, if `None` the top layer is selected.
1628
+ stop_layer : optional, str
1629
+ Padstack instance stop layer, if `None` the bottom layer is selected.
1630
+
1631
+ Return
1632
+ ------
1633
+ List[str], list of created padstack instances ID.
1634
+
1635
+ """
1636
+ merged_via_ids = []
1637
+ if not contour_boxes:
1638
+ raise Exception("No contour box provided, you need to pass a nested list as argument.")
1639
+ if not start_layer:
1640
+ start_layer = list(self._pedb.stackup.layers.values())[0].name
1641
+ if not stop_layer:
1642
+ stop_layer = list(self._pedb.stackup.layers.values())[-1].name
1643
+ instances_index = {}
1644
+ for id, inst in self.instances.items():
1645
+ instances_index[id] = inst.position
1646
+ for contour_box in contour_boxes:
1647
+ instances = self.get_padstack_instances_id_intersecting_polygon(
1648
+ points=contour_box, padstack_instances_index=instances_index
1649
+ )
1650
+ if not instances:
1651
+ raise Exception(f"No padstack instances found inside {contour_box}")
1652
+ else:
1653
+ if net_filter:
1654
+ instances = [id for id in instances if not self.instances[id].net_name in net_filter]
1655
+
1656
+ net = self.instances[instances[0]].net_name
1657
+ x_values = []
1658
+ y_values = []
1659
+ for inst in instances:
1660
+ pos = instances_index[inst]
1661
+ x_values.append(pos[0])
1662
+ y_values.append(pos[1])
1663
+ x_values = list(set(x_values))
1664
+ y_values = list(set(y_values))
1665
+ if len(x_values) == 1 or len(y_values) == 1:
1666
+ create_instances = self.merge_via_along_lines(
1667
+ net_name=net, padstack_instances_id=instances, minimum_via_number=2
1668
+ )
1669
+ merged_via_ids.extend(create_instances)
1670
+ else:
1671
+ instances_pts = np.array([instances_index[id] for id in instances])
1672
+ convex_hull_contour = ConvexHull(instances_pts)
1673
+ contour_points = list(instances_pts[convex_hull_contour.vertices])
1674
+ layer = list(self._pedb.stackup.layers.values())[0].name
1675
+ polygon = self._pedb.modeler.create_polygon(main_shape=contour_points, layer_name=layer)
1676
+ polygon_data = polygon.polygon_data
1677
+ polygon.delete()
1678
+ new_padstack_def = generate_unique_name(self.instances[instances[0]].definition.name)
1679
+ if not self.create(
1680
+ padstackname=new_padstack_def,
1681
+ pad_shape="Polygon",
1682
+ antipad_shape="Polygon",
1683
+ pad_polygon=polygon_data,
1684
+ antipad_polygon=polygon_data,
1685
+ polygon_hole=polygon_data,
1686
+ start_layer=start_layer,
1687
+ stop_layer=stop_layer,
1688
+ ):
1689
+ raise Exception(f"Failed to create padstack definition {new_padstack_def}")
1690
+ merged_instance = self.place(position=[0, 0], definition_name=new_padstack_def, net_name=net)
1691
+ merged_instance.start_layer = start_layer
1692
+ merged_instance.stop_layer = stop_layer
1693
+
1694
+ merged_via_ids.append(merged_instance.id)
1695
+ [self.instances[id].delete() for id in instances]
1696
+ return merged_via_ids
1697
+
1580
1698
  def merge_via_along_lines(
1581
- self, net_name="GND", distance_threshold=5e-3, minimum_via_number=6, selected_angles=None
1699
+ self,
1700
+ net_name="GND",
1701
+ distance_threshold=5e-3,
1702
+ minimum_via_number=6,
1703
+ selected_angles=None,
1704
+ padstack_instances_id=None,
1582
1705
  ):
1583
1706
  """Replace padstack instances along lines into a single polygon.
1584
1707
 
@@ -1602,11 +1725,15 @@ class EdbPadstacks(object):
1602
1725
  Specify angle in degrees to detected, for instance [0, 180] is only detecting horizontal and vertical lines.
1603
1726
  Other values can be assigned like 45 degrees. When `None` is provided all lines are detected. Default value
1604
1727
  is `None`.
1728
+ padstack_instances_id : List[int]
1729
+ List of padstack instances ID's to include. If `None`, the algorithm will scan all padstack instances belonging
1730
+ to the specified net. Default value is `None`.
1731
+
1605
1732
 
1606
1733
  Returns
1607
1734
  -------
1608
1735
  bool
1609
- ``True`` when succeeded ``False`` when failed. <
1736
+ List[int], list of created padstack instances id.
1610
1737
 
1611
1738
  """
1612
1739
  _def = list(
@@ -1615,12 +1742,16 @@ class EdbPadstacks(object):
1615
1742
  if not _def:
1616
1743
  self._logger.error(f"No padstack definition found for net {net_name}")
1617
1744
  return False
1745
+ instances_created = []
1618
1746
  _instances_to_delete = []
1619
1747
  padstack_instances = []
1620
- for pdstk_def in _def:
1621
- padstack_instances.append(
1622
- [inst for inst in self.definitions[pdstk_def].instances if inst.net_name == net_name]
1623
- )
1748
+ if padstack_instances_id:
1749
+ padstack_instances = [[self.instances[id] for id in padstack_instances_id]]
1750
+ else:
1751
+ for pdstk_def in _def:
1752
+ padstack_instances.append(
1753
+ [inst for inst in self.definitions[pdstk_def].instances if inst.net_name == net_name]
1754
+ )
1624
1755
  for pdstk_series in padstack_instances:
1625
1756
  instances_location = [inst.position for inst in pdstk_series]
1626
1757
  lines, line_indexes = GeometryOperators.find_points_along_lines(
@@ -1652,8 +1783,65 @@ class EdbPadstacks(object):
1652
1783
  polygon_hole=polygon_data,
1653
1784
  ):
1654
1785
  self._logger.error(f"Failed to create padstack definition {new_padstack_def}")
1655
- if not self.place(position=[0, 0], definition_name=new_padstack_def, net_name=net_name):
1786
+ new_instance = self.place(position=[0, 0], definition_name=new_padstack_def, net_name=net_name)
1787
+ if not new_instance:
1656
1788
  self._logger.error(f"Failed to place padstack instance {new_padstack_def}")
1789
+ else:
1790
+ instances_created.append(new_instance.id)
1657
1791
  for inst in _instances_to_delete:
1658
1792
  inst.delete()
1659
- return True
1793
+ return instances_created
1794
+
1795
+ def reduce_via_in_bounding_box(self, bounding_box, x_samples, y_samples, nets=None):
1796
+ """
1797
+ reduce the number of vias intersecting bounding box and nets by x and y samples.
1798
+
1799
+ Parameters
1800
+ ----------
1801
+ bounding_box : tuple or list.
1802
+ bounding box, [x1, y1, x2, y2]
1803
+ x_samples : int
1804
+ y_samples : int
1805
+ nets : str or list, optional
1806
+ net name of list of nets name applying filtering on padstack instances selection. If ``None`` is provided
1807
+ all instances are included in the index. Default value is ``None``.
1808
+
1809
+ Returns
1810
+ -------
1811
+ bool
1812
+ ``True`` when succeeded ``False`` when failed. <
1813
+ """
1814
+
1815
+ padstacks_inbox = self.get_padstack_instances_intersecting_bounding_box(bounding_box, nets)
1816
+ if not padstacks_inbox:
1817
+ self._logger.info("no padstack in bounding box")
1818
+ return False
1819
+ else:
1820
+ if len(padstacks_inbox) <= (x_samples * y_samples):
1821
+ self._logger.info(f"more samples {x_samples * y_samples} than existing {len(padstacks_inbox)}")
1822
+ return False
1823
+ else:
1824
+ # extract ids and positions
1825
+ vias = {item: self.instances[item].position for item in padstacks_inbox}
1826
+ ids, positions = zip(*vias.items())
1827
+ pt_x, pt_y = zip(*positions)
1828
+
1829
+ # meshgrid
1830
+ _x_min, _x_max = min(pt_x), max(pt_x)
1831
+ _y_min, _y_max = min(pt_y), max(pt_y)
1832
+
1833
+ x_grid, y_grid = np.meshgrid(
1834
+ np.linspace(_x_min, _x_max, x_samples), np.linspace(_y_min, _y_max, y_samples)
1835
+ )
1836
+
1837
+ # mapping to meshgrid
1838
+ to_keep = {
1839
+ ids[np.argmin(np.square(_x - pt_x) + np.square(_y - pt_y))]
1840
+ for _x, _y in zip(x_grid.ravel(), y_grid.ravel())
1841
+ }
1842
+
1843
+ for item in padstacks_inbox:
1844
+ if item not in to_keep:
1845
+ self.instances[item].delete()
1846
+
1847
+ return True
@@ -1242,8 +1242,7 @@ class EdbSiwave(object):
1242
1242
  )
1243
1243
 
1244
1244
  if edb_pingroup.IsNull(): # pragma: no cover
1245
- self._logger.error(f"Failed to create pin group {group_name}.")
1246
- return False
1245
+ raise RuntimeError(f"Failed to create pin group {group_name}.")
1247
1246
  else:
1248
1247
  names = [i for i in pins if i.GetNet().GetName()]
1249
1248
  edb_pingroup.SetNet(names[0].GetNet())
pyedb/generic/process.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os.path
2
2
  import subprocess
3
3
 
4
- from pyedb.generic.general_methods import env_path, is_linux
4
+ from pyedb.generic.general_methods import env_path, is_linux, is_windows
5
5
 
6
6
 
7
7
  class SiwaveSolve(object):
@@ -144,19 +144,19 @@ class SiwaveSolve(object):
144
144
  f.write("oDoc.ScrExport3DModel('{}', q3d_filename)\n".format(format_3d))
145
145
  f.write("oDoc.ScrCloseProject()\n")
146
146
  f.write("oApp.Quit()\n")
147
- if is_linux:
148
- _exe = '"' + os.path.join(self.installer_path, "siwave") + '"'
149
- else:
150
- _exe = '"' + os.path.join(self.installer_path, "siwave.exe") + '"'
147
+ _exe = os.path.join(self.installer_path, "siwave")
148
+ if is_windows:
149
+ _exe += ".exe"
151
150
  command = [_exe]
152
151
  if hidden:
153
152
  command.append("-embedding")
154
- command.append("-RunScriptAndExit")
155
- command.append(scriptname)
153
+ command += ["-RunScriptAndExit", scriptname]
156
154
  print(command)
157
- os.system(" ".join(command))
158
- # p1 = subprocess.call(" ".join(command))
159
- # p1.wait()
155
+ try:
156
+ result = subprocess.run(command, check=True, capture_output=True)
157
+ print(result.stdout.decode())
158
+ except subprocess.CalledProcessError as e:
159
+ print(f"Error occurred: {e.stderr.decode()}")
160
160
  return os.path.join(output_folder, aedt_file_name)
161
161
 
162
162
  def export_dc_report(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyedb
3
- Version: 0.34.2
3
+ Version: 0.35.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>
@@ -21,13 +21,13 @@ Requires-Dist: ansys-pythonnet >= 3.1.0rc4
21
21
  Requires-Dist: dotnetcore2 ==3.1.23;platform_system=='Linux'
22
22
  Requires-Dist: numpy>=1.20.0,<3
23
23
  Requires-Dist: pandas>=1.1.0,<2.3
24
- Requires-Dist: pydantic>=2.6.4,<2.10
24
+ Requires-Dist: pydantic>=2.6.4,<2.11
25
25
  Requires-Dist: Rtree >= 1.2.0
26
26
  Requires-Dist: toml == 0.10.2
27
27
  Requires-Dist: scikit-rf
28
28
  Requires-Dist: ansys-sphinx-theme>=0.10.0,<1.1 ; extra == "doc"
29
29
  Requires-Dist: imageio>=2.30.0,<2.37 ; extra == "doc"
30
- Requires-Dist: ipython>=8.13.0,<8.31 ; extra == "doc"
30
+ Requires-Dist: ipython>=8.13.0,<8.32 ; extra == "doc"
31
31
  Requires-Dist: jupyterlab>=4.0.0,<4.4 ; extra == "doc"
32
32
  Requires-Dist: jupytext>=1.16.0,<1.17 ; extra == "doc"
33
33
  Requires-Dist: matplotlib>=3.5.0,<3.10 ; extra == "doc"
@@ -76,7 +76,7 @@ Provides-Extra: tests
76
76
 
77
77
  ## What is PyEDB?
78
78
 
79
- PyEDB is Python client library for processing complex and large layout designs in the
79
+ PyEDB is a Python client library for processing complex and large layout designs in the
80
80
  Ansys Electronics Database (EDB) format, which stores information describing designs for
81
81
  [Ansys Electronics Desktop](https://www.ansys.com/products/electronics) (AEDT).
82
82
 
@@ -102,7 +102,7 @@ HFSS 3D Layout, Icepak, Maxwell, Q3D, and SIwave.
102
102
 
103
103
  EDB provides a proprietary database file format (AEDB) for efficient and fast layout design
104
104
  handling and processing for building ready-to-solve projects. EDB addresses signal integrity
105
- (SI), power integrity (PI-DC), and electro-thermal work flows. You can import an AEDB file
105
+ (SI), power integrity (PI-DC), and electro-thermal workflows. You can import an AEDB file
106
106
  into AEDT to modify the layout, assign materials, and define ports, simulations, and constraints.
107
107
  You can then launch any of the Ansys electromagnetic simulators.
108
108
 
@@ -112,7 +112,7 @@ memory, it provides the fastest and most efficient way to handle a large and com
112
112
 
113
113
  You can also parse an AEDB file from a command line in batch in an Ansys electromagnetic simulator
114
114
  like HFSS or SIwave. Thus, you can deploy completely non-graphical flows, from layout
115
- translation through simulatiom results.
115
+ translation through simulation results.
116
116
 
117
117
  Additionally, you can use PyAEDT to import an AEDB file into AEDT to view a project,
118
118
  combine 3D designs, or perform simulation postprocessing. EDB also supports 3D component models.
@@ -1,4 +1,4 @@
1
- pyedb/__init__.py,sha256=ZDatOkcJCppw0vyJACYczRa-_Dy0Zv-eH-3iWU9B7S0,1525
1
+ pyedb/__init__.py,sha256=QJGYOhTvr2BmugtK2s-wdaTRzp_3L2rc1RWwDKYu0yU,1525
2
2
  pyedb/edb_logger.py,sha256=7KXPvAMCKzlzJ5zioiNO5A3zkqbpCHhWHB4aXKfgu5Y,14959
3
3
  pyedb/exceptions.py,sha256=n94xluzUks6BA24vd_L6HkrvoP_H_l6__hQmqzdCyPo,111
4
4
  pyedb/siwave.py,sha256=Mgg5ZGzOUOtNdlePHcnrgN3rletQ7jrqRi3WfxF58uU,17727
@@ -9,38 +9,38 @@ pyedb/component_libraries/ansys_components.py,sha256=O3ypt832IHY9zG2AD_yrRrbH2KH
9
9
  pyedb/configuration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  pyedb/configuration/cfg_boundaries.py,sha256=5_v6HD0VgkFCJHgx5zTIn_nxPv3KpcCuGz9P4Kk4ywM,6246
11
11
  pyedb/configuration/cfg_common.py,sha256=feXGIBSlTPAewSsmu0m1SgyfF9DuK4C7SNP_RNQGD2A,2549
12
- pyedb/configuration/cfg_components.py,sha256=33XrTkyMvSgo1dFo15ChRXywwLnzprCxKG7yp9msVUA,12388
12
+ pyedb/configuration/cfg_components.py,sha256=E-gPe2XYry5C3kjjjqOzRfAG2UsBJfwbApNSgW_pIJs,12400
13
13
  pyedb/configuration/cfg_data.py,sha256=qCCR-Oo5_le61qWWmjrK4gIt_HH9jVqu4K0GbekAJkU,3773
14
14
  pyedb/configuration/cfg_general.py,sha256=DJAKTW8Sqojfqzc3jO3MU1-J8MrmVi37jUIkTD_Tw6o,2068
15
- pyedb/configuration/cfg_modeler.py,sha256=tgeTs-if1d_vQvnGzD6qqMGnJlqqG302APHUu0b5jtE,5889
15
+ pyedb/configuration/cfg_modeler.py,sha256=gXjc_thxa_sFiZ-b1zJCS8f6piCoM0d8In6MD26ZFZo,5930
16
16
  pyedb/configuration/cfg_nets.py,sha256=18NezeNh0ZOwk2ehz3zWJF_xYR7IYCqGlpDfDt7Ilho,2349
17
17
  pyedb/configuration/cfg_operations.py,sha256=CFLBdM2kQBsW6f7W0NHWbV56RDMHSnaNQl3BmqDWQWo,4707
18
18
  pyedb/configuration/cfg_package_definition.py,sha256=f_RRT9R-3H5kHBlc4QSpjq9uQgYbaKQ78XXXrc_r3kg,5296
19
- pyedb/configuration/cfg_padstacks.py,sha256=sjVlUDO-Jyl9VheCx2TM9lNEt971a1G8DUAtb-INUWo,18292
20
- pyedb/configuration/cfg_pin_groups.py,sha256=b0H6NaPKJ5zlcXL9W2Q8_HbiLB8-OxaqjsM4wlqP2ic,3768
21
- pyedb/configuration/cfg_ports_sources.py,sha256=t2LvKswLF4iohCIjj-tAoveiVQ_8R4G-QIK1XuSt8xs,20791
19
+ pyedb/configuration/cfg_padstacks.py,sha256=zZSEc92TwSqa7KSZBmDb4Sybm4ivM5lrvb8uMxFho8k,18292
20
+ pyedb/configuration/cfg_pin_groups.py,sha256=zNKfVP-fd1qUxS2wNb0ZTLGonkUnBmiXb4Rss1Rr7sE,3714
21
+ pyedb/configuration/cfg_ports_sources.py,sha256=p6pauq8r14N4whuzxirSkKTS2lu4ViRMxB0KbIcBj5c,20944
22
22
  pyedb/configuration/cfg_s_parameter_models.py,sha256=DgBprcEYR2r_3BY4f_CuwuhJw_QFEag3xaAlLTRfMuE,5356
23
23
  pyedb/configuration/cfg_setup.py,sha256=QGKQHAEeo196TYtKMvIMb2-p8KC4U8fmHx0yn0SpgMo,10351
24
24
  pyedb/configuration/cfg_spice_models.py,sha256=Q_5j2-V6cepSFcnijot8iypTqzanLp7HOz-agmnwKns,2570
25
- pyedb/configuration/cfg_stackup.py,sha256=ZKUcTh4UAFLJgES2W-5J7uXkUdz_q0URg28lUZUyfdo,6433
26
- pyedb/configuration/configuration.py,sha256=MnoO5H5VZSogQSZ3MUJqWiO3DB-_QUYOfM4qROTHcnY,15470
25
+ pyedb/configuration/cfg_stackup.py,sha256=Ie2mdHfCgPn3F7BSdLlYZoZ3exhCDgPrhlYwxHZ6ABU,6484
26
+ pyedb/configuration/configuration.py,sha256=kQvUa9pkrdIw5gZE6RlaVdQOiioH0T0JkqUzb8fvdnU,15635
27
27
  pyedb/dotnet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- pyedb/dotnet/clr_module.py,sha256=V8S_WV_XxjaJOf_XYBZ8i9GDnsF33ItYrXQAtgV0CBY,5287
29
- pyedb/dotnet/edb.py,sha256=Ut1lpxs_YwagTRjcmrANr8xyIOVu-BzedW_YtU6kIcU,186395
28
+ pyedb/dotnet/clr_module.py,sha256=EabqZgZgBZOhJD9_V8Ll8sEKgBFj9xe9zARNYIvYM_s,5304
29
+ pyedb/dotnet/edb.py,sha256=vl2Jbwq55eI3vdSq9Je-iklZBhnb7ccKC806s67kSrE,186428
30
30
  pyedb/dotnet/application/Variables.py,sha256=awNhyiLASBYrNjWIyW8IJowgqt7FfFPKF9UElRWyjZg,77750
31
31
  pyedb/dotnet/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  pyedb/dotnet/edb_core/__init__.py,sha256=nIRLJ8VZLcMAp12zmGsnZ5x2BEEl7q_Kj_KAOXxVjpQ,52
33
- pyedb/dotnet/edb_core/components.py,sha256=r8Gr9mV4Cuky7lVKOg-JWhRR2bflGYESsnOGG2g4BwM,111146
33
+ pyedb/dotnet/edb_core/components.py,sha256=qfMw7vRtw5n1KhYKrUIvZaoyJwV_yNyJBX6aYz_M6og,110487
34
34
  pyedb/dotnet/edb_core/general.py,sha256=k2Bcr5VV-QUzEZlYorqYCX1ZchHBH7WqUvc8maMxId0,4716
35
35
  pyedb/dotnet/edb_core/hfss.py,sha256=oQFC6PwRbjAwfR60RoklwpZ_2sDI4OheNNdwaqY23ok,68671
36
36
  pyedb/dotnet/edb_core/layout_obj_instance.py,sha256=Pd8rfdO3b6HLFGwXBMw-tfE4LPIcW_9_X5KEdFaiito,1407
37
- pyedb/dotnet/edb_core/layout_validation.py,sha256=JBaLnEgDv2GrX8GD0D4_3zT8EWLSMmXu5F2AhW7oGuU,13592
37
+ pyedb/dotnet/edb_core/layout_validation.py,sha256=S0IFx9t5toVpuTLTI2Cs9vvgR4BCebJLXnj0ydW2Op8,13597
38
38
  pyedb/dotnet/edb_core/materials.py,sha256=s105DUTFkQoQRWgtRMp02DKcU2YcSrfLbJoi8hcTQII,42293
39
39
  pyedb/dotnet/edb_core/modeler.py,sha256=rVJ-eh3eKOnCHENaBLZ8D7duH7tUtUqZJNLKGLFsZ_M,55519
40
40
  pyedb/dotnet/edb_core/net_class.py,sha256=4U6Cc1Gn7ZJ_ub9uKmtrsoz5wD1XS42afci3Y3ewRp0,11354
41
41
  pyedb/dotnet/edb_core/nets.py,sha256=Wc84urZG6nM3fZYqMj2HzM6CgNz_B4s4O3WmMGr-5H0,25199
42
- pyedb/dotnet/edb_core/padstack.py,sha256=19cRYqTHVjjvblYVoZgMetRBXDjtP5-URUv6eA0mvfY,63566
43
- pyedb/dotnet/edb_core/siwave.py,sha256=4duoAsFCuPMNLxtMTEEVJCUaHKNkdbLDmtTXiD93VrM,64311
42
+ pyedb/dotnet/edb_core/padstack.py,sha256=Qp5nSQNo1Ze0u8GUE3FjtbSYD73uQcNJhEOoUAHXLBo,72102
43
+ pyedb/dotnet/edb_core/siwave.py,sha256=QF4JyVNWoDeNQRRBBExlCxxVUt1-5DpKIlpuYkXd4k0,64286
44
44
  pyedb/dotnet/edb_core/stackup.py,sha256=b56leXg7X7dEVPP2DUD9n8LZIakWcjIsjiqqkIWsyZU,120035
45
45
  pyedb/dotnet/edb_core/cell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
46
  pyedb/dotnet/edb_core/cell/connectable.py,sha256=gc5jhWx4DX718T7koL6oZZzfS4EdQNTiFX76ZJ2c83E,2864
@@ -52,7 +52,7 @@ pyedb/dotnet/edb_core/cell/hierarchy/component.py,sha256=Iri2YVNntt02ojqtBAg-Nos
52
52
  pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py,sha256=OUNK6INKlbJkCbzy6jKZzrQs7fvCR1qiTjt7te0S7nQ,2160
53
53
  pyedb/dotnet/edb_core/cell/hierarchy/model.py,sha256=LwXE4VUfptG5rJ9gmAmye0hECBv7bUGtby1ZzNFkeT0,3198
54
54
  pyedb/dotnet/edb_core/cell/hierarchy/netlist_model.py,sha256=fF6tY-6s-lW9EuvJ5sw3RlIkjuoSjeZbrNk5wG-_hzM,1356
55
- pyedb/dotnet/edb_core/cell/hierarchy/pin_pair_model.py,sha256=4zo2ut6UAeJqxw70n1luWg2QGEeuMRoVcEcdC9bYG50,3846
55
+ pyedb/dotnet/edb_core/cell/hierarchy/pin_pair_model.py,sha256=nq_22nNC2EWo9rirAztOE2mysfP6uV9cdMnamy6zTu4,3792
56
56
  pyedb/dotnet/edb_core/cell/hierarchy/s_parameter_model.py,sha256=o7Omw4R9uQGCBDj4dIU-R73Uf6v3p_zKLMAzJlaH9VA,1456
57
57
  pyedb/dotnet/edb_core/cell/hierarchy/spice_model.py,sha256=SGiUcan2l0n8DGk3GtwCskkqZ3rdVHMSS_fGlAfwJSk,1443
58
58
  pyedb/dotnet/edb_core/cell/primitive/__init__.py,sha256=8jByHkoaowAYQTCww-zRrTQmN061fLz_OHjTLSrzQQY,58
@@ -62,10 +62,10 @@ pyedb/dotnet/edb_core/cell/primitive/primitive.py,sha256=wZcHylKr_OVnXzVfNtce_Wu
62
62
  pyedb/dotnet/edb_core/cell/terminal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  pyedb/dotnet/edb_core/cell/terminal/bundle_terminal.py,sha256=qM0wEXkZ-DpoJ6vlVa560Ce8IgOdp4vyIJPedvoa3O0,1977
64
64
  pyedb/dotnet/edb_core/cell/terminal/edge_terminal.py,sha256=lafPRrvsDPYKcysvrkO-5tEZXF3h4IcTXdeJgTjleuI,2158
65
- pyedb/dotnet/edb_core/cell/terminal/padstack_instance_terminal.py,sha256=XI7NiP1qT2aft7hjPK4gX42RzreiZ66aHXIHFPwUghs,3999
65
+ pyedb/dotnet/edb_core/cell/terminal/padstack_instance_terminal.py,sha256=ViG6tYI7_WNW67Coi36XHSV6bEGCm35AHkRSAtbQvn0,4417
66
66
  pyedb/dotnet/edb_core/cell/terminal/pingroup_terminal.py,sha256=Xupr55vseJsAR6y62Ekv1Kie_ILc6RVNzT3Sgxdi7X4,2753
67
- pyedb/dotnet/edb_core/cell/terminal/point_terminal.py,sha256=S3aCAuFc_QA36PVn2Cdb9L4dO3T4IikwyEVcP1FOW3I,2597
68
- pyedb/dotnet/edb_core/cell/terminal/terminal.py,sha256=2pAba8-6YxZdbrh_b8WiqF_pitmfGy8_fSiMHro7oEs,19145
67
+ pyedb/dotnet/edb_core/cell/terminal/point_terminal.py,sha256=zrGG4fxjuEqKaSLZz5w1uV0f-aigUJmN166p2j67RPI,3015
68
+ pyedb/dotnet/edb_core/cell/terminal/terminal.py,sha256=jQ1Zl7c7p6sQquNeRgtGg2L1flNCNPzJ9r2iuAX-bmY,18671
69
69
  pyedb/dotnet/edb_core/definition/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
70
  pyedb/dotnet/edb_core/definition/component_def.py,sha256=iXrGs1CpFHoLZ4cJZ7hebf592Hq5mG9Kp4Ip1TfuMjo,7404
71
71
  pyedb/dotnet/edb_core/definition/component_model.py,sha256=HZzS3YX9hZBq5vv5Q9fS9MAN8S7Bxc3M6xcOETKvfT0,1838
@@ -80,7 +80,7 @@ pyedb/dotnet/edb_core/edb_data/control_file.py,sha256=qIXBJG0V_dvpvSqIycQcNOb8Ur
80
80
  pyedb/dotnet/edb_core/edb_data/design_options.py,sha256=RO9ip-T5Bfxpsl97_QEk0qDZsza3tLzIX2t25XLutys,2057
81
81
  pyedb/dotnet/edb_core/edb_data/edbvalue.py,sha256=Vj_11HXsQUNavizKp5FicORm6cjhXRh9uvxhv_D_RJc,1977
82
82
  pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py,sha256=wIKH4it1uYkEae4OimS3YE6QoSf8rAAIhxdTwtR9cqU,13040
83
- pyedb/dotnet/edb_core/edb_data/layer_data.py,sha256=d-gdIwODshMiHkdLCVoHtc0VbONzDYnZFil0WsUXN4c,33160
83
+ pyedb/dotnet/edb_core/edb_data/layer_data.py,sha256=4Z_eaHSfGfwQBKETEmGSwMvwGzvirtwYw4G4TwonNiA,34314
84
84
  pyedb/dotnet/edb_core/edb_data/nets_data.py,sha256=fXJ1U18ZLm9xI7MJD3UcTsI8XNZSq5kf20KF2IMib4o,10137
85
85
  pyedb/dotnet/edb_core/edb_data/padstacks_data.py,sha256=1j_GG552iwvzvx6TKI3Yx6C3RXOWiSNehdlbD8AuzaI,78474
86
86
  pyedb/dotnet/edb_core/edb_data/ports.py,sha256=wr2RQi8VExuNIVmnp7c4VpTIhODgthmJmHr01zO4ueo,8873
@@ -117,7 +117,7 @@ pyedb/generic/design_types.py,sha256=qHyIaz-Vd3ra4CP9xER76-nGRonYmSAiI3Dr8YPUeH8
117
117
  pyedb/generic/filesystem.py,sha256=EqsLGwdhCgY3asomjoWZBBYWQiGhVOBlSzQlM6FCZhw,3674
118
118
  pyedb/generic/general_methods.py,sha256=HfDQEiQkNng4apFUbStsEfvKDbPkZ0Oz9Wjlqqz5LSI,42798
119
119
  pyedb/generic/plot.py,sha256=0x2-v_xNSoy07rILKGQStQMTUIYrvJEvFO1n9KuSfAc,4717
120
- pyedb/generic/process.py,sha256=DiOanqNq5APYryBYo3Wt4mQ54cBR9-ULrrIOqGE4S8c,11107
120
+ pyedb/generic/process.py,sha256=i0poMbEnFFAsnNOPWN-myMnUaG7hMClKi9kGPMFyvCM,11148
121
121
  pyedb/generic/settings.py,sha256=QTX5OVZ8sVPIy_QaSxRODUWvoXkYkVpzh3l6pQPseKQ,9220
122
122
  pyedb/ipc2581/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
123
  pyedb/ipc2581/history_record.py,sha256=s1GjcIgnZHlNCBOeEERBDX7xDuqhXmh2Ctt3ccFDWso,2739
@@ -188,7 +188,7 @@ pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py,sha256=YmYI6WTQulL5Uf8Wx
188
188
  pyedb/misc/siw_feature_config/xtalk_scan/td_xtalk_config.py,sha256=KHa-UqcXuabiVfT2CV-UvWl5Q2qGYHF2Ye9azcAlnXc,3966
189
189
  pyedb/modeler/geometry_operators.py,sha256=g_Sy7a6R23sP6RtboJn1rl8uTuo8oeLmMF21rNkzwjk,74198
190
190
  pyedb/siwave_core/icepak.py,sha256=WnZ-t8mik7LDY06V8hZFV-TxRZJQWK7bu_8Ichx-oBs,5206
191
- pyedb-0.34.2.dist-info/LICENSE,sha256=qQWivZ12ETN5l3QxvTARY-QI5eoRRlyHdwLlAj0Bg5I,1089
192
- pyedb-0.34.2.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
193
- pyedb-0.34.2.dist-info/METADATA,sha256=oNJa8H9I4rPugFDVo03TVQBCfs-7gkyrHTuLMUf9Sro,8512
194
- pyedb-0.34.2.dist-info/RECORD,,
191
+ pyedb-0.35.0.dist-info/LICENSE,sha256=qQWivZ12ETN5l3QxvTARY-QI5eoRRlyHdwLlAj0Bg5I,1089
192
+ pyedb-0.35.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
193
+ pyedb-0.35.0.dist-info/METADATA,sha256=FuDrrBF8NzY_z8cYDUfz0hI2iVKmUn2AwxXR4NBbdRQ,8513
194
+ pyedb-0.35.0.dist-info/RECORD,,
File without changes