pyedb 0.49.0__py3-none-any.whl → 0.50.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.

Files changed (79) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_modeler.py +42 -11
  3. pyedb/configuration/cfg_ports_sources.py +9 -1
  4. pyedb/dotnet/database/cell/hierarchy/component.py +6 -6
  5. pyedb/dotnet/database/components.py +3 -3
  6. pyedb/dotnet/database/edb_data/padstacks_data.py +13 -0
  7. pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
  8. pyedb/dotnet/database/edb_data/variables.py +3 -3
  9. pyedb/dotnet/database/materials.py +16 -16
  10. pyedb/dotnet/database/modeler.py +38 -4
  11. pyedb/dotnet/database/sim_setup_data/data/settings.py +28 -0
  12. pyedb/dotnet/database/stackup.py +1 -0
  13. pyedb/dotnet/database/utilities/hfss_simulation_setup.py +5 -6
  14. pyedb/dotnet/edb.py +22 -20
  15. pyedb/extensions/__init__.py +0 -0
  16. pyedb/extensions/via_design_backend.py +681 -0
  17. pyedb/grpc/database/components.py +537 -686
  18. pyedb/grpc/database/control_file.py +458 -149
  19. pyedb/grpc/database/definition/component_def.py +17 -14
  20. pyedb/grpc/database/definition/materials.py +60 -60
  21. pyedb/grpc/database/definition/package_def.py +8 -8
  22. pyedb/grpc/database/definition/padstack_def.py +31 -33
  23. pyedb/grpc/database/definitions.py +6 -4
  24. pyedb/grpc/database/geometry/arc_data.py +5 -5
  25. pyedb/grpc/database/geometry/point_3d_data.py +3 -3
  26. pyedb/grpc/database/geometry/polygon_data.py +5 -5
  27. pyedb/grpc/database/hfss.py +399 -397
  28. pyedb/grpc/database/hierarchy/component.py +60 -58
  29. pyedb/grpc/database/hierarchy/pin_pair_model.py +6 -6
  30. pyedb/grpc/database/hierarchy/pingroup.py +13 -11
  31. pyedb/grpc/database/hierarchy/s_parameter_model.py +1 -1
  32. pyedb/grpc/database/hierarchy/spice_model.py +1 -1
  33. pyedb/grpc/database/layers/layer.py +2 -2
  34. pyedb/grpc/database/layers/stackup_layer.py +144 -44
  35. pyedb/grpc/database/layout/layout.py +12 -12
  36. pyedb/grpc/database/layout/voltage_regulator.py +8 -8
  37. pyedb/grpc/database/layout_validation.py +5 -5
  38. pyedb/grpc/database/modeler.py +248 -245
  39. pyedb/grpc/database/net/differential_pair.py +4 -4
  40. pyedb/grpc/database/net/extended_net.py +7 -8
  41. pyedb/grpc/database/net/net.py +57 -46
  42. pyedb/grpc/database/nets.py +139 -122
  43. pyedb/grpc/database/padstacks.py +174 -190
  44. pyedb/grpc/database/ports/ports.py +23 -17
  45. pyedb/grpc/database/primitive/padstack_instance.py +45 -30
  46. pyedb/grpc/database/primitive/path.py +7 -7
  47. pyedb/grpc/database/primitive/polygon.py +9 -9
  48. pyedb/grpc/database/primitive/primitive.py +21 -21
  49. pyedb/grpc/database/primitive/rectangle.py +1 -1
  50. pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +1 -1
  51. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
  52. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +1 -1
  53. pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +6 -6
  54. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +2 -2
  55. pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +2 -2
  56. pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +1 -1
  57. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +3 -3
  58. pyedb/grpc/database/siwave.py +166 -214
  59. pyedb/grpc/database/source_excitations.py +156 -0
  60. pyedb/grpc/database/stackup.py +415 -316
  61. pyedb/grpc/database/terminal/bundle_terminal.py +12 -12
  62. pyedb/grpc/database/terminal/edge_terminal.py +6 -5
  63. pyedb/grpc/database/terminal/padstack_instance_terminal.py +13 -13
  64. pyedb/grpc/database/terminal/pingroup_terminal.py +12 -12
  65. pyedb/grpc/database/terminal/point_terminal.py +6 -6
  66. pyedb/grpc/database/terminal/terminal.py +26 -26
  67. pyedb/grpc/database/utility/heat_sink.py +5 -5
  68. pyedb/grpc/database/utility/hfss_extent_info.py +21 -21
  69. pyedb/grpc/database/utility/layout_statistics.py +13 -13
  70. pyedb/grpc/database/utility/rlc.py +3 -3
  71. pyedb/grpc/database/utility/sources.py +1 -1
  72. pyedb/grpc/database/utility/sweep_data_distribution.py +1 -1
  73. pyedb/grpc/edb.py +524 -764
  74. {pyedb-0.49.0.dist-info → pyedb-0.50.1.dist-info}/METADATA +1 -1
  75. {pyedb-0.49.0.dist-info → pyedb-0.50.1.dist-info}/RECORD +77 -77
  76. pyedb/extensions/pre_layout_design_toolkit/via_design.py +0 -1151
  77. pyedb/grpc/database/utility/simulation_configuration.py +0 -3305
  78. {pyedb-0.49.0.dist-info → pyedb-0.50.1.dist-info}/LICENSE +0 -0
  79. {pyedb-0.49.0.dist-info → pyedb-0.50.1.dist-info}/WHEEL +0 -0
@@ -49,7 +49,6 @@ from ansys.edb.core.layer.layer_collection import LayerCollection as GrpcLayerCo
49
49
  from ansys.edb.core.layer.layer_collection import LayerTypeSet as GrpcLayerTypeSet
50
50
  from ansys.edb.core.layer.stackup_layer import StackupLayer as GrpcStackupLayer
51
51
  from ansys.edb.core.layout.mcad_model import McadModel as GrpcMcadModel
52
- from ansys.edb.core.utility.transform3d import Transform3D as GrpcTransform3D
53
52
  from ansys.edb.core.utility.value import Value as GrpcValue
54
53
 
55
54
  from pyedb.generic.general_methods import ET, generate_unique_name
@@ -79,7 +78,15 @@ logger = logging.getLogger(__name__)
79
78
 
80
79
 
81
80
  class LayerCollection(GrpcLayerCollection):
82
- """Layer collection."""
81
+ """Manages layer collections in an EDB database.
82
+
83
+ Parameters
84
+ ----------
85
+ pedb : :class:`pyedb.Edb`
86
+ EDB object.
87
+ edb_object : :class:`ansys.edb.core.layer.LayerCollection`
88
+ EDB layer collection object.
89
+ """
83
90
 
84
91
  def __init__(self, pedb, edb_object):
85
92
  super().__init__(edb_object.msg)
@@ -87,12 +94,7 @@ class LayerCollection(GrpcLayerCollection):
87
94
  self._pedb = pedb
88
95
 
89
96
  def update_layout(self):
90
- """Set layer collection into edb.
91
-
92
- Parameters
93
- ----------
94
- stackup
95
- """
97
+ """Update the layout with the current layer collection."""
96
98
  self._pedb.layout.layer_collection = self
97
99
 
98
100
  def add_layer_top(self, name, layer_type="signal", **kwargs):
@@ -102,13 +104,17 @@ class LayerCollection(GrpcLayerCollection):
102
104
  ----------
103
105
  name : str
104
106
  Name of the layer.
105
- layer_type: str, optional
106
- Type of the layer. The default to ``"signal"``. Options are ``"signal"``, ``"dielectric"``
107
- kwargs
107
+ layer_type : str, optional
108
+ Type of the layer. The default is ``"signal"``. Options are ``"signal"`` and ``"dielectric"``.
109
+ **kwargs : dict, optional
110
+ Additional keyword arguments. Possible keys are:
111
+ - ``thickness`` : float, layer thickness.
112
+ - ``material`` : str, layer material.
108
113
 
109
114
  Returns
110
115
  -------
111
-
116
+ :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`
117
+ Layer object created.
112
118
  """
113
119
  thickness = GrpcValue(0.0)
114
120
  if "thickness" in kwargs:
@@ -123,19 +129,24 @@ class LayerCollection(GrpcLayerCollection):
123
129
  return self._layer_collection.add_layer_top(layer)
124
130
 
125
131
  def add_layer_bottom(self, name, layer_type="signal", **kwargs):
126
- """Add a layer on bottom of the stackup.
132
+ """Add a layer at the bottom of the stackup.
127
133
 
128
134
  Parameters
129
135
  ----------
130
136
  name : str
131
137
  Name of the layer.
132
- layer_type: str, optional
133
- Type of the layer. The default to ``"signal"``. Options are ``"signal"``, ``"dielectric"``
134
- kwargs
138
+ layer_type : str, optional
139
+ Type of the layer. The default is ``"signal"``. Options are ``"signal"`` and ``"dielectric"``.
140
+ **kwargs : dict, optional
141
+ Additional keyword arguments. Possible keys are:
142
+ - ``thickness`` : float, layer thickness.
143
+ - ``material`` : str, layer material.
144
+ - ``fill_material`` : str, fill material.
135
145
 
136
146
  Returns
137
147
  -------
138
-
148
+ :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`
149
+ Layer object created.
139
150
  """
140
151
  thickness = GrpcValue(0.0)
141
152
  layer_type_map = {"dielectric": GrpcLayerType.DIELECTRIC_LAYER, "signal": GrpcLayerType.SIGNAL_LAYER}
@@ -158,21 +169,25 @@ class LayerCollection(GrpcLayerCollection):
158
169
  return self._layer_collection.add_layer_bottom(layer)
159
170
 
160
171
  def add_layer_below(self, name, base_layer_name, layer_type="signal", **kwargs):
161
- """Add a layer below a layer.
172
+ """Add a layer below a specified layer.
162
173
 
163
174
  Parameters
164
175
  ----------
165
176
  name : str
166
177
  Name of the layer.
167
- base_layer_name: str
178
+ base_layer_name : str
168
179
  Name of the base layer.
169
- layer_type: str, optional
170
- Type of the layer. The default to ``"signal"``. Options are ``"signal"``, ``"dielectric"``
171
- kwargs
180
+ layer_type : str, optional
181
+ Type of the layer. The default is ``"signal"``. Options are ``"signal"`` and ``"dielectric"``.
182
+ **kwargs : dict, optional
183
+ Additional keyword arguments. Possible keys are:
184
+ - ``thickness`` : float, layer thickness.
185
+ - ``material`` : str, layer material.
172
186
 
173
187
  Returns
174
188
  -------
175
-
189
+ :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`
190
+ Layer object created.
176
191
  """
177
192
  thickness = GrpcValue(0.0)
178
193
  if "thickness" in kwargs:
@@ -195,21 +210,25 @@ class LayerCollection(GrpcLayerCollection):
195
210
  return self._layer_collection.add_layer_below(layer, base_layer_name)
196
211
 
197
212
  def add_layer_above(self, name, base_layer_name, layer_type="signal", **kwargs):
198
- """Add a layer above a layer.
213
+ """Add a layer above a specified layer.
199
214
 
200
215
  Parameters
201
216
  ----------
202
217
  name : str
203
218
  Name of the layer.
204
- base_layer_name: str
219
+ base_layer_name : str
205
220
  Name of the base layer.
206
- layer_type: str, optional
207
- Type of the layer. The default to ``"signal"``. Options are ``"signal"``, ``"dielectric"``
208
- kwargs
221
+ layer_type : str, optional
222
+ Type of the layer. The default is ``"signal"``. Options are ``"signal"`` and ``"dielectric"``.
223
+ **kwargs : dict, optional
224
+ Additional keyword arguments. Possible keys are:
225
+ - ``thickness`` : float, layer thickness.
226
+ - ``material`` : str, layer material.
209
227
 
210
228
  Returns
211
229
  -------
212
-
230
+ :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`
231
+ Layer object created.
213
232
  """
214
233
  thickness = GrpcValue(0.0)
215
234
  if "thickness" in kwargs:
@@ -230,13 +249,15 @@ class LayerCollection(GrpcLayerCollection):
230
249
  ----------
231
250
  name : str
232
251
  Name of the layer.
233
- layer_type: str, optional
234
- Type of the layer. The default is ``"user"``. Options are ``"user"``, ``"outline"``
235
- kwargs
252
+ layer_type : str, optional
253
+ Type of the layer. The default is ``"user"``. Options are ``"user"`` and ``"outline"``.
254
+ **kwargs : dict, optional
255
+ Additional keyword arguments.
236
256
 
237
257
  Returns
238
258
  -------
239
-
259
+ :class:`pyedb.grpc.database.layers.layer.Layer`
260
+ Layer object created.
240
261
  """
241
262
  added_layer = self.add_layer_top(name)
242
263
  added_layer.type = GrpcLayerType.USER_LAYER
@@ -244,29 +265,65 @@ class LayerCollection(GrpcLayerCollection):
244
265
 
245
266
  @property
246
267
  def stackup_layers(self):
247
- """Retrieve the dictionary of signal and dielectric layers."""
268
+ """Retrieve the dictionary of signal and dielectric layers.
269
+
270
+ .. deprecated:: 0.6.61
271
+ Use :func:`layers` instead.
272
+
273
+ Returns
274
+ -------
275
+ dict[str, :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`]
276
+ Dictionary of stackup layers.
277
+ """
248
278
  warnings.warn("Use new property :func:`layers` instead.", DeprecationWarning)
249
279
  return self.layers
250
280
 
251
281
  @property
252
282
  def non_stackup_layers(self):
253
- """Retrieve the dictionary of signal layers."""
283
+ """Retrieve the dictionary of non-stackup layers.
284
+
285
+ Returns
286
+ -------
287
+ dict[str, :class:`pyedb.grpc.database.layers.layer.Layer`]
288
+ Dictionary of non-stackup layers.
289
+ """
254
290
  return {
255
291
  layer.name: Layer(self._pedb, layer) for layer in self.get_layers(GrpcLayerTypeSet.NON_STACKUP_LAYER_SET)
256
292
  }
257
293
 
258
294
  @property
259
295
  def all_layers(self):
296
+ """Retrieve all layers.
297
+
298
+ Returns
299
+ -------
300
+ dict[str, :class:`pyedb.grpc.database.layers.layer.Layer`]
301
+ Dictionary of all layers.
302
+ """
260
303
  return {layer.name: Layer(self._pedb, layer) for layer in self.get_layers(GrpcLayerTypeSet.ALL_LAYER_SET)}
261
304
 
262
305
  @property
263
306
  def signal_layers(self):
307
+ """Retrieve the dictionary of signal layers.
308
+
309
+ Returns
310
+ -------
311
+ dict[str, :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`]
312
+ Dictionary of signal layers.
313
+ """
264
314
  return {
265
315
  layer.name: StackupLayer(self._pedb, layer) for layer in self.get_layers(GrpcLayerTypeSet.SIGNAL_LAYER_SET)
266
316
  }
267
317
 
268
318
  @property
269
319
  def dielectric_layers(self):
320
+ """Retrieve the dictionary of dielectric layers.
321
+
322
+ Returns
323
+ -------
324
+ dict[str, :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`]
325
+ Dictionary of dielectric layers.
326
+ """
270
327
  return {
271
328
  layer.name: StackupLayer(self._pedb, layer)
272
329
  for layer in self.get_layers(GrpcLayerTypeSet.DIELECTRIC_LAYER_SET)
@@ -274,25 +331,46 @@ class LayerCollection(GrpcLayerCollection):
274
331
 
275
332
  @property
276
333
  def layers_by_id(self):
277
- """Retrieve the list of layers with their ids."""
334
+ """Retrieve the list of layers with their IDs.
335
+
336
+ Returns
337
+ -------
338
+ list[list[int, str]]
339
+ List of layers with their IDs and names.
340
+ """
278
341
  return [[obj.id, name] for name, obj in self.all_layers.items()]
279
342
 
280
343
  @property
281
344
  def layers(self):
282
- """Retrieve the dictionary of layers.
345
+ """Retrieve the dictionary of stackup layers (signal and dielectric).
283
346
 
284
347
  Returns
285
348
  -------
286
- Dict[str, :class:`pyedb.grpc.database.edb_data.layer_data.LayerEdbClass`]
349
+ dict[str, :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`]
350
+ Dictionary of stackup layers.
287
351
  """
288
352
  return {obj.name: StackupLayer(self._pedb, obj) for obj in self.get_layers(GrpcLayerTypeSet.STACKUP_LAYER_SET)}
289
353
 
290
354
  def find_layer_by_name(self, name: str):
291
- """Finds a layer with the given name.
355
+ """Find a layer by its name.
356
+
357
+ .. deprecated:: 0.29.0
358
+ Use :func:`find_by_name` instead.
359
+
360
+ Parameters
361
+ ----------
362
+ name : str
363
+ Name of the layer.
292
364
 
293
- . deprecated:: pyedb 0.29.0
294
- Use :func:`find_by_name` instead.
365
+ Returns
366
+ -------
367
+ :class:`ansys.edb.core.layer.Layer`
368
+ Layer object found.
295
369
 
370
+ Raises
371
+ ------
372
+ ValueError
373
+ If no layer with the given name is found.
296
374
  """
297
375
  warnings.warn(
298
376
  "`find_layer_by_name` is deprecated and is now located here "
@@ -306,37 +384,51 @@ class LayerCollection(GrpcLayerCollection):
306
384
 
307
385
 
308
386
  class Stackup(LayerCollection):
309
- """Manages EDB methods for stackup."""
387
+ """Manages EDB methods for stackup operations.
388
+
389
+ Parameters
390
+ ----------
391
+ pedb : :class:`pyedb.Edb`
392
+ EDB object.
393
+ edb_object : :class:`ansys.edb.core.layer.LayerCollection`, optional
394
+ EDB layer collection object. The default is ``None``.
395
+ """
310
396
 
311
397
  def __init__(self, pedb, edb_object=None):
312
398
  super().__init__(pedb, edb_object)
313
399
  self._pedb = pedb
314
400
 
401
+ def __getitem__(self, item):
402
+ if item in self.non_stackup_layers:
403
+ return Layer(self._pedb, self.find_by_name(item))
404
+ elif item in self.layers:
405
+ return StackupLayer(self._pedb, self.find_by_name(item))
406
+ else:
407
+ return None
408
+
315
409
  @property
316
410
  def _logger(self):
317
411
  return self._pedb.logger
318
412
 
319
413
  @property
320
414
  def thickness(self):
321
- """Retrieve Stackup thickness.
415
+ """Retrieve the stackup thickness.
322
416
 
323
417
  Returns
324
418
  -------
325
419
  float
326
- Layout stackup thickness.
327
-
420
+ Stackup thickness.
328
421
  """
329
422
  return self.get_layout_thickness()
330
423
 
331
424
  @property
332
425
  def num_layers(self):
333
- """Retrieve the stackup layer number.
426
+ """Retrieve the number of layers in the stackup.
334
427
 
335
428
  Returns
336
429
  -------
337
430
  int
338
- layer number.
339
-
431
+ Number of layers.
340
432
  """
341
433
  return len(list(self.layers.keys()))
342
434
 
@@ -355,7 +447,7 @@ class Stackup(LayerCollection):
355
447
  Parameters
356
448
  ----------
357
449
  layer_count : int
358
- Number of layer count.
450
+ Number of layers. Must be even.
359
451
  inner_layer_thickness : str, float, optional
360
452
  Thickness of inner conductor layer.
361
453
  outer_layer_thickness : str, float, optional
@@ -365,13 +457,14 @@ class Stackup(LayerCollection):
365
457
  dielectric_material : str, optional
366
458
  Material of dielectric layer.
367
459
  soldermask : bool, optional
368
- Whether to create soldermask layers. The default is``True``.
460
+ Whether to create soldermask layers. The default is ``True``.
369
461
  soldermask_thickness : str, optional
370
462
  Thickness of soldermask layer.
371
463
 
372
464
  Returns
373
465
  -------
374
466
  bool
467
+ ``True`` when successful, ``False`` when failed.
375
468
  """
376
469
  if not np:
377
470
  self._pedb.logger.error("Numpy is needed. Please, install it first.")
@@ -468,22 +561,26 @@ class Stackup(LayerCollection):
468
561
 
469
562
  Returns
470
563
  -------
471
- int, str
472
- Type of the stackup mode, where:
473
-
474
- * 0 - Laminate
475
- * 1 - Overlapping
476
- * 2 - MultiZone
564
+ str
565
+ Type of the stackup mode. Options are:
566
+ - ``"laminate"``
567
+ - ``"overlapping"``
568
+ - ``"multizone"``
477
569
  """
478
570
  return super().mode.name.lower()
479
571
 
480
572
  @mode.setter
481
573
  def mode(self, value):
482
- if value == 0 or value == GrpcLayerCollectionMode.LAMINATE or value == "laminate":
574
+ if value == 0 or value == GrpcLayerCollectionMode.LAMINATE or value == "laminate" or value == "Laminate":
483
575
  super(LayerCollection, self.__class__).mode.__set__(self, GrpcLayerCollectionMode.LAMINATE)
484
- elif value == 1 or value == GrpcLayerCollectionMode.OVERLAPPING or value == "overlapping":
576
+ elif (
577
+ value == 1
578
+ or value == GrpcLayerCollectionMode.OVERLAPPING
579
+ or value == "overlapping"
580
+ or value == "Overlapping"
581
+ ):
485
582
  super(LayerCollection, self.__class__).mode.__set__(self, GrpcLayerCollectionMode.OVERLAPPING)
486
- elif value == 2 or value == GrpcLayerCollectionMode.MULTIZONE or value == "multizone":
583
+ elif value == 2 or value == GrpcLayerCollectionMode.MULTIZONE or value == "multizone" or value == "MultiZone":
487
584
  super(LayerCollection, self.__class__).mode.__set__(self, GrpcLayerCollectionMode.MULTIZONE)
488
585
  self.update_layout()
489
586
 
@@ -492,16 +589,19 @@ class Stackup(LayerCollection):
492
589
 
493
590
  Parameters
494
591
  ----------
495
- layer_clone : :class:`dotnet.database.EDB_Data.EDBLayer`
592
+ layer_clone : :class:`ansys.edb.core.layer.StackupLayer`
593
+ Layer object to apply.
496
594
  operation : str
497
- Options are ``"change_attribute"``, ``"change_name"``,``"change_position"``, ``"insert_below"``,
498
- ``"insert_above"``, ``"add_on_top"``, ``"add_on_bottom"``, ``"non_stackup"``, ``"add_at_elevation"``.
595
+ Operation to perform. Options are ``"change_attribute"``, ``"change_name"``, ``"change_position"``,
596
+ ``"insert_below"``, ``"insert_above"``, ``"add_on_top"``, ``"add_on_bottom"``, ``"non_stackup"``,
597
+ and ``"add_at_elevation"``.
499
598
  base_layer : str, optional
500
599
  Name of the base layer. The default value is ``None``.
501
600
 
502
601
  Returns
503
602
  -------
504
-
603
+ bool
604
+ ``True`` when successful.
505
605
  """
506
606
  lc = self._pedb.layout.layer_collection
507
607
  if operation in ["change_position", "change_attribute", "change_name"]:
@@ -593,17 +693,15 @@ class Stackup(LayerCollection):
593
693
  return result
594
694
 
595
695
  def add_outline_layer(self, outline_name="Outline"):
596
- """Add an outline layer named ``"Outline"`` if it is not present.
696
+ """Add an outline layer named "Outline" if it is not present.
597
697
 
598
698
  Returns
599
699
  -------
600
700
  bool
601
- "True" if successful, ``False`` if failed.
701
+ ``True`` when successful.
602
702
  """
603
703
  return self.add_document_layer(name="Outline", layer_type="outline")
604
704
 
605
- # TODO: Update optional argument material into material_name and fillMaterial into fill_material_name
606
-
607
705
  def add_layer(
608
706
  self,
609
707
  layer_name,
@@ -627,12 +725,29 @@ class Stackup(LayerCollection):
627
725
  base_layer : str, optional
628
726
  Name of the base layer.
629
727
  method : str, optional
630
- Where to insert the new layer. The default is ``"add_on_top"``. Options are ``"add_on_top"``,
631
- ``"add_on_bottom"``, ``"insert_above"``, ``"insert_below"``, ``"add_at_elevation"``,.
728
+ Where to insert the new layer. The default is ``"add_on_top"``. Options are:
729
+ - ``"add_on_top"``
730
+ - ``"add_on_bottom"``
731
+ - ``"insert_above"``
732
+ - ``"insert_below"``
733
+ - ``"add_at_elevation"``
632
734
  layer_type : str, optional
633
- Type of layer. The default is ``"signal"``. Options are ``"signal"``, ``"dielectric"``, ``"conducting"``,
634
- ``"air_lines"``, ``"error"``, ``"symbol"``, ``"measure"``, ``"assembly"``, ``"silkscreen"``,
635
- ``"solder_mask"``, ``"solder_paste"``, ``"glue"``, ``"wirebond"``, ``"hfss_region"``, ``"user"``.
735
+ Type of layer. The default is ``"signal"``. Options are:
736
+ - ``"signal"``
737
+ - ``"dielectric"``
738
+ - ``"conducting"``
739
+ - ``"air_lines"``
740
+ - ``"error"``
741
+ - ``"symbol"``
742
+ - ``"measure"``
743
+ - ``"assembly"``
744
+ - ``"silkscreen"``
745
+ - ``"solder_mask"``
746
+ - ``"solder_paste"``
747
+ - ``"glue"``
748
+ - ``"wirebond"``
749
+ - ``"hfss_region"``
750
+ - ``"user"``
636
751
  material : str, optional
637
752
  Material of the layer.
638
753
  fillMaterial : str, optional
@@ -650,7 +765,8 @@ class Stackup(LayerCollection):
650
765
 
651
766
  Returns
652
767
  -------
653
- :class:`pyedb.dotnet.database.edb_data.layer_data.LayerEdbClass`
768
+ :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`
769
+ Layer object created.
654
770
  """
655
771
  if layer_name in self.layers:
656
772
  logger.error("layer {} exists.".format(layer_name))
@@ -696,6 +812,7 @@ class Stackup(LayerCollection):
696
812
  else:
697
813
  new_layer = self._create_nonstackup_layer(layer_name, layer_type)
698
814
  self._set_layout_stackup(new_layer, "non_stackup")
815
+ return self.non_stackup_layers[layer_name]
699
816
  return self.layers[layer_name]
700
817
 
701
818
  def remove_layer(self, name):
@@ -708,7 +825,8 @@ class Stackup(LayerCollection):
708
825
 
709
826
  Returns
710
827
  -------
711
-
828
+ bool
829
+ ``True`` when successful.
712
830
  """
713
831
  new_layer_collection = LayerCollection.create()
714
832
  for layer_name, lyr in self.layers.items():
@@ -719,19 +837,26 @@ class Stackup(LayerCollection):
719
837
  return True
720
838
 
721
839
  def export(self, fpath, file_format="xml", include_material_with_layer=False):
722
- """Export stackup definition to a CSV or JSON file.
840
+ """Export stackup definition to a file.
723
841
 
724
842
  Parameters
725
843
  ----------
726
844
  fpath : str
727
- File path to csv or json file.
845
+ File path to export to.
728
846
  file_format : str, optional
729
- Format of the file to export. The default is ``"csv"``. Options are ``"csv"``, ``"xlsx"``,
730
- ``"json"``.
731
- include_material_with_layer : bool, optional.
732
- Whether to include the material definition inside layer ones. This parameter is only used
733
- when a JSON file is exported. The default is ``False``, which keeps the material definition
734
- section in the JSON file. If ``True``, the material definition is included inside the layer ones.
847
+ Format of the file to export. The default is ``"xml"``. Options are:
848
+ - ``"csv"``
849
+ - ``"xlsx"``
850
+ - ``"json"``
851
+ - ``"xml"``
852
+ include_material_with_layer : bool, optional
853
+ Whether to include the material definition inside layer objects. This parameter is only used
854
+ when a JSON file is exported. The default is ``False``.
855
+
856
+ Returns
857
+ -------
858
+ bool
859
+ ``True`` when successful.
735
860
 
736
861
  Examples
737
862
  --------
@@ -755,7 +880,7 @@ class Stackup(LayerCollection):
755
880
  return False
756
881
 
757
882
  def export_stackup(self, fpath, file_format="xml", include_material_with_layer=False):
758
- """Export stackup definition to a CSV or JSON file.
883
+ """Export stackup definition to a file.
759
884
 
760
885
  .. deprecated:: 0.6.61
761
886
  Use :func:`export` instead.
@@ -763,14 +888,15 @@ class Stackup(LayerCollection):
763
888
  Parameters
764
889
  ----------
765
890
  fpath : str
766
- File path to CSV or JSON file.
891
+ File path to export to.
767
892
  file_format : str, optional
768
- Format of the file to export. The default is ``"csv"``. Options are ``"csv"``, ``"xlsx"``
769
- and ``"json"``.
770
- include_material_with_layer : bool, optional.
893
+ Format of the file to export. The default is ``"xml"``. Options are:
894
+ - ``"csv"``
895
+ - ``"xlsx"``
896
+ - ``"json"``
897
+ include_material_with_layer : bool, optional
771
898
  Whether to include the material definition inside layer objects. This parameter is only used
772
- when a JSON file is exported. The default is ``False``, which keeps the material definition
773
- section in the JSON file. If ``True``, the material definition is included inside the layer ones.
899
+ when a JSON file is exported. The default is ``False``.
774
900
 
775
901
  Examples
776
902
  --------
@@ -819,9 +945,6 @@ class Stackup(LayerCollection):
819
945
  layers_out = {}
820
946
  for k, v in self.layers.items():
821
947
  data = v._json_format()
822
- # FIXME: Update the API to avoid providing following information to our users
823
- del data["pedb"]
824
- del data["edb_object"]
825
948
  layers_out[k] = data
826
949
  if v.material in self._pedb.materials.materials:
827
950
  layer_material = self._pedb.materials.materials[v.material]
@@ -845,57 +968,6 @@ class Stackup(LayerCollection):
845
968
  else:
846
969
  return False
847
970
 
848
- # TODO: This method might need some refactoring
849
-
850
- def _import_layer_stackup(self, input_file=None):
851
- if input_file:
852
- f = open(input_file)
853
- json_dict = json.load(f) # pragma: no cover
854
- for k, v in json_dict.items():
855
- if k == "materials":
856
- for material in v.values():
857
- material_name = material["name"]
858
- del material["name"]
859
- if material_name not in self._pedb.materials:
860
- self._pedb.materials.add_material(material_name, **material)
861
- else:
862
- self._pedb.materials.update_material(material_name, material)
863
- if k == "layers":
864
- if len(list(v.values())) == len(list(self.layers.values())):
865
- imported_layers_list = [l_dict["name"] for l_dict in list(v.values())]
866
- layout_layer_list = list(self.layers.keys())
867
- for layer_name in imported_layers_list:
868
- layer_index = imported_layers_list.index(layer_name)
869
- if layout_layer_list[layer_index] != layer_name:
870
- self.layers[layout_layer_list[layer_index]].name = layer_name
871
- prev_layer = None
872
- for layer_name, layer in v.items():
873
- if layer["name"] not in self.layers:
874
- if not prev_layer:
875
- self.add_layer(
876
- layer_name,
877
- method="add_on_top",
878
- layer_type=layer["type"],
879
- material=layer["material"],
880
- fillMaterial=layer["dielectric_fill"],
881
- thickness=layer["thickness"],
882
- )
883
- prev_layer = layer_name
884
- else:
885
- self.add_layer(
886
- layer_name,
887
- base_layer=layer_name,
888
- method="insert_below",
889
- layer_type=layer["type"],
890
- material=layer["material"],
891
- fillMaterial=layer["dielectric_fill"],
892
- thickness=layer["thickness"],
893
- )
894
- prev_layer = layer_name
895
- if layer_name in self.layers:
896
- self.layers[layer["name"]]._load_layer(layer)
897
- return True
898
-
899
971
  def limits(self, only_metals=False):
900
972
  """Retrieve stackup limits.
901
973
 
@@ -906,8 +978,12 @@ class Stackup(LayerCollection):
906
978
 
907
979
  Returns
908
980
  -------
909
- bool
910
- ``True`` when successful, ``False`` when failed.
981
+ tuple
982
+ Tuple containing:
983
+ - Upper layer name
984
+ - Upper layer top elevation
985
+ - Lower layer name
986
+ - Lower layer bottom elevation
911
987
  """
912
988
  if only_metals:
913
989
  input_layers = GrpcLayerTypeSet.SIGNAL_LAYER_SET
@@ -927,11 +1003,11 @@ class Stackup(LayerCollection):
927
1003
  Returns
928
1004
  -------
929
1005
  bool
930
- ``True`` when succeed ``False`` if not.
1006
+ ``True`` when successful.
931
1007
 
932
1008
  Examples
933
1009
  --------
934
- >>> edb = Edb(edbpath=targetfile, edbversion="2021.2")
1010
+ >>> edb = Edb(edbpath=targetfile, edbversion="2021.2")
935
1011
  >>> edb.stackup.flip_design()
936
1012
  >>> edb.save()
937
1013
  >>> edb.close_edb()
@@ -1027,7 +1103,7 @@ class Stackup(LayerCollection):
1027
1103
  Returns
1028
1104
  -------
1029
1105
  float
1030
- The thickness value.
1106
+ Thickness value.
1031
1107
  """
1032
1108
  layers = list(self.layers.values())
1033
1109
  layers.sort(key=lambda lay: lay.lower_elevation)
@@ -1039,10 +1115,14 @@ class Stackup(LayerCollection):
1039
1115
  return round(thickness, 7)
1040
1116
 
1041
1117
  def _get_solder_height(self, layer_name):
1118
+ height = 0.0
1042
1119
  for _, val in self._pedb.components.instances.items():
1043
- if val.solder_ball_height and val.placement_layer == layer_name:
1044
- return val.solder_ball_height
1045
- return 0
1120
+ try:
1121
+ if val.solder_ball_height and val.placement_layer == layer_name:
1122
+ height = val.solder_ball_height
1123
+ except:
1124
+ pass
1125
+ return height
1046
1126
 
1047
1127
  def _remove_solder_pec(self, layer_name):
1048
1128
  for _, val in self._pedb.components.instances.items():
@@ -1052,16 +1132,18 @@ class Stackup(LayerCollection):
1052
1132
  port_property.reference_size_auto = False
1053
1133
  port_property.reference_size = (GrpcValue(0.0), GrpcValue(0.0))
1054
1134
  comp_prop.port_property = port_property
1055
- val.edbcomponent.component_property = comp_prop
1135
+ val.component_property = comp_prop
1056
1136
 
1057
1137
  def adjust_solder_dielectrics(self):
1058
- """Adjust the stack-up by adding or modifying dielectric layers that contains Solder Balls.
1059
- This method identifies the solder-ball height and adjust the dielectric thickness on top (or bottom) to fit
1060
- the thickness in order to merge another layout.
1138
+ """Adjust the stack-up by adding or modifying dielectric layers that contain solder balls.
1139
+
1140
+ This method identifies the solder-ball height and adjusts the dielectric thickness on top (or bottom)
1141
+ to fit the thickness in order to merge another layout.
1061
1142
 
1062
1143
  Returns
1063
1144
  -------
1064
1145
  bool
1146
+ ``True`` when successful.
1065
1147
  """
1066
1148
  for el, val in self._pedb.components.instances.items():
1067
1149
  if val.solder_ball_height:
@@ -1099,33 +1181,33 @@ class Stackup(LayerCollection):
1099
1181
  flipped_stackup=True,
1100
1182
  place_on_top=True,
1101
1183
  ):
1102
- """Place current Cell into another cell using layer placement method.
1103
- Flip the current layer stackup of a layout if requested. Transform parameters currently not supported.
1184
+ """Place current cell into another cell using layer placement method.
1185
+
1186
+ Flip the current layer stackup of a layout if requested.
1104
1187
 
1105
1188
  Parameters
1106
1189
  ----------
1107
- edb : Edb
1108
- Cell on which to place the current layout. If None the Cell will be applied on an empty new Cell.
1109
- angle : double, optional
1110
- The rotation angle applied on the design.
1111
- offset_x : double, optional
1112
- The x offset value.
1113
- offset_y : double, optional
1114
- The y offset value.
1190
+ edb : :class:`pyedb.Edb`
1191
+ Target Edb object.
1192
+ angle : float, optional
1193
+ Rotation angle in degrees. The default is ``0.0``.
1194
+ offset_x : float, optional
1195
+ X offset value. The default is ``0.0``.
1196
+ offset_y : float, optional
1197
+ Y offset value. The default is ``0.0``.
1115
1198
  flipped_stackup : bool, optional
1116
- Either if the current layout is inverted.
1117
- If `True` and place_on_top is `True` the stackup will be flipped before the merge.
1199
+ Whether to flip the current layout. The default is ``True``.
1118
1200
  place_on_top : bool, optional
1119
- Either if place the current layout on Top or Bottom of destination Layout.
1201
+ Whether to place the current layout on top of the destination layout. The default is ``True``.
1120
1202
 
1121
1203
  Returns
1122
1204
  -------
1123
1205
  bool
1124
- ``True`` when succeed ``False`` if not.
1206
+ ``True`` when successful.
1125
1207
 
1126
1208
  Examples
1127
1209
  --------
1128
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1210
+ >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1129
1211
  >>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
1130
1212
 
1131
1213
  >>> hosting_cmp = edb1.components.get_component_by_name("U100")
@@ -1188,36 +1270,35 @@ class Stackup(LayerCollection):
1188
1270
  place_on_top=True,
1189
1271
  solder_height=0,
1190
1272
  ):
1191
- """Place current Cell into another cell using 3d placement method.
1192
- Flip the current layer stackup of a layout if requested. Transform parameters currently not supported.
1273
+ """Place current cell into another cell using 3D placement method.
1274
+
1275
+ Flip the current layer stackup of a layout if requested.
1193
1276
 
1194
1277
  Parameters
1195
1278
  ----------
1196
- edb : Edb
1197
- Cell on which to place the current layout. If None the Cell will be applied on an empty new Cell.
1198
- angle : double, optional
1199
- The rotation angle applied on the design.
1200
- offset_x : double, optional
1201
- The x offset value.
1202
- offset_y : double, optional
1203
- The y offset value.
1279
+ edb : :class:`pyedb.Edb`
1280
+ Target Edb object.
1281
+ angle : float, optional
1282
+ Rotation angle in degrees. The default is ``0.0``.
1283
+ offset_x : float, optional
1284
+ X offset value. The default is ``0.0``.
1285
+ offset_y : float, optional
1286
+ Y offset value. The default is ``0.0``.
1204
1287
  flipped_stackup : bool, optional
1205
- Either if the current layout is inverted.
1206
- If `True` and place_on_top is `True` the stackup will be flipped before the merge.
1288
+ Whether to flip the current layout. The default is ``True``.
1207
1289
  place_on_top : bool, optional
1208
- Either if place the current layout on Top or Bottom of destination Layout.
1290
+ Whether to place the current layout on top of the destination layout. The default is ``True``.
1209
1291
  solder_height : float, optional
1210
- Solder Ball or Bumps eight.
1211
- This value will be added to the elevation to align the two layouts.
1292
+ Solder ball or bumps height. This value will be added to the elevation to align the two layouts.
1212
1293
 
1213
1294
  Returns
1214
1295
  -------
1215
1296
  bool
1216
- ``True`` when succeed ``False`` if not.
1297
+ ``True`` when successful.
1217
1298
 
1218
1299
  Examples
1219
1300
  --------
1220
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1301
+ >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1221
1302
  >>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
1222
1303
  >>> hosting_cmp = edb1.components.get_component_by_name("U100")
1223
1304
  >>> mounted_cmp = edb2.components.get_component_by_name("BGA")
@@ -1260,7 +1341,7 @@ class Stackup(LayerCollection):
1260
1341
  _offset_y = GrpcValue(offset_y)
1261
1342
 
1262
1343
  if edb_cell.name not in self._pedb.cell_names:
1263
- list_cells = self._pedb.copy_cells(edb_cell.api_object)
1344
+ list_cells = self._pedb.copy_cells(edb_cell)
1264
1345
  edb_cell = list_cells[0]
1265
1346
  self._pedb.layout.cell.is_blackbox = True
1266
1347
  cell_inst2 = GrpcCellInstance.create(
@@ -1271,9 +1352,9 @@ class Stackup(LayerCollection):
1271
1352
  stackup_source = self._pedb.layout.layer_collection
1272
1353
 
1273
1354
  if place_on_top:
1274
- cell_inst2.placement_layer = stackup_target.Layers(GrpcLayerTypeSet.SIGNAL_LAYER_SET)[0]
1355
+ cell_inst2.placement_layer = list(LayerCollection(self._pedb, stackup_target).layers.values())[0]
1275
1356
  else:
1276
- cell_inst2.placement_layer = stackup_target.Layers(GrpcLayerTypeSet.SIGNAL_LAYER_SET)[-1]
1357
+ cell_inst2.placement_layer = list(LayerCollection(self._pedb, stackup_target).layers.values())[-1]
1277
1358
  cell_inst2.placement_3d = True
1278
1359
  res = stackup_target.get_top_bottom_stackup_layers(GrpcLayerTypeSet.SIGNAL_LAYER_SET)
1279
1360
  target_top_elevation = res[1]
@@ -1301,7 +1382,13 @@ class Stackup(LayerCollection):
1301
1382
  point_loc = GrpcPoint3DData(zero_data, zero_data, zero_data)
1302
1383
  point_from = GrpcPoint3DData(one_data, zero_data, zero_data)
1303
1384
  point_to = GrpcPoint3DData(math.cos(_angle), -1 * math.sin(_angle), zero_data)
1304
- cell_inst2.transform3d = GrpcTransform3D(point_loc, point_from, point_to, rotation, point3d_t) # TODO check
1385
+ transform = cell_inst2.transform3d.create_from_one_axis_to_another(from_axis=point_from, to_axis=point_to)
1386
+ cell_inst2.transform3d = transform
1387
+ transform = cell_inst2.transform3d.create_from_axis_and_angle(axis=point_loc, angle=angle)
1388
+ cell_inst2.transform3d = transform
1389
+ transform = cell_inst2.transform3d.create_from_offset(offset=point3d_t)
1390
+ cell_inst2.transform3d = transform
1391
+ # TODO check if component is properly placed.
1305
1392
  return True
1306
1393
 
1307
1394
  def place_instance(
@@ -1315,48 +1402,31 @@ class Stackup(LayerCollection):
1315
1402
  place_on_top=True,
1316
1403
  solder_height=0,
1317
1404
  ):
1318
- """Place current Cell into another cell using 3d placement method.
1319
- Flip the current layer stackup of a layout if requested. Transform parameters currently not supported.
1405
+ """Place a component instance in the layout using 3D placement.
1320
1406
 
1321
1407
  Parameters
1322
1408
  ----------
1323
- component_edb : Edb
1324
- Cell to place in the current layout.
1325
- angle : double, optional
1326
- The rotation angle applied on the design.
1327
- offset_x : double, optional
1328
- The x offset value.
1329
- The default value is ``0.0``.
1330
- offset_y : double, optional
1331
- The y offset value.
1332
- The default value is ``0.0``.
1333
- offset_z : double, optional
1334
- The z offset value. (i.e. elevation offset for placement relative to the top layer conductor).
1335
- The default value is ``0.0``, which places the cell layout on top of the top conductor
1336
- layer of the target EDB.
1409
+ component_edb : :class:`pyedb.Edb`
1410
+ Component Edb object to place.
1411
+ angle : float, optional
1412
+ Rotation angle in degrees. The default is ``0.0``.
1413
+ offset_x : float, optional
1414
+ X offset value. The default is ``0.0``.
1415
+ offset_y : float, optional
1416
+ Y offset value. The default is ``0.0``.
1417
+ offset_z : float, optional
1418
+ Z offset value (elevation offset). The default is ``0.0``.
1337
1419
  flipped_stackup : bool, optional
1338
- Either if the current layout is inverted.
1339
- If `True` and place_on_top is `True` the stackup will be flipped before the merge.
1420
+ Whether to flip the component stackup. The default is ``True``.
1340
1421
  place_on_top : bool, optional
1341
- Either if place the component_edb layout on Top or Bottom of destination Layout.
1422
+ Whether to place the component on top of the target layout. The default is ``True``.
1342
1423
  solder_height : float, optional
1343
- Solder Ball or Bumps eight.
1344
- This value will be added to the elevation to align the two layouts.
1424
+ Solder ball or bumps height. The default is ``0``.
1345
1425
 
1346
1426
  Returns
1347
1427
  -------
1348
- bool
1349
- ``True`` when succeed ``False`` if not.
1350
-
1351
- Examples
1352
- --------
1353
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1354
- >>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
1355
- >>> hosting_cmp = edb1.components.get_component_by_name("U100")
1356
- >>> mounted_cmp = edb2.components.get_component_by_name("BGA")
1357
- >>> edb1.stackup.place_instance(edb2, angle=0.0, offset_x="1mm",
1358
- ... offset_y="2mm", flipped_stackup=False, place_on_top=True,
1359
- ... )
1428
+ :class:`ansys.edb.core.hierarchy.CellInstance`
1429
+ Cell instance created.
1360
1430
  """
1361
1431
  _angle = angle * math.pi / 180.0
1362
1432
 
@@ -1392,7 +1462,7 @@ class Stackup(LayerCollection):
1392
1462
  _offset_y = GrpcValue(offset_y)
1393
1463
 
1394
1464
  if edb_cell.name not in self._pedb.cell_names:
1395
- list_cells = self._pedb.copy_cells(edb_cell.api_object)
1465
+ list_cells = self._pedb.copy_cells(edb_cell)
1396
1466
  edb_cell = list_cells[0]
1397
1467
  for cell in self._pedb.active_db.top_circuit_cells:
1398
1468
  if cell.name == edb_cell.name:
@@ -1444,7 +1514,13 @@ class Stackup(LayerCollection):
1444
1514
  point_loc = GrpcPoint3DData(zero_data, zero_data, zero_data)
1445
1515
  point_from = GrpcPoint3DData(one_data, zero_data, zero_data)
1446
1516
  point_to = GrpcPoint3DData(math.cos(_angle), -1 * math.sin(_angle), zero_data)
1447
- cell_inst2.transform3d = (point_loc, point_from, point_to, rotation, point3d_t) # TODO check
1517
+ transform = cell_inst2.transform3d.create_from_axis_and_angle(axis=point_loc, angle=angle)
1518
+ cell_inst2.transform3d = transform
1519
+ transform = cell_inst2.transform3d.create_from_one_axis_to_another(point_from, point_to)
1520
+ cell_inst2.transform3d = transform
1521
+ transform = cell_inst2.transform3d.create_from_offset(point3d_t)
1522
+ cell_inst2.transform3d = transform
1523
+ # TODO check is position is correct.
1448
1524
  return cell_inst2
1449
1525
 
1450
1526
  def place_a3dcomp_3d_placement(
@@ -1455,51 +1531,46 @@ class Stackup(LayerCollection):
1455
1531
  offset_y=0.0,
1456
1532
  offset_z=0.0,
1457
1533
  place_on_top=True,
1458
- ):
1459
- """Place a 3D Component into current layout.
1460
- 3D Component ports are not visible via EDB. They will be visible after the EDB has been opened in Ansys
1461
- Electronics Desktop as a project.
1534
+ ) -> bool:
1535
+ """Place a 3D component into the current layout.
1536
+
1537
+ 3D Component ports are not visible via EDB. They will be visible after the EDB has been opened in Ansys
1538
+ Electronics Desktop as a project.
1462
1539
 
1463
1540
  Parameters
1464
1541
  ----------
1465
1542
  a3dcomp_path : str
1466
- Path to the 3D Component file (\\*.a3dcomp) to place.
1467
- angle : double, optional
1543
+ Path to the 3D Component file (``*.a3dcomp``) to place.
1544
+ angle : float, optional
1468
1545
  Clockwise rotation angle applied to the a3dcomp.
1469
- offset_x : double, optional
1470
- The x offset value.
1471
- The default value is ``0.0``.
1472
- offset_y : double, optional
1473
- The y offset value.
1474
- The default value is ``0.0``.
1475
- offset_z : double, optional
1476
- The z offset value. (i.e. elevation)
1477
- The default value is ``0.0``.
1546
+ offset_x : float, optional
1547
+ X offset value. The default is ``0.0``.
1548
+ offset_y : float, optional
1549
+ Y offset value. The default is ``0.0``.
1550
+ offset_z : float, optional
1551
+ Z offset value (elevation). The default is ``0.0``.
1478
1552
  place_on_top : bool, optional
1479
- Whether to place the 3D Component on the top or the bottom of this layout.
1480
- If ``False`` then the 3D Component will also be flipped over around its X axis.
1553
+ Whether to place the 3D component on the top or the bottom of this layout. If ``False``, the 3D component
1554
+ will be flipped over around its X axis.
1481
1555
 
1482
1556
  Returns
1483
1557
  -------
1484
1558
  bool
1485
- ``True`` if successful and ``False`` if not.
1559
+ ``True`` if successful, ``False`` if not.
1486
1560
 
1487
1561
  Examples
1488
1562
  --------
1489
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1563
+ >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1490
1564
  >>> a3dcomp_path = "connector.a3dcomp"
1491
1565
  >>> edb1.stackup.place_a3dcomp_3d_placement(a3dcomp_path, angle=0.0, offset_x="1mm",
1492
1566
  ... offset_y="2mm", flipped_stackup=False, place_on_top=True,
1493
1567
  ... )
1494
1568
  """
1495
- zero_data = GrpcValue(0.0)
1496
- one_data = GrpcValue(1.0)
1497
- local_origin = GrpcPoint3DData(0.0, 0.0, 0.0)
1498
1569
  rotation_axis_from = GrpcPoint3DData(1.0, 0.0, 0.0)
1499
1570
  _angle = angle * math.pi / 180.0
1500
1571
  rotation_axis_to = GrpcPoint3DData(math.cos(_angle), -1 * math.sin(_angle), 0.0)
1501
1572
 
1502
- stackup_target = GrpcLayerCollection(self._pedb.layout.layer_collection)
1573
+ stackup_target = LayerCollection(self._pedb, self._pedb.layout.layer_collection)
1503
1574
  res = stackup_target.get_top_bottom_stackup_layers(GrpcLayerTypeSet.SIGNAL_LAYER_SET)
1504
1575
  target_top_elevation = res[1]
1505
1576
  target_bottom_elevation = res[3]
@@ -1521,9 +1592,12 @@ class Stackup(LayerCollection):
1521
1592
  return False
1522
1593
 
1523
1594
  mcad_model.cell_instance.placement_3d = True
1524
- mcad_model.cell_instance.transform3d = GrpcTransform3D(
1525
- local_origin, rotation_axis_from, rotation_axis_to, flip_angle, location
1595
+ transform_rotation = mcad_model.cell_instance.transform3d.create_from_axis_and_angle(
1596
+ axis=rotation_axis_from, angle=flip_angle.value
1526
1597
  )
1598
+ mcad_model.cell_instance.transform3d = transform_rotation
1599
+ transform_translation = mcad_model.cell_instance.transform3d.create_from_offset(offset=location)
1600
+ mcad_model.cell_instance.transform3d = transform_translation
1527
1601
  return True
1528
1602
 
1529
1603
  def residual_copper_area_per_layer(self):
@@ -1532,11 +1606,11 @@ class Stackup(LayerCollection):
1532
1606
  Returns
1533
1607
  -------
1534
1608
  dict
1535
- Copper area per layer.
1609
+ Dictionary of copper area per layer.
1536
1610
 
1537
1611
  Examples
1538
1612
  --------
1539
- >>> edb = Edb(edbpath=targetfile1, edbversion="2021.2")
1613
+ >>> edb = Edb(edbpath=targetfile1, edbversion="2021.2")
1540
1614
  >>> edb.stackup.residual_copper_area_per_layer()
1541
1615
  """
1542
1616
  temp_data = {name: 0 for name, _ in self.signal_layers.items()}
@@ -1555,10 +1629,21 @@ class Stackup(LayerCollection):
1555
1629
  temp_data = {name: area / outline_area * 100 for name, area in temp_data.items()}
1556
1630
  return temp_data
1557
1631
 
1558
- # TODO: This method might need some refactoring
1559
-
1560
1632
  def _import_dict(self, json_dict, rename=False):
1561
- """Import stackup from a dictionary."""
1633
+ """Import stackup from a dictionary.
1634
+
1635
+ Parameters
1636
+ ----------
1637
+ json_dict : dict
1638
+ Dictionary containing stackup information.
1639
+ rename : bool, optional
1640
+ Whether to rename layers. The default is ``False``.
1641
+
1642
+ Returns
1643
+ -------
1644
+ bool
1645
+ ``True`` when successful.
1646
+ """
1562
1647
  if not "materials" in json_dict:
1563
1648
  self._logger.info("Configuration file does not have material definition. Using aedb and syslib materials.")
1564
1649
  else:
@@ -1699,7 +1784,20 @@ class Stackup(LayerCollection):
1699
1784
  return True
1700
1785
 
1701
1786
  def _import_json(self, file_path, rename=False):
1702
- """Import stackup from a json file."""
1787
+ """Import stackup from a JSON file.
1788
+
1789
+ Parameters
1790
+ ----------
1791
+ file_path : str
1792
+ Path to the JSON file.
1793
+ rename : bool, optional
1794
+ Whether to rename layers. The default is ``False``.
1795
+
1796
+ Returns
1797
+ -------
1798
+ bool
1799
+ ``True`` when successful.
1800
+ """
1703
1801
  if file_path:
1704
1802
  f = open(file_path)
1705
1803
  json_dict = json.load(f) # pragma: no cover
@@ -1712,6 +1810,11 @@ class Stackup(LayerCollection):
1712
1810
  ----------
1713
1811
  file_path : str
1714
1812
  File path to the CSV file.
1813
+
1814
+ Returns
1815
+ -------
1816
+ bool
1817
+ ``True`` when successful.
1715
1818
  """
1716
1819
  if not pd:
1717
1820
  self._pedb.logger.error("Pandas is needed. You must install it first.")
@@ -1753,16 +1856,19 @@ class Stackup(LayerCollection):
1753
1856
 
1754
1857
  Parameters
1755
1858
  ----------
1756
- layers: dict
1859
+ layers : dict, optional
1757
1860
  Dictionary containing layer information.
1758
- materials: dict
1861
+ materials : dict, optional
1759
1862
  Dictionary containing material information.
1760
- roughness: dict
1863
+ roughness : dict, optional
1761
1864
  Dictionary containing roughness information.
1865
+ non_stackup_layers : dict, optional
1866
+ Dictionary containing non-stackup layer information.
1762
1867
 
1763
1868
  Returns
1764
1869
  -------
1765
-
1870
+ bool
1871
+ ``True`` when successful.
1766
1872
  """
1767
1873
  if materials:
1768
1874
  self._add_materials_from_dictionary(materials)
@@ -1879,9 +1985,14 @@ class Stackup(LayerCollection):
1879
1985
  def _get(self):
1880
1986
  """Get stackup information from layout.
1881
1987
 
1882
- Returns:
1883
- tuple: (dict, dict, dict)
1884
- layers, materials, roughness_models
1988
+ Returns
1989
+ -------
1990
+ tuple
1991
+ Tuple containing:
1992
+ - layers (dict)
1993
+ - materials (dict)
1994
+ - roughness_models (dict)
1995
+ - non_stackup_layers (dict)
1885
1996
  """
1886
1997
  layers = OrderedDict()
1887
1998
  roughness_models = OrderedDict()
@@ -1946,39 +2057,30 @@ class Stackup(LayerCollection):
1946
2057
  def _add_materials_from_dictionary(self, material_dict):
1947
2058
  materials = self.self._pedb.materials.materials
1948
2059
  for name, material_properties in material_dict.items():
1949
- if not name in materials:
1950
- if "Conductivity" in material_properties:
1951
- materials.add_conductor_material(name, material_properties["Conductivity"])
1952
- else:
1953
- materials.add_dielectric_material(
1954
- name,
1955
- material_properties["Permittivity"],
1956
- material_properties["DielectricLossTangent"],
1957
- )
2060
+ if "Conductivity" in material_properties:
2061
+ materials.add_conductor_material(name, material_properties["Conductivity"])
1958
2062
  else:
1959
- material = materials[name]
1960
- if "Conductivity" in material_properties:
1961
- material.conductivity = material_properties["Conductivity"]
1962
- else:
1963
- material.permittivity = material_properties["Permittivity"]
1964
- material.loss_tanget = material_properties["DielectricLossTangent"]
2063
+ materials.add_dielectric_material(
2064
+ name,
2065
+ material_properties["Permittivity"],
2066
+ material_properties["DielectricLossTangent"],
2067
+ )
1965
2068
  return True
1966
2069
 
1967
2070
  def _import_xml(self, file_path, rename=False):
1968
- """Read external xml file and convert into json file.
1969
- You can use xml file to import layer stackup but using json file is recommended.
1970
- see :class:`pyedb.dotnet.database.edb_data.simulation_configuration.SimulationConfiguration´ class to
1971
- generate files`.
2071
+ """Read external XML file and convert into JSON format.
1972
2072
 
1973
2073
  Parameters
1974
2074
  ----------
1975
- file_path: str
2075
+ file_path : str
1976
2076
  Path to external XML file.
2077
+ rename : bool, optional
2078
+ Whether to rename layers. The default is ``False``.
1977
2079
 
1978
2080
  Returns
1979
2081
  -------
1980
2082
  bool
1981
- ``True`` when successful, ``False`` when failed.
2083
+ ``True`` when successful.
1982
2084
  """
1983
2085
  if not colors:
1984
2086
  self._pedb.logger.error("Matplotlib is needed. Please, install it first.")
@@ -2037,17 +2139,17 @@ class Stackup(LayerCollection):
2037
2139
  return self._pedb.configuration.load(cfg, apply_file=True)
2038
2140
 
2039
2141
  def _export_xml(self, file_path):
2040
- """Export stackup information to an external XMLfile.
2142
+ """Export stackup information to an external XML file.
2041
2143
 
2042
2144
  Parameters
2043
2145
  ----------
2044
- file_path: str
2146
+ file_path : str
2045
2147
  Path to external XML file.
2046
2148
 
2047
2149
  Returns
2048
2150
  -------
2049
2151
  bool
2050
- ``True`` when successful, ``False`` when failed.
2152
+ ``True`` when successful.
2051
2153
  """
2052
2154
  layers, materials, roughness, non_stackup_layers = self._get()
2053
2155
 
@@ -2087,25 +2189,23 @@ class Stackup(LayerCollection):
2087
2189
  return True
2088
2190
 
2089
2191
  def load(self, file_path, rename=False):
2090
- """Import stackup from a file. The file format can be XML, CSV, or JSON. Valid control file must
2091
- have the same number of signal layers. Signals layers can be renamed. Dielectric layers can be
2092
- added and deleted.
2192
+ """Import stackup from a file.
2093
2193
 
2194
+ Supported formats: XML, CSV, JSON.
2094
2195
 
2095
2196
  Parameters
2096
2197
  ----------
2097
- file_path : str, dict
2098
- Path to stackup file or dict with stackup details.
2099
- rename : bool
2100
- If rename is ``False`` then layer in layout not found in the stackup file are deleted.
2101
- Otherwise, if the number of layer in the stackup file equals the number of stackup layer
2102
- in the layout, layers are renamed according the file.
2103
- Note that layer order matters, and has to be writtent from top to bottom layer in the file.
2198
+ file_path : str or dict
2199
+ Path to stackup file or dictionary with stackup details.
2200
+ rename : bool, optional
2201
+ If ``False``, layers in layout not found in the stackup file are deleted.
2202
+ If ``True`` and the number of layers in the stackup file equals the number of stackup layers
2203
+ in the layout, layers are renamed according to the file.
2104
2204
 
2105
2205
  Returns
2106
2206
  -------
2107
2207
  bool
2108
- ``True`` when successful, ``False`` when failed.
2208
+ ``True`` when successful.
2109
2209
 
2110
2210
  Examples
2111
2211
  --------
@@ -2135,32 +2235,31 @@ class Stackup(LayerCollection):
2135
2235
  scale_elevation=True,
2136
2236
  show=True,
2137
2237
  ):
2138
- """Plot current stackup and, optionally, overlap padstack definitions.
2139
- Plot supports only 'Laminate' and 'Overlapping' stackup types.
2238
+ """Plot the current stackup and optionally overlap padstack definitions.
2239
+
2240
+ Only supports 'Laminate' and 'Overlapping' stackup types.
2140
2241
 
2141
2242
  Parameters
2142
2243
  ----------
2143
2244
  save_plot : str, optional
2144
- If a path is specified the plot will be saved in this location.
2145
- If ``save_plot`` is provided, the ``show`` parameter is ignored.
2245
+ Path to save the plot image. If provided, ``show`` is ignored.
2146
2246
  size : tuple, optional
2147
- Image size in pixel (width, height). Default value is ``(2000, 1500)``
2148
- plot_definitions : str, list, optional
2149
- List of padstack definitions to plot on the stackup.
2150
- It is supported only for Laminate mode.
2151
- first_layer : str or :class:`pyedb.dotnet.database.edb_data.layer_data.LayerEdbClass`
2152
- First layer to plot from the bottom. Default is `None` to start plotting from bottom.
2153
- last_layer : str or :class:`pyedb.dotnet.database.edb_data.layer_data.LayerEdbClass`
2154
- Last layer to plot from the bottom. Default is `None` to plot up to top layer.
2247
+ Image size in pixels (width, height). Default is ``(2000, 1500)``.
2248
+ plot_definitions : str or list, optional
2249
+ List of padstack definitions to plot on the stackup. Only supported for Laminate mode.
2250
+ first_layer : str or :class:`pyedb.grpc.database.layers.layer.Layer`, optional
2251
+ First layer to plot from the bottom. Default is ``None`` (start from bottom).
2252
+ last_layer : str or :class:`pyedb.grpc.database.layers.layer.Layer`, optional
2253
+ Last layer to plot from the bottom. Default is ``None`` (plot up to top layer).
2155
2254
  scale_elevation : bool, optional
2156
- The real layer thickness is scaled so that max_thickness = 3 * min_thickness.
2157
- Default is `True`.
2255
+ Scale real layer thickness so that max_thickness = 3 * min_thickness. Default is ``True``.
2158
2256
  show : bool, optional
2159
- Whether to show the plot or not. Default is `True`.
2257
+ Whether to show the plot. Default is ``True``.
2160
2258
 
2161
2259
  Returns
2162
2260
  -------
2163
- :class:`matplotlib.plt`
2261
+ :class:`matplotlib.pyplot`
2262
+ Matplotlib plot object.
2164
2263
  """
2165
2264
 
2166
2265
  from pyedb.generic.constants import CSS4_COLORS
@@ -2363,7 +2462,7 @@ class Stackup(LayerCollection):
2363
2462
  width = len(columns) + 1
2364
2463
  for i, c in enumerate(columns[:-1]):
2365
2464
  for j, r in enumerate(c):
2366
- if r != 0: # and dname == r[0].name:
2465
+ if r != 0: # and dname == r[0].name
2367
2466
  if columns[i + 1][j] == 0:
2368
2467
  # nothing on the right, so expand the fill
2369
2468
  x = r[1]