pyedb 0.2.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.

Files changed (128) hide show
  1. pyedb/__init__.py +17 -0
  2. pyedb/dotnet/__init__.py +0 -0
  3. pyedb/dotnet/application/Variables.py +2261 -0
  4. pyedb/dotnet/application/__init__.py +0 -0
  5. pyedb/dotnet/clr_module.py +103 -0
  6. pyedb/dotnet/edb.py +4237 -0
  7. pyedb/dotnet/edb_core/__init__.py +1 -0
  8. pyedb/dotnet/edb_core/cell/__init__.py +0 -0
  9. pyedb/dotnet/edb_core/cell/hierarchy/__init__.py +0 -0
  10. pyedb/dotnet/edb_core/cell/hierarchy/model.py +66 -0
  11. pyedb/dotnet/edb_core/components.py +2669 -0
  12. pyedb/dotnet/edb_core/configuration.py +423 -0
  13. pyedb/dotnet/edb_core/definition/__init__.py +0 -0
  14. pyedb/dotnet/edb_core/definition/component_def.py +166 -0
  15. pyedb/dotnet/edb_core/definition/component_model.py +30 -0
  16. pyedb/dotnet/edb_core/definition/definition_obj.py +18 -0
  17. pyedb/dotnet/edb_core/definition/definitions.py +12 -0
  18. pyedb/dotnet/edb_core/dotnet/__init__.py +0 -0
  19. pyedb/dotnet/edb_core/dotnet/database.py +1218 -0
  20. pyedb/dotnet/edb_core/dotnet/layout.py +238 -0
  21. pyedb/dotnet/edb_core/dotnet/primitive.py +1517 -0
  22. pyedb/dotnet/edb_core/edb_data/__init__.py +0 -0
  23. pyedb/dotnet/edb_core/edb_data/components_data.py +938 -0
  24. pyedb/dotnet/edb_core/edb_data/connectable.py +113 -0
  25. pyedb/dotnet/edb_core/edb_data/control_file.py +1268 -0
  26. pyedb/dotnet/edb_core/edb_data/design_options.py +35 -0
  27. pyedb/dotnet/edb_core/edb_data/edbvalue.py +45 -0
  28. pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +330 -0
  29. pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +1607 -0
  30. pyedb/dotnet/edb_core/edb_data/layer_data.py +576 -0
  31. pyedb/dotnet/edb_core/edb_data/nets_data.py +281 -0
  32. pyedb/dotnet/edb_core/edb_data/obj_base.py +19 -0
  33. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +2080 -0
  34. pyedb/dotnet/edb_core/edb_data/ports.py +287 -0
  35. pyedb/dotnet/edb_core/edb_data/primitives_data.py +1397 -0
  36. pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +2914 -0
  37. pyedb/dotnet/edb_core/edb_data/simulation_setup.py +716 -0
  38. pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1205 -0
  39. pyedb/dotnet/edb_core/edb_data/sources.py +514 -0
  40. pyedb/dotnet/edb_core/edb_data/terminals.py +632 -0
  41. pyedb/dotnet/edb_core/edb_data/utilities.py +148 -0
  42. pyedb/dotnet/edb_core/edb_data/variables.py +91 -0
  43. pyedb/dotnet/edb_core/general.py +181 -0
  44. pyedb/dotnet/edb_core/hfss.py +1646 -0
  45. pyedb/dotnet/edb_core/layout.py +1244 -0
  46. pyedb/dotnet/edb_core/layout_validation.py +272 -0
  47. pyedb/dotnet/edb_core/materials.py +939 -0
  48. pyedb/dotnet/edb_core/net_class.py +335 -0
  49. pyedb/dotnet/edb_core/nets.py +1215 -0
  50. pyedb/dotnet/edb_core/padstack.py +1389 -0
  51. pyedb/dotnet/edb_core/siwave.py +1427 -0
  52. pyedb/dotnet/edb_core/stackup.py +2703 -0
  53. pyedb/edb_logger.py +396 -0
  54. pyedb/generic/__init__.py +0 -0
  55. pyedb/generic/constants.py +1063 -0
  56. pyedb/generic/data_handlers.py +320 -0
  57. pyedb/generic/design_types.py +104 -0
  58. pyedb/generic/filesystem.py +150 -0
  59. pyedb/generic/general_methods.py +1535 -0
  60. pyedb/generic/plot.py +1840 -0
  61. pyedb/generic/process.py +285 -0
  62. pyedb/generic/settings.py +224 -0
  63. pyedb/ipc2581/__init__.py +0 -0
  64. pyedb/ipc2581/bom/__init__.py +0 -0
  65. pyedb/ipc2581/bom/bom.py +21 -0
  66. pyedb/ipc2581/bom/bom_item.py +32 -0
  67. pyedb/ipc2581/bom/characteristics.py +37 -0
  68. pyedb/ipc2581/bom/refdes.py +16 -0
  69. pyedb/ipc2581/content/__init__.py +0 -0
  70. pyedb/ipc2581/content/color.py +38 -0
  71. pyedb/ipc2581/content/content.py +55 -0
  72. pyedb/ipc2581/content/dictionary_color.py +29 -0
  73. pyedb/ipc2581/content/dictionary_fill.py +28 -0
  74. pyedb/ipc2581/content/dictionary_line.py +30 -0
  75. pyedb/ipc2581/content/entry_color.py +13 -0
  76. pyedb/ipc2581/content/entry_line.py +14 -0
  77. pyedb/ipc2581/content/fill.py +15 -0
  78. pyedb/ipc2581/content/layer_ref.py +10 -0
  79. pyedb/ipc2581/content/standard_geometries_dictionary.py +72 -0
  80. pyedb/ipc2581/ecad/__init__.py +0 -0
  81. pyedb/ipc2581/ecad/cad_data/__init__.py +0 -0
  82. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +26 -0
  83. pyedb/ipc2581/ecad/cad_data/cad_data.py +37 -0
  84. pyedb/ipc2581/ecad/cad_data/component.py +41 -0
  85. pyedb/ipc2581/ecad/cad_data/drill.py +30 -0
  86. pyedb/ipc2581/ecad/cad_data/feature.py +54 -0
  87. pyedb/ipc2581/ecad/cad_data/layer.py +41 -0
  88. pyedb/ipc2581/ecad/cad_data/layer_feature.py +151 -0
  89. pyedb/ipc2581/ecad/cad_data/logical_net.py +32 -0
  90. pyedb/ipc2581/ecad/cad_data/outline.py +25 -0
  91. pyedb/ipc2581/ecad/cad_data/package.py +104 -0
  92. pyedb/ipc2581/ecad/cad_data/padstack_def.py +38 -0
  93. pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +24 -0
  94. pyedb/ipc2581/ecad/cad_data/padstack_instance.py +62 -0
  95. pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +26 -0
  96. pyedb/ipc2581/ecad/cad_data/path.py +89 -0
  97. pyedb/ipc2581/ecad/cad_data/phy_net.py +80 -0
  98. pyedb/ipc2581/ecad/cad_data/pin.py +31 -0
  99. pyedb/ipc2581/ecad/cad_data/polygon.py +169 -0
  100. pyedb/ipc2581/ecad/cad_data/profile.py +40 -0
  101. pyedb/ipc2581/ecad/cad_data/stackup.py +31 -0
  102. pyedb/ipc2581/ecad/cad_data/stackup_group.py +42 -0
  103. pyedb/ipc2581/ecad/cad_data/stackup_layer.py +21 -0
  104. pyedb/ipc2581/ecad/cad_data/step.py +275 -0
  105. pyedb/ipc2581/ecad/cad_header.py +33 -0
  106. pyedb/ipc2581/ecad/ecad.py +19 -0
  107. pyedb/ipc2581/ecad/spec.py +46 -0
  108. pyedb/ipc2581/history_record.py +37 -0
  109. pyedb/ipc2581/ipc2581.py +387 -0
  110. pyedb/ipc2581/logistic_header.py +25 -0
  111. pyedb/misc/__init__.py +0 -0
  112. pyedb/misc/aedtlib_personalib_install.py +14 -0
  113. pyedb/misc/downloads.py +322 -0
  114. pyedb/misc/misc.py +67 -0
  115. pyedb/misc/pyedb.runtimeconfig.json +13 -0
  116. pyedb/misc/siw_feature_config/__init__.py +0 -0
  117. pyedb/misc/siw_feature_config/emc/__init__.py +0 -0
  118. pyedb/misc/siw_feature_config/emc/component_tags.py +46 -0
  119. pyedb/misc/siw_feature_config/emc/net_tags.py +37 -0
  120. pyedb/misc/siw_feature_config/emc/tag_library.py +62 -0
  121. pyedb/misc/siw_feature_config/emc/xml_generic.py +78 -0
  122. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +179 -0
  123. pyedb/misc/utilities.py +27 -0
  124. pyedb/modeler/geometry_operators.py +2082 -0
  125. pyedb-0.2.0.dist-info/LICENSE +21 -0
  126. pyedb-0.2.0.dist-info/METADATA +208 -0
  127. pyedb-0.2.0.dist-info/RECORD +128 -0
  128. pyedb-0.2.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,1215 @@
1
+ from __future__ import absolute_import # noreorder
2
+
3
+ import math
4
+ import os
5
+ import time
6
+ import warnings
7
+
8
+ from pyedb.dotnet.edb_core.edb_data.nets_data import EDBNetsData
9
+ from pyedb.generic.constants import CSS4_COLORS
10
+ from pyedb.generic.general_methods import (
11
+ generate_unique_name,
12
+ is_ironpython,
13
+ pyedb_function_handler,
14
+ )
15
+ from pyedb.modeler.geometry_operators import GeometryOperators
16
+
17
+
18
+ class EdbNets(object):
19
+ """Manages EDB methods for nets management accessible from `Edb.nets` property.
20
+
21
+ Examples
22
+ --------
23
+ >>> from pyedb.dotnet.edb import Edb
24
+ >>> edbapp = Edb("myaedbfolder", edbversion="2021.2")
25
+ >>> edb_nets = edbapp.nets
26
+ """
27
+
28
+ @pyedb_function_handler()
29
+ def __getitem__(self, name):
30
+ """Get a net from the Edb project.
31
+
32
+ Parameters
33
+ ----------
34
+ name : str, int
35
+
36
+ Returns
37
+ -------
38
+ :class:` :class:`pyedb.dotnet.edb_core.edb_data.nets_data.EDBNetsData`
39
+
40
+ """
41
+ if name in self.nets:
42
+ return self.nets[name]
43
+ self._pedb.logger.error("Component or definition not found.")
44
+ return
45
+
46
+ @pyedb_function_handler()
47
+ def __contains__(self, name):
48
+ """Determine if a net is named ``name`` or not.
49
+
50
+ Parameters
51
+ ----------
52
+ name : str
53
+
54
+ Returns
55
+ -------
56
+ bool
57
+ ``True`` when one of the net is named ``name``, ``False`` otherwise.
58
+
59
+ """
60
+ return name in self.nets
61
+
62
+ def __init__(self, p_edb):
63
+ self._pedb = p_edb
64
+ self._nets_by_comp_dict = {}
65
+ self._comps_by_nets_dict = {}
66
+
67
+ @property
68
+ def _edb(self):
69
+ """ """
70
+ return self._pedb.edb_api
71
+
72
+ @property
73
+ def _active_layout(self):
74
+ """ """
75
+ return self._pedb.active_layout
76
+
77
+ @property
78
+ def _layout(self):
79
+ """ """
80
+ return self._pedb.layout
81
+
82
+ @property
83
+ def _cell(self):
84
+ """ """
85
+ return self._pedb.cell
86
+
87
+ @property
88
+ def db(self):
89
+ """Db object."""
90
+ return self._pedb.active_db
91
+
92
+ @property
93
+ def _logger(self):
94
+ """Edb logger."""
95
+ return self._pedb.logger
96
+
97
+ @property
98
+ def nets(self):
99
+ """Nets.
100
+
101
+ Returns
102
+ -------
103
+ dict[str, :class:`pyedb.dotnet.edb_core.edb_data.nets_data.EDBNetsData`]
104
+ Dictionary of nets.
105
+ """
106
+
107
+ temp = {}
108
+ for net in self._layout.nets:
109
+ temp[net.name] = EDBNetsData(net.api_object, self._pedb)
110
+ return temp
111
+
112
+ @property
113
+ def netlist(self):
114
+ """Return the cell netlist.
115
+
116
+ Returns
117
+ -------
118
+ list
119
+ Net names.
120
+ """
121
+ return list(self.nets.keys())
122
+
123
+ @property
124
+ def signal_nets(self):
125
+ """Signal nets.
126
+
127
+ .. deprecated:: 0.6.62
128
+ Use :func:`signal` instead.
129
+
130
+ Returns
131
+ -------
132
+ dict[str, :class:`pyedb.dotnet.edb_core.edb_data.EDBNetsData`]
133
+ Dictionary of signal nets.
134
+ """
135
+ warnings.warn("Use :func:`signal` instead.", DeprecationWarning)
136
+ return self.signal
137
+
138
+ @property
139
+ def power_nets(self):
140
+ """Power nets.
141
+
142
+ .. deprecated:: 0.6.62
143
+ Use :func:`power` instead.
144
+
145
+ Returns
146
+ -------
147
+ dict[str, :class:`pyedb.dotnet.edb_core.edb_data.EDBNetsData`]
148
+ Dictionary of power nets.
149
+ """
150
+ warnings.warn("Use :func:`power` instead.", DeprecationWarning)
151
+ return self.power
152
+
153
+ @property
154
+ def signal(self):
155
+ """Signal nets.
156
+
157
+ Returns
158
+ -------
159
+ dict[str, :class:`pyedb.dotnet.edb_core.edb_data.EDBNetsData`]
160
+ Dictionary of signal nets.
161
+ """
162
+ nets = {}
163
+ for net, value in self.nets.items():
164
+ if not value.IsPowerGround():
165
+ nets[net] = value
166
+ return nets
167
+
168
+ @property
169
+ def power(self):
170
+ """Power nets.
171
+
172
+ Returns
173
+ -------
174
+ dict[str, :class:`pyedb.dotnet.edb_core.edb_data.EDBNetsData`]
175
+ Dictionary of power nets.
176
+ """
177
+ nets = {}
178
+ for net, value in self.nets.items():
179
+ if value.IsPowerGround():
180
+ nets[net] = value
181
+ return nets
182
+
183
+ @pyedb_function_handler()
184
+ def eligible_power_nets(self, threshold=0.3):
185
+ """Return a list of nets calculated by area to be eligible for PWR/Ground net classification.
186
+ It uses the same algorithm implemented in SIwave.
187
+
188
+ Parameters
189
+ ----------
190
+ threshold : float, optional
191
+ Area ratio used by the ``get_power_ground_nets`` method.
192
+
193
+ Returns
194
+ -------
195
+ list of :class:`pyedb.dotnet.edb_core.edb_data.EDBNetsData`
196
+ """
197
+ pwr_gnd_nets = []
198
+ for net in self._layout.nets[:]:
199
+ total_plane_area = 0.0
200
+ total_trace_area = 0.0
201
+ for primitive in net.Primitives:
202
+ if primitive.GetPrimitiveType() == self._edb.cell.primitive.PrimitiveType.Bondwire:
203
+ continue
204
+ if primitive.GetPrimitiveType() != self._edb.cell.primitive.PrimitiveType.Path:
205
+ total_plane_area += float(primitive.GetPolygonData().Area())
206
+ else:
207
+ total_trace_area += float(primitive.GetPolygonData().Area())
208
+ if total_plane_area == 0.0:
209
+ continue
210
+ if total_trace_area == 0.0:
211
+ pwr_gnd_nets.append(EDBNetsData(net.api_object, self._pedb))
212
+ continue
213
+ if total_plane_area > 0.0 and total_trace_area > 0.0:
214
+ if total_plane_area / (total_plane_area + total_trace_area) > threshold:
215
+ pwr_gnd_nets.append(EDBNetsData(net.api_object, self._pedb))
216
+ return pwr_gnd_nets
217
+
218
+ @property
219
+ def nets_by_components(self):
220
+ # type: () -> dict
221
+ """Get all nets for each component instance."""
222
+ for comp, i in self._pedb.components.instances.items():
223
+ self._nets_by_comp_dict[comp] = i.nets
224
+ return self._nets_by_comp_dict
225
+
226
+ @property
227
+ def components_by_nets(self):
228
+ # type: () -> dict
229
+ """Get all component instances grouped by nets."""
230
+ for comp, i in self._pedb.components.instances.items():
231
+ for n in i.nets:
232
+ if n in self._comps_by_nets_dict:
233
+ self._comps_by_nets_dict[n].append(comp)
234
+ else:
235
+ self._comps_by_nets_dict[n] = [comp]
236
+ return self._comps_by_nets_dict
237
+
238
+ @pyedb_function_handler()
239
+ def generate_extended_nets(
240
+ self,
241
+ resistor_below=10,
242
+ inductor_below=1,
243
+ capacitor_above=1,
244
+ exception_list=None,
245
+ include_signal=True,
246
+ include_power=True,
247
+ ):
248
+ # type: (int | float, int | float, int |float, list, bool, bool) -> list
249
+ """Get extended net and associated components.
250
+
251
+ Parameters
252
+ ----------
253
+ resistor_below : int, float, optional
254
+ Threshold of resistor value. Search extended net across resistors which has value lower than the threshold.
255
+ inductor_below : int, float, optional
256
+ Threshold of inductor value. Search extended net across inductances which has value lower than the
257
+ threshold.
258
+ capacitor_above : int, float, optional
259
+ Threshold of capacitor value. Search extended net across capacitors which has value higher than the
260
+ threshold.
261
+ exception_list : list, optional
262
+ List of components to bypass when performing threshold checks. Components
263
+ in the list are considered as serial components. The default is ``None``.
264
+ include_signal : str, optional
265
+ Whether to generate extended signal nets. The default is ``True``.
266
+ include_power : str, optional
267
+ Whether to generate extended power nets. The default is ``True``.
268
+
269
+ Returns
270
+ -------
271
+ list
272
+ List of all extended nets.
273
+
274
+ Examples
275
+ --------
276
+ >>> from pyedb import Edb
277
+ >>> app = Edb()
278
+ >>> app.nets.get_extended_nets()
279
+ """
280
+ if exception_list is None:
281
+ exception_list = []
282
+ _extended_nets = []
283
+ _nets = self.nets
284
+ all_nets = list(_nets.keys())[:]
285
+ net_dicts = self._comps_by_nets_dict if self._comps_by_nets_dict else self.components_by_nets
286
+ comp_dict = self._nets_by_comp_dict if self._nets_by_comp_dict else self.nets_by_components
287
+
288
+ def get_net_list(net_name, _net_list):
289
+ comps = []
290
+ if net_name in net_dicts:
291
+ comps = net_dicts[net_name]
292
+
293
+ for vals in comps:
294
+ refdes = vals
295
+ cmp = self._pedb.components.instances[refdes]
296
+ is_enabled = cmp.is_enabled
297
+ if not is_enabled:
298
+ continue
299
+ val_type = cmp.type
300
+ if val_type not in ["Inductor", "Resistor", "Capacitor"]:
301
+ continue
302
+
303
+ val_value = cmp.rlc_values
304
+ if refdes in exception_list:
305
+ pass
306
+ elif val_type == "Inductor" and val_value[1] < inductor_below:
307
+ pass
308
+ elif val_type == "Resistor" and val_value[0] < resistor_below:
309
+ pass
310
+ elif val_type == "Capacitor" and val_value[2] > capacitor_above:
311
+ pass
312
+ else:
313
+ continue
314
+
315
+ for net in comp_dict[refdes]:
316
+ if net not in _net_list:
317
+ _net_list.append(net)
318
+ get_net_list(net, _net_list)
319
+
320
+ while len(all_nets) > 0:
321
+ new_ext = [all_nets[0]]
322
+ get_net_list(new_ext[0], new_ext)
323
+ all_nets = [i for i in all_nets if i not in new_ext]
324
+ _extended_nets.append(new_ext)
325
+
326
+ if len(new_ext) > 1:
327
+ i = new_ext[0]
328
+ for i in new_ext:
329
+ if not i.lower().startswith("unnamed"):
330
+ break
331
+
332
+ is_power = False
333
+ for i in new_ext:
334
+ is_power = is_power or _nets[i].is_power_ground
335
+
336
+ if is_power:
337
+ if include_power:
338
+ self._pedb.extended_nets.create(i, new_ext)
339
+ else: # pragma: no cover
340
+ pass
341
+ else:
342
+ if include_signal:
343
+ self._pedb.extended_nets.create(i, new_ext)
344
+ else: # pragma: no cover
345
+ pass
346
+
347
+ return _extended_nets
348
+
349
+ @staticmethod
350
+ def _eval_arc_points(p1, p2, h, n=6, tol=1e-12):
351
+ """Get the points of the arc.
352
+
353
+ Parameters
354
+ ----------
355
+ p1 : list
356
+ Arc starting point.
357
+ p2 : list
358
+ Arc ending point.
359
+ h : float
360
+ Arc height.
361
+ n : int
362
+ Number of points to generate along the arc.
363
+ tol : float
364
+ Geometric tolerance.
365
+
366
+ Returns
367
+ -------
368
+ list
369
+ points generated along the arc.
370
+ """
371
+ # fmt: off
372
+ if abs(h) < tol:
373
+ return [], []
374
+ elif h > 0:
375
+ reverse = False
376
+ x1 = p1[0]
377
+ y1 = p1[1]
378
+ x2 = p2[0]
379
+ y2 = p2[1]
380
+ else:
381
+ reverse = True
382
+ x1 = p2[0]
383
+ y1 = p2[1]
384
+ x2 = p1[0]
385
+ y2 = p1[1]
386
+ h *= -1
387
+ xa = (x2 - x1) / 2
388
+ ya = (y2 - y1) / 2
389
+ xo = x1 + xa
390
+ yo = y1 + ya
391
+ a = math.sqrt(xa ** 2 + ya ** 2)
392
+ if a < tol:
393
+ return [], []
394
+ r = (a ** 2) / (2 * h) + h / 2
395
+ if abs(r - a) < tol:
396
+ b = 0
397
+ th = 2 * math.asin(1) # chord angle
398
+ else:
399
+ b = math.sqrt(r ** 2 - a ** 2)
400
+ th = 2 * math.asin(a / r) # chord angle
401
+
402
+ # center of the circle
403
+ xc = xo + b * ya / a
404
+ yc = yo - b * xa / a
405
+
406
+ alpha = math.atan2((y1 - yc), (x1 - xc))
407
+ xr = []
408
+ yr = []
409
+ for i in range(n):
410
+ i += 1
411
+ dth = (i / (n + 1)) * th
412
+ xi = xc + r * math.cos(alpha - dth)
413
+ yi = yc + r * math.sin(alpha - dth)
414
+ xr.append(xi)
415
+ yr.append(yi)
416
+
417
+ if reverse:
418
+ xr.reverse()
419
+ yr.reverse()
420
+ # fmt: on
421
+ return xr, yr
422
+
423
+ def _get_points_for_plot(self, my_net_points):
424
+ """
425
+ Get the points to be plot
426
+ """
427
+ # fmt: off
428
+ x = []
429
+ y = []
430
+ for i, point in enumerate(my_net_points):
431
+ # point = my_net_points[i]
432
+ if not point.IsArc():
433
+ x.append(point.X.ToDouble())
434
+ y.append(point.Y.ToDouble())
435
+ # i += 1
436
+ else:
437
+ arc_h = point.GetArcHeight().ToDouble()
438
+ p1 = [my_net_points[i - 1].X.ToDouble(), my_net_points[i - 1].Y.ToDouble()]
439
+ if i + 1 < len(my_net_points):
440
+ p2 = [my_net_points[i + 1].X.ToDouble(), my_net_points[i + 1].Y.ToDouble()]
441
+ else:
442
+ p2 = [my_net_points[0].X.ToDouble(), my_net_points[0].Y.ToDouble()]
443
+ x_arc, y_arc = self._eval_arc_points(p1, p2, arc_h)
444
+ x.extend(x_arc)
445
+ y.extend(y_arc)
446
+ # i += 1
447
+ # fmt: on
448
+ return x, y
449
+
450
+ @pyedb_function_handler()
451
+ def get_plot_data(
452
+ self,
453
+ nets,
454
+ layers=None,
455
+ color_by_net=False,
456
+ outline=None,
457
+ plot_components_on_top=False,
458
+ plot_components_on_bottom=False,
459
+ ):
460
+ """Return List of points for Matplotlib 2D Chart.
461
+
462
+ Parameters
463
+ ----------
464
+ nets : str, list
465
+ Name of the net or list of nets to plot. If `None` all nets will be plotted.
466
+ layers : str, list, optional
467
+ Name of the layers to include in the plot. If `None` all the signal layers will be considered.
468
+ color_by_net : bool, optional
469
+ If ``True`` the plot will be colored by net.
470
+ If ``False`` the plot will be colored by layer. (default)
471
+ outline : list, optional
472
+ List of points of the outline to plot.
473
+ plot_components_on_top : bool, optional
474
+ If ``True`` the components placed on top layer are plotted.
475
+ If ``False`` the components are not plotted. (default)
476
+ If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted.
477
+ plot_components_on_bottom : bool, optional
478
+ If ``True`` the components placed on bottom layer are plotted.
479
+ If ``False`` the components are not plotted. (default)
480
+ If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted.
481
+
482
+ Returns
483
+ -------
484
+ List, str: list of data to be used in plot.
485
+ In case of remote session it will be returned a string that could be converted \
486
+ to list using ast.literal_eval().
487
+ """
488
+ start_time = time.time()
489
+ if not nets:
490
+ nets = list(self.nets.keys())
491
+ if isinstance(nets, str):
492
+ nets = [nets]
493
+ if not layers:
494
+ layers = list(self._pedb.stackup.signal_layers.keys())
495
+ if isinstance(layers, str):
496
+ layers = [layers]
497
+ color_index = 0
498
+ objects_lists = []
499
+ label_colors = {}
500
+ n_label = 0
501
+ max_labels = 10
502
+
503
+ if outline:
504
+ xt = [i[0] for i in outline]
505
+ yt = [i[1] for i in outline]
506
+ xc, yc = GeometryOperators.orient_polygon(xt, yt, clockwise=True)
507
+ vertices = [(i, j) for i, j in zip(xc, yc)]
508
+ codes = [2 for _ in vertices]
509
+ codes[0] = 1
510
+ vertices.append((0, 0))
511
+ codes.append(79)
512
+ objects_lists.append([vertices, codes, "b", "Outline", 1.0, 1.5, "contour"])
513
+ n_label += 1
514
+ top_layer = list(self._pedb.stackup.signal_layers.keys())[0]
515
+ bottom_layer = list(self._pedb.stackup.signal_layers.keys())[-1]
516
+ if plot_components_on_top or plot_components_on_bottom:
517
+ nc = 0
518
+ for comp in self._pedb.components.components.values():
519
+ if not comp.is_enabled:
520
+ continue
521
+ net_names = comp.nets
522
+ if nets and not any([i in nets for i in net_names]):
523
+ continue
524
+ layer_name = comp.placement_layer
525
+ if layer_name not in layers:
526
+ continue
527
+ if plot_components_on_top and layer_name == top_layer:
528
+ component_color = (184 / 255, 115 / 255, 51 / 255) # this is the color used in AEDT
529
+ label = "Component on top layer"
530
+ elif plot_components_on_bottom and layer_name == bottom_layer:
531
+ component_color = (41 / 255, 171 / 255, 135 / 255) # 41, 171, 135
532
+ label = "Component on bottom layer"
533
+ else:
534
+ continue
535
+ cbb = comp.bounding_box
536
+ x = [cbb[0], cbb[0], cbb[2], cbb[2]]
537
+ y = [cbb[1], cbb[3], cbb[3], cbb[1]]
538
+ vertices = [(i, j) for i, j in zip(x, y)]
539
+ codes = [2 for _ in vertices]
540
+ codes[0] = 1
541
+ vertices.append((0, 0))
542
+ codes.append(79)
543
+ if label not in label_colors:
544
+ label_colors[label] = component_color
545
+ objects_lists.append([vertices, codes, label_colors[label], label, 1.0, 2.0, "contour"])
546
+ n_label += 1
547
+ else:
548
+ objects_lists.append([vertices, codes, label_colors[label], None, 1.0, 2.0, "contour"])
549
+ nc += 1
550
+ self._logger.debug("Plotted {} component(s)".format(nc))
551
+
552
+ for path in self._pedb.modeler.paths:
553
+ if path.is_void:
554
+ continue
555
+ net_name = path.net_name
556
+ layer_name = path.layer_name
557
+ if nets and (net_name not in nets or layer_name not in layers):
558
+ continue
559
+ try:
560
+ x, y = path.points()
561
+ except ValueError:
562
+ x = None
563
+ if not x:
564
+ continue
565
+ create_label = False
566
+ if not color_by_net:
567
+ label = "Layer " + layer_name
568
+ if label not in label_colors:
569
+ try:
570
+ color = path.layer.GetColor()
571
+ c = (
572
+ float(color.Item1 / 255),
573
+ float(color.Item2 / 255),
574
+ float(color.Item3 / 255),
575
+ )
576
+ except:
577
+ c = list(CSS4_COLORS.keys())[color_index]
578
+ color_index += 1
579
+ if color_index >= len(CSS4_COLORS):
580
+ color_index = 0
581
+ label_colors[label] = c
582
+ create_label = True
583
+ else:
584
+ label = "Net " + net_name
585
+ if label not in label_colors:
586
+ label_colors[label] = list(CSS4_COLORS.keys())[color_index]
587
+ color_index += 1
588
+ if color_index >= len(CSS4_COLORS):
589
+ color_index = 0
590
+ create_label = True
591
+
592
+ if create_label and n_label <= max_labels:
593
+ objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"])
594
+ n_label += 1
595
+ else:
596
+ objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"])
597
+
598
+ for poly in self._pedb.modeler.polygons:
599
+ if poly.is_void:
600
+ continue
601
+ net_name = poly.net_name
602
+ layer_name = poly.layer_name
603
+ if nets and (net_name != "" and net_name not in nets or layer_name not in layers):
604
+ continue
605
+ xt, yt = poly.points()
606
+ if not xt:
607
+ continue
608
+ x, y = GeometryOperators.orient_polygon(xt, yt, clockwise=True)
609
+ vertices = [(i, j) for i, j in zip(x, y)]
610
+ codes = [2 for _ in vertices]
611
+ codes[0] = 1
612
+ vertices.append((0, 0))
613
+ codes.append(79)
614
+
615
+ for void in poly.voids:
616
+ xvt, yvt = void.points()
617
+ if xvt:
618
+ xv, yv = GeometryOperators.orient_polygon(xvt, yvt, clockwise=False)
619
+ tmpV = [(i, j) for i, j in zip(xv, yv)]
620
+ vertices.extend(tmpV)
621
+ tmpC = [2 for _ in tmpV]
622
+ tmpC[0] = 1
623
+ codes.extend(tmpC)
624
+ vertices.append((0, 0))
625
+ codes.append(79)
626
+
627
+ create_label = False
628
+ if not color_by_net:
629
+ label = "Layer " + layer_name
630
+ if label not in label_colors:
631
+ try:
632
+ color = poly.GetLayer().GetColor()
633
+ c = (
634
+ float(color.Item1 / 255),
635
+ float(color.Item2 / 255),
636
+ float(color.Item3 / 255),
637
+ )
638
+ except:
639
+ c = list(CSS4_COLORS.keys())[color_index]
640
+ color_index += 1
641
+ if color_index >= len(CSS4_COLORS):
642
+ color_index = 0
643
+ label_colors[label] = c
644
+ create_label = True
645
+ else:
646
+ label = "Net " + net_name
647
+ if label not in label_colors:
648
+ label_colors[label] = list(CSS4_COLORS.keys())[color_index]
649
+ color_index += 1
650
+ if color_index >= len(CSS4_COLORS):
651
+ color_index = 0
652
+ create_label = True
653
+
654
+ if create_label and n_label <= max_labels:
655
+ if layer_name == "Outline":
656
+ objects_lists.append([vertices, codes, label_colors[label], label, 1.0, 2.0, "contour"])
657
+ else:
658
+ objects_lists.append([vertices, codes, label_colors[label], label, 0.4, "path"])
659
+ n_label += 1
660
+ else:
661
+ if layer_name == "Outline":
662
+ objects_lists.append([vertices, codes, label_colors[label], None, 1.0, 2.0, "contour"])
663
+ else:
664
+ objects_lists.append([vertices, codes, label_colors[label], None, 0.4, "path"])
665
+
666
+ for circle in self._pedb.modeler.circles:
667
+ if circle.is_void:
668
+ continue
669
+ net_name = circle.net_name
670
+ layer_name = circle.layer_name
671
+ if nets and (net_name not in nets or layer_name not in layers):
672
+ continue
673
+ x, y = circle.points()
674
+ if not x:
675
+ continue
676
+ create_label = False
677
+ if not color_by_net:
678
+ label = "Layer " + layer_name
679
+ if label not in label_colors:
680
+ try:
681
+ color = circle.layer.GetColor()
682
+ c = (
683
+ float(color.Item1 / 255),
684
+ float(color.Item2 / 255),
685
+ float(color.Item3 / 255),
686
+ )
687
+ except:
688
+ c = list(CSS4_COLORS.keys())[color_index]
689
+ color_index += 1
690
+ if color_index >= len(CSS4_COLORS):
691
+ color_index = 0
692
+ label_colors[label] = c
693
+ create_label = True
694
+ else:
695
+ label = "Net " + net_name
696
+ if label not in label_colors:
697
+ label_colors[label] = list(CSS4_COLORS.keys())[color_index]
698
+ color_index += 1
699
+ if color_index >= len(CSS4_COLORS):
700
+ color_index = 0
701
+ create_label = True
702
+
703
+ if create_label and n_label <= max_labels:
704
+ objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"])
705
+ n_label += 1
706
+ else:
707
+ objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"])
708
+
709
+ for rect in self._pedb.modeler.rectangles:
710
+ if rect.is_void:
711
+ continue
712
+ net_name = rect.net_name
713
+ layer_name = rect.layer_name
714
+ if nets and (net_name not in nets or layer_name not in layers):
715
+ continue
716
+ x, y = rect.points()
717
+ if not x:
718
+ continue
719
+ create_label = False
720
+ if not color_by_net:
721
+ label = "Layer " + layer_name
722
+ if label not in label_colors:
723
+ try:
724
+ color = rect.layer.GetColor()
725
+ c = (
726
+ float(color.Item1 / 255),
727
+ float(color.Item2 / 255),
728
+ float(color.Item3 / 255),
729
+ )
730
+ except:
731
+ c = list(CSS4_COLORS.keys())[color_index]
732
+ color_index += 1
733
+ if color_index >= len(CSS4_COLORS):
734
+ color_index = 0
735
+ label_colors[label] = c
736
+ create_label = True
737
+ else:
738
+ label = "Net " + net_name
739
+ if label not in label_colors:
740
+ label_colors[label] = list(CSS4_COLORS.keys())[color_index]
741
+ color_index += 1
742
+ if color_index >= len(CSS4_COLORS):
743
+ color_index = 0
744
+ create_label = True
745
+
746
+ if create_label and n_label <= max_labels:
747
+ objects_lists.append([x, y, label_colors[label], label, 0.4, "fill"])
748
+ n_label += 1
749
+ else:
750
+ objects_lists.append([x, y, label_colors[label], None, 0.4, "fill"])
751
+
752
+ end_time = time.time() - start_time
753
+ self._logger.info("Nets Point Generation time %s seconds", round(end_time, 3))
754
+ if os.getenv("PYAEDT_SERVER_AEDT_PATH", None):
755
+ return str(objects_lists)
756
+ else:
757
+ return objects_lists
758
+
759
+ @pyedb_function_handler()
760
+ def classify_nets(self, power_nets=None, signal_nets=None):
761
+ """Reassign power/ground or signal nets based on list of nets.
762
+
763
+ Parameters
764
+ ----------
765
+ power_nets : str, list, optional
766
+ List of power nets to assign. Default is `None`.
767
+ signal_nets : str, list, optional
768
+ List of signal nets to assign. Default is `None`.
769
+
770
+ Returns
771
+ -------
772
+ bool
773
+ ``True`` when successful, ``False`` when failed.
774
+ """
775
+ if isinstance(power_nets, str):
776
+ power_nets = []
777
+ elif not power_nets:
778
+ power_nets = []
779
+ if isinstance(signal_nets, str):
780
+ signal_nets = []
781
+ elif not signal_nets:
782
+ signal_nets = []
783
+ for net in power_nets:
784
+ if net in self.nets:
785
+ self.nets[net].net_object.SetIsPowerGround(True)
786
+ for net in signal_nets:
787
+ if net in self.nets:
788
+ self.nets[net].net_object.SetIsPowerGround(False)
789
+ return True
790
+
791
+ @pyedb_function_handler()
792
+ def plot(
793
+ self,
794
+ nets=None,
795
+ layers=None,
796
+ color_by_net=False,
797
+ show_legend=True,
798
+ save_plot=None,
799
+ outline=None,
800
+ size=(2000, 1000),
801
+ plot_components_on_top=False,
802
+ plot_components_on_bottom=False,
803
+ ):
804
+ """Plot a Net to Matplotlib 2D Chart.
805
+
806
+ Parameters
807
+ ----------
808
+ nets : str, list, optional
809
+ Name of the net or list of nets to plot. If ``None`` all nets will be plotted.
810
+ layers : str, list, optional
811
+ Name of the layers to include in the plot. If ``None`` all the signal layers will be considered.
812
+ color_by_net : bool, optional
813
+ If ``True`` the plot will be colored by net.
814
+ If ``False`` the plot will be colored by layer. (default)
815
+ show_legend : bool, optional
816
+ If ``True`` the legend is shown in the plot. (default)
817
+ If ``False`` the legend is not shown.
818
+ save_plot : str, optional
819
+ If ``None`` the plot will be shown.
820
+ If a file path is specified the plot will be saved to such file.
821
+ outline : list, optional
822
+ List of points of the outline to plot.
823
+ size : tuple, int, optional
824
+ Image size in pixel (width, height). Default value is ``(2000, 1000)``
825
+ plot_components_on_top : bool, optional
826
+ If ``True`` the components placed on top layer are plotted.
827
+ If ``False`` the components are not plotted. (default)
828
+ If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted.
829
+ plot_components_on_bottom : bool, optional
830
+ If ``True`` the components placed on bottom layer are plotted.
831
+ If ``False`` the components are not plotted. (default)
832
+ If nets and/or layers is specified, only the components belonging to the specified nets/layers are plotted.
833
+ """
834
+ if is_ironpython:
835
+ self._logger.warning("Plot functionalities are enabled only in CPython.")
836
+ return False
837
+ from pyedb.generic.plot import plot_matplotlib
838
+
839
+ object_lists = self.get_plot_data(
840
+ nets,
841
+ layers,
842
+ color_by_net,
843
+ outline,
844
+ plot_components_on_top,
845
+ plot_components_on_bottom,
846
+ )
847
+
848
+ if isinstance(size, int): # pragma: no cover
849
+ board_size_x, board_size_y = self._pedb.get_statistics().layout_size
850
+ fig_size_x = size
851
+ fig_size_y = board_size_y * fig_size_x / board_size_x
852
+ size = (fig_size_x, fig_size_y)
853
+
854
+ plot_matplotlib(
855
+ plot_data=object_lists,
856
+ size=size,
857
+ show_legend=show_legend,
858
+ xlabel="X (m)",
859
+ ylabel="Y (m)",
860
+ title=self._pedb.active_cell.GetName(),
861
+ snapshot_path=save_plot,
862
+ axis_equal=True,
863
+ )
864
+
865
+ @pyedb_function_handler()
866
+ def is_power_gound_net(self, netname_list):
867
+ """Determine if one of the nets in a list is power or ground.
868
+
869
+ Parameters
870
+ ----------
871
+ netname_list : list
872
+ List of net names.
873
+
874
+ Returns
875
+ -------
876
+ bool
877
+ ``True`` when one of the net names is ``"power"`` or ``"ground"``, ``False`` otherwise.
878
+ """
879
+ if isinstance(netname_list, str):
880
+ netname_list = [netname_list]
881
+ power_nets_names = list(self.power_nets.keys())
882
+ for netname in netname_list:
883
+ if netname in power_nets_names:
884
+ return True
885
+ return False
886
+
887
+ @pyedb_function_handler()
888
+ def get_dcconnected_net_list(self, ground_nets=["GND"], res_value=0.001):
889
+ """Get the nets connected to the direct current through inductors.
890
+
891
+ .. note::
892
+ Only inductors are considered.
893
+
894
+ Parameters
895
+ ----------
896
+ ground_nets : list, optional
897
+ List of ground nets. The default is ``["GND"]``.
898
+
899
+ Returns
900
+ -------
901
+ list
902
+ List of nets connected to DC through inductors.
903
+ """
904
+ temp_list = []
905
+ for _, comp_obj in self._pedb.components.inductors.items():
906
+ numpins = comp_obj.numpins
907
+
908
+ if numpins == 2:
909
+ nets = comp_obj.nets
910
+ if not set(nets).intersection(set(ground_nets)):
911
+ temp_list.append(set(nets))
912
+ else:
913
+ pass
914
+ for _, comp_obj in self._pedb.components.resistors.items():
915
+ numpins = comp_obj.numpins
916
+
917
+ if numpins == 2 and self._pedb._decompose_variable_value(comp_obj.res_value) <= res_value:
918
+ nets = comp_obj.nets
919
+ if not set(nets).intersection(set(ground_nets)):
920
+ temp_list.append(set(nets))
921
+ else:
922
+ pass
923
+ dcconnected_net_list = []
924
+
925
+ while not not temp_list:
926
+ s = temp_list.pop(0)
927
+ interseciton_flag = False
928
+ for i in temp_list:
929
+ if not not s.intersection(i):
930
+ i.update(s)
931
+ interseciton_flag = True
932
+
933
+ if not interseciton_flag:
934
+ dcconnected_net_list.append(s)
935
+
936
+ return dcconnected_net_list
937
+
938
+ @pyedb_function_handler()
939
+ def get_powertree(self, power_net_name, ground_nets):
940
+ """Retrieve the power tree.
941
+
942
+ Parameters
943
+ ----------
944
+ power_net_name : str
945
+ Name of the power net.
946
+ ground_nets :
947
+
948
+
949
+ Returns
950
+ -------
951
+
952
+ """
953
+ flag_in_ng = False
954
+ net_group = []
955
+ for ng in self.get_dcconnected_net_list(ground_nets):
956
+ if power_net_name in ng:
957
+ flag_in_ng = True
958
+ net_group.extend(ng)
959
+ break
960
+
961
+ if not flag_in_ng:
962
+ net_group.append(power_net_name)
963
+
964
+ component_list = []
965
+ rats = self._pedb.components.get_rats()
966
+ for net in net_group:
967
+ for el in rats:
968
+ if net in el["net_name"]:
969
+ i = 0
970
+ for n in el["net_name"]:
971
+ if n == net:
972
+ df = [el["refdes"][i], el["pin_name"][i], net]
973
+ component_list.append(df)
974
+ i += 1
975
+
976
+ component_type = []
977
+ for el in component_list:
978
+ refdes = el[0]
979
+ comp_type = self._pedb.components._cmp[refdes].type
980
+ component_type.append(comp_type)
981
+ el.append(comp_type)
982
+
983
+ comp_partname = self._pedb.components._cmp[refdes].partname
984
+ el.append(comp_partname)
985
+ pins = self._pedb.components.get_pin_from_component(component=refdes, netName=el[2])
986
+ el.append("-".join([i.GetName() for i in pins]))
987
+
988
+ component_list_columns = [
989
+ "refdes",
990
+ "pin_name",
991
+ "net_name",
992
+ "component_type",
993
+ "component_partname",
994
+ "pin_list",
995
+ ]
996
+ return component_list, component_list_columns, net_group
997
+
998
+ @pyedb_function_handler()
999
+ def get_net_by_name(self, net_name):
1000
+ """Find a net by name."""
1001
+ edb_net = self._edb.cell.net.find_by_name(self._active_layout, net_name)
1002
+ if edb_net is not None:
1003
+ return edb_net
1004
+
1005
+ @pyedb_function_handler()
1006
+ def delete_nets(self, netlist):
1007
+ """Delete one or more nets from EDB.
1008
+
1009
+ .. deprecated:: 0.6.62
1010
+ Use :func:`delete` method instead.
1011
+
1012
+ Parameters
1013
+ ----------
1014
+ netlist : str or list
1015
+ One or more nets to delete.
1016
+
1017
+ Returns
1018
+ -------
1019
+ list
1020
+ List of nets that were deleted.
1021
+
1022
+ Examples
1023
+ --------
1024
+
1025
+ >>> deleted_nets = edb_core.nets.delete(["Net1","Net2"])
1026
+ """
1027
+ warnings.warn("Use :func:`delete` method instead.", DeprecationWarning)
1028
+ return self.delete(netlist=netlist)
1029
+
1030
+ @pyedb_function_handler()
1031
+ def delete(self, netlist):
1032
+ """Delete one or more nets from EDB.
1033
+
1034
+ Parameters
1035
+ ----------
1036
+ netlist : str or list
1037
+ One or more nets to delete.
1038
+
1039
+ Returns
1040
+ -------
1041
+ list
1042
+ List of nets that were deleted.
1043
+
1044
+ Examples
1045
+ --------
1046
+
1047
+ >>> deleted_nets = edb_core.nets.delete(["Net1","Net2"])
1048
+ """
1049
+ if isinstance(netlist, str):
1050
+ netlist = [netlist]
1051
+
1052
+ self._pedb.modeler.delete_primitives(netlist)
1053
+ self._pedb.padstacks.delete_padstack_instances(netlist)
1054
+
1055
+ nets_deleted = []
1056
+
1057
+ for i in self._pedb.nets.nets.values():
1058
+ if i.name in netlist:
1059
+ i.net_object.Delete()
1060
+ nets_deleted.append(i.name)
1061
+ return nets_deleted
1062
+
1063
+ @pyedb_function_handler()
1064
+ def find_or_create_net(self, net_name="", start_with="", contain="", end_with=""):
1065
+ """Find or create the net with the given name in the layout.
1066
+
1067
+ Parameters
1068
+ ----------
1069
+ net_name : str, optional
1070
+ Name of the net to find or create. The default is ``""``.
1071
+
1072
+ start_with : str, optional
1073
+ All net name starting with the string. Not case-sensitive.
1074
+
1075
+ contain : str, optional
1076
+ All net name containing the string. Not case-sensitive.
1077
+
1078
+ end_with : str, optional
1079
+ All net name ending with the string. Not case-sensitive.
1080
+
1081
+ Returns
1082
+ -------
1083
+ object
1084
+ Net Object.
1085
+ """
1086
+ if not net_name and not start_with and not contain and not end_with:
1087
+ net_name = generate_unique_name("NET_")
1088
+ net = self._edb.cell.net.create(self._active_layout, net_name)
1089
+ return net
1090
+ else:
1091
+ if not start_with and not contain and not end_with:
1092
+ net = self._edb.cell.net.find_by_name(self._active_layout, net_name)
1093
+ if net.IsNull():
1094
+ net = self._edb.cell.net.create(self._active_layout, net_name)
1095
+ return net
1096
+ elif start_with:
1097
+ nets_found = [
1098
+ self.nets[net].net_object for net in list(self.nets.keys()) if net.lower().startswith(start_with)
1099
+ ]
1100
+ return nets_found
1101
+ elif start_with and end_with:
1102
+ nets_found = [
1103
+ self.nets[net].net_object
1104
+ for net in list(self.nets.keys())
1105
+ if net.lower().startswith(start_with) and net.lower().endswith(end_with)
1106
+ ]
1107
+ return nets_found
1108
+ elif start_with and contain and end_with:
1109
+ nets_found = [
1110
+ self.nets[net].net_object
1111
+ for net in list(self.nets.keys())
1112
+ if net.lower().startswith(start_with) and net.lower().endswith(end_with) and contain in net.lower()
1113
+ ]
1114
+ return nets_found
1115
+ elif start_with and contain:
1116
+ nets_found = [
1117
+ self.nets[net].net_object
1118
+ for net in list(self.nets.keys())
1119
+ if net.lower().startswith(start_with) and contain in net.lower()
1120
+ ]
1121
+ return nets_found
1122
+ elif contain and end_with:
1123
+ nets_found = [
1124
+ self.nets[net].net_object
1125
+ for net in list(self.nets.keys())
1126
+ if net.lower().endswith(end_with) and contain in net.lower()
1127
+ ]
1128
+ return nets_found
1129
+ elif end_with and not start_with and not contain:
1130
+ nets_found = [
1131
+ self.nets[net].net_object for net in list(self.nets.keys()) if net.lower().endswith(end_with)
1132
+ ]
1133
+ return nets_found
1134
+ elif contain and not start_with and not end_with:
1135
+ nets_found = [self.nets[net].net_object for net in list(self.nets.keys()) if contain in net.lower()]
1136
+ return nets_found
1137
+
1138
+ @pyedb_function_handler()
1139
+ def is_net_in_component(self, component_name, net_name):
1140
+ """Check if a net belongs to a component.
1141
+
1142
+ Parameters
1143
+ ----------
1144
+ component_name : str
1145
+ Name of the component.
1146
+ net_name : str
1147
+ Name of the net.
1148
+
1149
+ Returns
1150
+ -------
1151
+ bool
1152
+ ``True`` if the net is found in component pins.
1153
+
1154
+ """
1155
+ if component_name not in self._pedb.components.components:
1156
+ return False
1157
+ for net in self._pedb.components.components[component_name].nets:
1158
+ if net_name == net:
1159
+ return True
1160
+ return False
1161
+
1162
+ @pyedb_function_handler()
1163
+ def find_and_fix_disjoint_nets(
1164
+ self, net_list=None, keep_only_main_net=False, clean_disjoints_less_than=0.0, order_by_area=False
1165
+ ):
1166
+ """Find and fix disjoint nets from a given netlist.
1167
+
1168
+ .. deprecated::
1169
+ Use new property :func:`edb.layout_validation.disjoint_nets` instead.
1170
+
1171
+ Parameters
1172
+ ----------
1173
+ net_list : str, list, optional
1174
+ List of nets on which check disjoints. If `None` is provided then the algorithm will loop on all nets.
1175
+ keep_only_main_net : bool, optional
1176
+ Remove all secondary nets other than principal one (the one with more objects in it). Default is `False`.
1177
+ clean_disjoints_less_than : bool, optional
1178
+ Clean all disjoint nets with area less than specified area in square meters. Default is `0.0` to disable it.
1179
+ order_by_area : bool, optional
1180
+ Whether if the naming order has to be by number of objects (fastest) or area (slowest but more accurate).
1181
+ Default is ``False``.
1182
+
1183
+ Returns
1184
+ -------
1185
+ List
1186
+ New nets created.
1187
+
1188
+ Examples
1189
+ --------
1190
+
1191
+ >>> renamed_nets = edb_core.nets.find_and_fix_disjoint_nets(["GND","Net2"])
1192
+ """
1193
+ warnings.warn("Use new function :func:`edb.layout_validation.disjoint_nets` instead.", DeprecationWarning)
1194
+ return self._pedb.layout_validation.disjoint_nets(
1195
+ net_list, keep_only_main_net, clean_disjoints_less_than, order_by_area
1196
+ )
1197
+
1198
+ @pyedb_function_handler()
1199
+ def merge_nets_polygons(self, net_list):
1200
+ """Convert paths from net into polygons, evaluate all connected polygons and perform the merge.
1201
+
1202
+ Parameters
1203
+ ----------
1204
+ net_list : str or list[str]
1205
+ Net name of list of net name.
1206
+
1207
+ Returns
1208
+ -------
1209
+ bool
1210
+ ``True`` when successful, ``False`` when failed.
1211
+
1212
+ """
1213
+ if isinstance(net_list, str):
1214
+ net_list = [net_list]
1215
+ return self._pedb.modeler.unite_polygons_on_layer(net_list=net_list)