pyedb 0.43.0__py3-none-any.whl → 0.45.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 (68) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_boundaries.py +21 -15
  3. pyedb/configuration/cfg_components.py +8 -8
  4. pyedb/configuration/cfg_general.py +14 -6
  5. pyedb/configuration/cfg_modeler.py +8 -0
  6. pyedb/configuration/cfg_operations.py +40 -1
  7. pyedb/configuration/cfg_package_definition.py +41 -1
  8. pyedb/configuration/cfg_padstacks.py +611 -256
  9. pyedb/configuration/cfg_pin_groups.py +1 -1
  10. pyedb/configuration/cfg_ports_sources.py +234 -66
  11. pyedb/configuration/cfg_s_parameter_models.py +81 -1
  12. pyedb/configuration/cfg_setup.py +167 -33
  13. pyedb/configuration/cfg_stackup.py +44 -0
  14. pyedb/configuration/configuration.py +13 -3
  15. pyedb/dotnet/database/cell/primitive/path.py +12 -0
  16. pyedb/dotnet/database/edb_data/design_options.py +19 -1
  17. pyedb/dotnet/database/edb_data/padstacks_data.py +9 -4
  18. pyedb/dotnet/database/geometry/point_data.py +26 -0
  19. pyedb/dotnet/database/geometry/polygon_data.py +13 -2
  20. pyedb/dotnet/database/nets.py +13 -3
  21. pyedb/dotnet/database/padstack.py +6 -2
  22. pyedb/dotnet/database/utilities/simulation_setup.py +7 -17
  23. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +30 -0
  24. pyedb/dotnet/edb.py +41 -18
  25. pyedb/grpc/database/components.py +2 -3
  26. pyedb/grpc/database/definition/component_def.py +15 -0
  27. pyedb/grpc/database/definition/component_pin.py +1 -1
  28. pyedb/grpc/database/definition/materials.py +27 -0
  29. pyedb/grpc/database/definition/package_def.py +20 -2
  30. pyedb/grpc/database/definition/padstack_def.py +5 -2
  31. pyedb/grpc/database/hfss.py +10 -1
  32. pyedb/grpc/database/hierarchy/component.py +4 -2
  33. pyedb/grpc/database/hierarchy/pingroup.py +12 -8
  34. pyedb/grpc/database/layers/layer.py +28 -0
  35. pyedb/grpc/database/layers/stackup_layer.py +281 -40
  36. pyedb/grpc/database/layout/layout.py +12 -6
  37. pyedb/grpc/database/layout_validation.py +2 -2
  38. pyedb/grpc/database/modeler.py +8 -8
  39. pyedb/grpc/database/padstacks.py +15 -9
  40. pyedb/grpc/database/ports/ports.py +3 -3
  41. pyedb/grpc/database/primitive/bondwire.py +3 -3
  42. pyedb/grpc/database/primitive/circle.py +1 -1
  43. pyedb/grpc/database/primitive/padstack_instance.py +13 -3
  44. pyedb/grpc/database/primitive/path.py +2 -2
  45. pyedb/grpc/database/primitive/polygon.py +3 -3
  46. pyedb/grpc/database/primitive/primitive.py +1 -1
  47. pyedb/grpc/database/primitive/rectangle.py +2 -2
  48. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +78 -30
  49. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +73 -30
  50. pyedb/grpc/database/simulation_setup/sweep_data.py +12 -1
  51. pyedb/grpc/database/siwave.py +10 -1
  52. pyedb/grpc/database/source_excitations.py +19 -9
  53. pyedb/grpc/database/stackup.py +26 -10
  54. pyedb/grpc/database/terminal/bundle_terminal.py +3 -3
  55. pyedb/grpc/database/terminal/edge_terminal.py +95 -2
  56. pyedb/grpc/database/terminal/padstack_instance_terminal.py +42 -2
  57. pyedb/grpc/database/terminal/pingroup_terminal.py +48 -2
  58. pyedb/grpc/database/terminal/point_terminal.py +10 -1
  59. pyedb/grpc/database/terminal/terminal.py +4 -4
  60. pyedb/grpc/database/utility/hfss_extent_info.py +14 -10
  61. pyedb/grpc/edb.py +21 -17
  62. pyedb/grpc/edb_init.py +19 -15
  63. pyedb/grpc/rpc_session.py +11 -8
  64. pyedb/misc/misc.py +13 -0
  65. {pyedb-0.43.0.dist-info → pyedb-0.45.0.dist-info}/METADATA +6 -6
  66. {pyedb-0.43.0.dist-info → pyedb-0.45.0.dist-info}/RECORD +68 -68
  67. {pyedb-0.43.0.dist-info → pyedb-0.45.0.dist-info}/LICENSE +0 -0
  68. {pyedb-0.43.0.dist-info → pyedb-0.45.0.dist-info}/WHEEL +0 -0
@@ -25,7 +25,7 @@ import math
25
25
 
26
26
  from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
27
27
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
28
- from ansys.edb.core.primitive.primitive import Polygon as GrpcPolygon
28
+ from ansys.edb.core.primitive.polygon import Polygon as GrpcPolygon
29
29
  from ansys.edb.core.utility.value import Value as GrpcValue
30
30
 
31
31
  from pyedb.grpc.database.primitive.primitive import Primitive
@@ -64,7 +64,7 @@ class Polygon(GrpcPolygon, Primitive):
64
64
 
65
65
  Returns
66
66
  -------
67
- List[:class:`Polygon <ansys.edb.core.primitive.primitive.Polygon>`]
67
+ List[:class:`Polygon <ansys.edb.core.primitive.polygon.Polygon>`]
68
68
  All new polygons created from the removal operation.
69
69
 
70
70
  """
@@ -84,7 +84,7 @@ class Polygon(GrpcPolygon, Primitive):
84
84
 
85
85
  Returns
86
86
  -------
87
- :class:`Polygon <ansys.edb.core.primitive.primitive.Polygon>`
87
+ :class:`Polygon <ansys.edb.core.primitive.polygon.Polygon>`
88
88
  Cloned polygon.
89
89
 
90
90
  """
@@ -22,7 +22,7 @@
22
22
 
23
23
  from ansys.edb.core.database import ProductIdType as GrpcProductIdType
24
24
  from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
25
- from ansys.edb.core.primitive.primitive import Circle as GrpcCircle
25
+ from ansys.edb.core.primitive.circle import Circle as GrpcCircle
26
26
  from ansys.edb.core.primitive.primitive import Primitive as GrpcPrimitive
27
27
 
28
28
  from pyedb.misc.utilities import compute_arc_points
@@ -21,10 +21,10 @@
21
21
  # SOFTWARE.
22
22
 
23
23
 
24
- from ansys.edb.core.primitive.primitive import (
24
+ from ansys.edb.core.primitive.rectangle import (
25
25
  RectangleRepresentationType as GrpcRectangleRepresentationType,
26
26
  )
27
- from ansys.edb.core.primitive.primitive import Rectangle as GrpcRectangle
27
+ from ansys.edb.core.primitive.rectangle import Rectangle as GrpcRectangle
28
28
  from ansys.edb.core.utility.value import Value as GrpcValue
29
29
 
30
30
  from pyedb.grpc.database.primitive.primitive import Primitive
@@ -293,7 +293,14 @@ class HfssSimulationSetup(GrpcHfssSimulationSetup):
293
293
  return mesh_operation
294
294
 
295
295
  def add_sweep(
296
- self, name=None, distribution="linear", start_freq="0GHz", stop_freq="20GHz", step="10MHz", discrete=False
296
+ self,
297
+ name=None,
298
+ distribution="linear",
299
+ start_freq="0GHz",
300
+ stop_freq="20GHz",
301
+ step="10MHz",
302
+ discrete=False,
303
+ frequency_set=None,
297
304
  ):
298
305
  """Add a HFSS frequency sweep.
299
306
 
@@ -317,39 +324,80 @@ class HfssSimulationSetup(GrpcHfssSimulationSetup):
317
324
  distribution. Must be integer in that case.
318
325
  discrete : bool, optional
319
326
  Whether the sweep is discrete. The default is ``False``.
327
+ frequency_set : List, optional
328
+ Frequency set is a list adding one or more frequency sweeps. If ``frequency_set`` is provided, the other
329
+ arguments are ignored except ``discrete``. Default value is ``None``.
330
+ example of frequency_set : [['linear_scale', '50MHz', '200MHz', '10MHz']].
320
331
 
321
332
  Returns
322
333
  -------
323
334
  bool
324
335
  """
325
336
  init_sweep_count = len(self.sweep_data)
326
- start_freq = self._pedb.number_with_units(start_freq, "Hz")
327
- stop_freq = self._pedb.number_with_units(stop_freq, "Hz")
328
- step = str(step)
329
- if distribution.lower() == "linear":
330
- distribution = "LIN"
331
- elif distribution.lower() == "linear_count":
332
- distribution = "LINC"
333
- elif distribution.lower() == "exponential":
334
- distribution = "ESTP"
335
- elif distribution.lower() == "decade_count":
336
- distribution = "DEC"
337
- elif distribution.lower() == "octave_count":
338
- distribution = "OCT"
337
+ if frequency_set:
338
+ for sweep in frequency_set:
339
+ if "linear_scale" in sweep:
340
+ distribution = "LIN"
341
+ elif "linear_count" in sweep:
342
+ distribution = "LINC"
343
+ elif "exponential" in sweep:
344
+ distribution = "ESTP"
345
+ elif "log_scale" in sweep:
346
+ distribution = "DEC"
347
+ elif "octave_count" in sweep:
348
+ distribution = "OCT"
349
+ else:
350
+ distribution = "LIN"
351
+ start_freq = self._pedb.number_with_units(sweep[1], "Hz")
352
+ stop_freq = self._pedb.number_with_units(sweep[2], "Hz")
353
+ step = str(sweep[3])
354
+ if not name:
355
+ name = f"sweep_{init_sweep_count + 1}"
356
+ sweep_data = [
357
+ SweepData(
358
+ self._pedb, name=name, distribution=distribution, start_f=start_freq, end_f=stop_freq, step=step
359
+ )
360
+ ]
361
+ if discrete:
362
+ sweep_data[0].type = sweep_data[0].type.DISCRETE_SWEEP
363
+ for sweep in self.sweep_data:
364
+ sweep_data.append(sweep)
365
+ self.sweep_data = sweep_data
339
366
  else:
340
- distribution = "LIN"
341
- if not name:
342
- name = f"sweep_{init_sweep_count + 1}"
343
- sweep_data = [
344
- SweepData(self._pedb, name=name, distribution=distribution, start_f=start_freq, end_f=stop_freq, step=step)
345
- ]
346
- if discrete:
347
- sweep_data[0].type = sweep_data[0].type.DISCRETE_SWEEP
348
- for sweep in self.sweep_data:
349
- sweep_data.append(sweep)
350
- self.sweep_data = sweep_data
351
- if len(self.sweep_data) == init_sweep_count + 1:
352
- return True
353
- else:
354
- self._pedb.logger.error("Failed to add frequency sweep data")
355
- return False
367
+ start_freq = self._pedb.number_with_units(start_freq, "Hz")
368
+ stop_freq = self._pedb.number_with_units(stop_freq, "Hz")
369
+ step = str(step)
370
+ if not distribution in ["LIN", "LINC", "ESTP", "DEC", "OCT"]:
371
+ if distribution.lower() == "linear" or distribution.lower() == "linear scale":
372
+ distribution = "LIN"
373
+ elif distribution.lower() == "linear_count" or distribution.lower() == "linear count":
374
+ distribution = "LINC"
375
+ elif distribution.lower() == "exponential":
376
+ distribution = "ESTP"
377
+ elif (
378
+ distribution.lower() == "decade_count"
379
+ or distribution.lower() == "decade count"
380
+ or distribution.lower()
381
+ ) == "log scale":
382
+ distribution = "DEC"
383
+ elif distribution.lower() == "octave_count" or distribution.lower() == "octave count":
384
+ distribution = "OCT"
385
+ else:
386
+ distribution = "LIN"
387
+ if not name:
388
+ name = f"sweep_{init_sweep_count + 1}"
389
+ sweep_data = [
390
+ SweepData(
391
+ self._pedb, name=name, distribution=distribution, start_f=start_freq, end_f=stop_freq, step=step
392
+ )
393
+ ]
394
+ if discrete:
395
+ sweep_data[0].type = sweep_data[0].type.DISCRETE_SWEEP
396
+ for sweep in self.sweep_data:
397
+ sweep_data.append(sweep)
398
+ self.sweep_data = sweep_data
399
+ if len(self.sweep_data) == init_sweep_count + 1:
400
+ return self.sweep_data[-1]
401
+ else:
402
+ self._pedb.logger.error("Failed to add frequency sweep data")
403
+ return False
@@ -57,7 +57,14 @@ class SiwaveSimulationSetup(GrpcSIWaveSimulationSetup):
57
57
  super(SiwaveSimulationSetup, self.__class__).type.__set__(self, GrpcSimulationSetupType.SI_WAVE_DCIR)
58
58
 
59
59
  def add_sweep(
60
- self, name=None, distribution="linear", start_freq="0GHz", stop_freq="20GHz", step="10MHz", discrete=False
60
+ self,
61
+ name=None,
62
+ distribution="linear",
63
+ start_freq="0GHz",
64
+ stop_freq="20GHz",
65
+ step="10MHz",
66
+ discrete=False,
67
+ frequency_set=None,
61
68
  ):
62
69
  """Add a HFSS frequency sweep.
63
70
 
@@ -81,39 +88,75 @@ class SiwaveSimulationSetup(GrpcSIWaveSimulationSetup):
81
88
  distribution. Must be integer in that case.
82
89
  discrete : bool, optional
83
90
  Whether the sweep is discrete. The default is ``False``.
91
+ frequency_set : List, optional
92
+ Frequency set is a list adding one or more frequency sweeps. If ``frequency_set`` is provided, the other
93
+ arguments are ignored except ``discrete``. Default value is ``None``.
94
+ example of frequency_set : [['linear_scale', '50MHz', '200MHz', '10MHz']].
84
95
 
85
96
  Returns
86
97
  -------
87
98
  bool
88
99
  """
89
100
  init_sweep_count = len(self.sweep_data)
90
- start_freq = self._pedb.number_with_units(start_freq, "Hz")
91
- stop_freq = self._pedb.number_with_units(stop_freq, "Hz")
92
- step = str(step)
93
- if distribution.lower() == "linear":
94
- distribution = "LIN"
95
- elif distribution.lower() == "linear_count":
96
- distribution = "LINC"
97
- elif distribution.lower() == "exponential":
98
- distribution = "ESTP"
99
- elif distribution.lower() == "decade_count":
100
- distribution = "DEC"
101
- elif distribution.lower() == "octave_count":
102
- distribution = "OCT"
101
+ if frequency_set:
102
+ for sweep in frequency_set:
103
+ if "linear_scale" in sweep:
104
+ distribution = "LIN"
105
+ elif "linear_count" in sweep:
106
+ distribution = "LINC"
107
+ elif "exponential" in sweep:
108
+ distribution = "ESTP"
109
+ elif "log_scale" in sweep:
110
+ distribution = "DEC"
111
+ elif "octave_count" in sweep:
112
+ distribution = "OCT"
113
+ else:
114
+ distribution = "LIN"
115
+ start_freq = self._pedb.number_with_units(sweep[1], "Hz")
116
+ stop_freq = self._pedb.number_with_units(sweep[2], "Hz")
117
+ step = str(sweep[3])
118
+ if not name:
119
+ name = f"sweep_{init_sweep_count + 1}"
120
+ sweep_data = [
121
+ SweepData(
122
+ self._pedb, name=name, distribution=distribution, start_f=start_freq, end_f=stop_freq, step=step
123
+ )
124
+ ]
125
+ if discrete:
126
+ sweep_data[0].type = sweep_data[0].type.DISCRETE_SWEEP
127
+ for sweep in self.sweep_data:
128
+ sweep_data.append(sweep)
129
+ self.sweep_data = sweep_data
103
130
  else:
104
- distribution = "LIN"
105
- if not name:
106
- name = f"sweep_{init_sweep_count + 1}"
107
- sweep_data = [
108
- SweepData(self._pedb, name=name, distribution=distribution, start_f=start_freq, end_f=stop_freq, step=step)
109
- ]
110
- if discrete:
111
- sweep_data[0].type = sweep_data[0].type.DISCRETE_SWEEP
112
- for sweep in self.sweep_data:
113
- sweep_data.append(sweep)
114
- self.sweep_data = sweep_data
115
- if len(self.sweep_data) == init_sweep_count + 1:
116
- return True
117
- else:
118
- self._pedb.logger.error("Failed to add frequency sweep data")
119
- return False
131
+ start_freq = self._pedb.number_with_units(start_freq, "Hz")
132
+ stop_freq = self._pedb.number_with_units(stop_freq, "Hz")
133
+ step = str(step)
134
+ if distribution.lower() == "linear":
135
+ distribution = "LIN"
136
+ elif distribution.lower() == "linear_count":
137
+ distribution = "LINC"
138
+ elif distribution.lower() == "exponential":
139
+ distribution = "ESTP"
140
+ elif distribution.lower() == "decade_count":
141
+ distribution = "DEC"
142
+ elif distribution.lower() == "octave_count":
143
+ distribution = "OCT"
144
+ else:
145
+ distribution = "LIN"
146
+ if not name:
147
+ name = f"sweep_{init_sweep_count + 1}"
148
+ sweep_data = [
149
+ SweepData(
150
+ self._pedb, name=name, distribution=distribution, start_f=start_freq, end_f=stop_freq, step=step
151
+ )
152
+ ]
153
+ if discrete:
154
+ sweep_data[0].type = sweep_data[0].type.DISCRETE_SWEEP
155
+ for sweep in self.sweep_data:
156
+ sweep_data.append(sweep)
157
+ self.sweep_data = sweep_data
158
+ if len(self.sweep_data) == init_sweep_count + 1:
159
+ return True
160
+ else:
161
+ self._pedb.logger.error("Failed to add frequency sweep data")
162
+ return False
@@ -20,6 +20,12 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
+ from ansys.edb.core.simulation_setup.simulation_setup import (
24
+ Distribution as GrpcDistribution,
25
+ )
26
+ from ansys.edb.core.simulation_setup.simulation_setup import (
27
+ FrequencyData as GrpcFrequencyData,
28
+ )
23
29
  from ansys.edb.core.simulation_setup.simulation_setup import SweepData as GrpcSweepData
24
30
 
25
31
 
@@ -27,6 +33,11 @@ class SweepData(GrpcSweepData):
27
33
  """Frequency sweep data class."""
28
34
 
29
35
  def __init__(self, pedb, name, distribution, start_f, end_f, step, edb_object=None):
30
- super().__init__(name=name, distribution=distribution, start_f=start_f, end_f=end_f, step=step)
36
+ super().__init__(
37
+ name=name,
38
+ frequency_data=GrpcFrequencyData(
39
+ distribution=GrpcDistribution[distribution], start_f=start_f, end_f=end_f, step=step
40
+ ),
41
+ )
31
42
  self._edb_object = edb_object
32
43
  self._pedb = pedb
@@ -28,6 +28,12 @@ import os
28
28
  import warnings
29
29
 
30
30
  from ansys.edb.core.database import ProductIdType as GrpcProductIdType
31
+ from ansys.edb.core.simulation_setup.simulation_setup import (
32
+ Distribution as GrpcDistribution,
33
+ )
34
+ from ansys.edb.core.simulation_setup.simulation_setup import (
35
+ FrequencyData as GrpcFrequencyData,
36
+ )
31
37
  from ansys.edb.core.simulation_setup.simulation_setup import SweepData as GrpcSweepData
32
38
 
33
39
  from pyedb.misc.siw_feature_config.xtalk_scan.scan_config import SiwaveScanConfig
@@ -592,7 +598,10 @@ class Siwave(object):
592
598
  sweep_name = f"sweep_{len(setup.sweep_data) + 1}"
593
599
  sweep_data = [
594
600
  GrpcSweepData(
595
- name=sweep_name, distribution=distribution, start_f=start_freq, end_f=stop_freq, step=step_freq
601
+ name=sweep_name,
602
+ frequency_data=GrpcFrequencyData(
603
+ distribution=GrpcDistribution[distribution], start_f=start_freq, end_f=stop_freq, step=step_freq
604
+ ),
596
605
  )
597
606
  ]
598
607
  if discrete_sweep:
@@ -20,14 +20,14 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- from typing import Union
23
+ from typing import List, Set, Union
24
24
 
25
25
  from ansys.edb.core.database import ProductIdType as GrpcProductIdType
26
26
  from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
27
27
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
28
- from ansys.edb.core.terminal.terminals import BoundaryType as GrpcBoundaryType
29
- from ansys.edb.core.terminal.terminals import EdgeTerminal as GrpcEdgeTerminal
30
- from ansys.edb.core.terminal.terminals import PrimitiveEdge as GrpcPrimitiveEdge
28
+ from ansys.edb.core.terminal.edge_terminal import EdgeTerminal as GrpcEdgeTerminal
29
+ from ansys.edb.core.terminal.edge_terminal import PrimitiveEdge as GrpcPrimitiveEdge
30
+ from ansys.edb.core.terminal.terminal import BoundaryType as GrpcBoundaryType
31
31
  from ansys.edb.core.utility.rlc import Rlc as GrpcRlc
32
32
  from ansys.edb.core.utility.value import Value as GrpcValue
33
33
 
@@ -225,7 +225,7 @@ class SourceExcitation:
225
225
  if refdes and any(refdes.rlc_values):
226
226
  return self._pedb.components.deactivate_rlc_component(component=refdes, create_circuit_port=True)
227
227
  if not port_name:
228
- port_name = f"Port_{pins[0].net_name}_{pins[0].name}"
228
+ port_name = f"Port_{pins[0].net_name}_{pins[0].component.name}_{pins[0].name}"
229
229
 
230
230
  if len(pins) > 1 or pingroup_on_single_pin:
231
231
  pec_boundary = False
@@ -267,8 +267,8 @@ class SourceExcitation:
267
267
  return term or False
268
268
 
269
269
  def _get_pins_for_ports(
270
- self, pins: Union[int, str, PadstackInstance, list[Union[int, str, PadstackInstance]]], comp: Component
271
- ) -> list[PadstackInstance]:
270
+ self, pins: Union[int, str, PadstackInstance, List[Union[int, str, PadstackInstance]]], comp: Component
271
+ ) -> List[PadstackInstance]:
272
272
  if not isinstance(pins, list):
273
273
  pins = [pins]
274
274
  result = []
@@ -506,7 +506,7 @@ class SourceExcitation:
506
506
  return True
507
507
 
508
508
  @staticmethod
509
- def _normalize_net_list(net_list) -> set[str]:
509
+ def _normalize_net_list(net_list) -> Set[str]:
510
510
  if not isinstance(net_list, list):
511
511
  net_list = [net_list]
512
512
  nets = set()
@@ -713,9 +713,19 @@ class SourceExcitation:
713
713
  -------
714
714
  Edb pin group terminal.
715
715
  """
716
+ from ansys.edb.core.hierarchy.pin_group import PinGroup as GrpcPinGroup
717
+
718
+ from pyedb.grpc.database.hierarchy.pingroup import PinGroup
719
+
716
720
  if pingroup.is_null:
717
721
  self._logger.error(f"{pingroup} is null")
718
- pin = PadstackInstance(self._pedb, pingroup.pins[0])
722
+ if not pingroup.pins:
723
+ self._pedb.logger.error("No pins defined on pingroup.")
724
+ return False
725
+ if isinstance(pingroup, GrpcPinGroup):
726
+ pingroup = PinGroup(self._pedb, pingroup)
727
+ pin = list(pingroup.pins.values())[0]
728
+ pin = PadstackInstance(self._pedb, pin)
719
729
  if term_name is None:
720
730
  term_name = f"{pin.component.name}.{pin.name}.{pin.net_name}"
721
731
  for t in self._pedb.active_layout.terminals:
@@ -138,15 +138,23 @@ class LayerCollection(GrpcLayerCollection):
138
138
 
139
139
  """
140
140
  thickness = GrpcValue(0.0)
141
+ layer_type_map = {"dielectric": GrpcLayerType.DIELECTRIC_LAYER, "signal": GrpcLayerType.SIGNAL_LAYER}
141
142
  if "thickness" in kwargs:
142
143
  thickness = GrpcValue(kwargs["thickness"])
143
144
  elevation = GrpcValue(0.0)
144
- _layer_type = GrpcLayerType.SIGNAL_LAYER
145
- if layer_type.lower() == "dielectric":
146
- _layer_type = GrpcLayerType.DIELECTRIC_LAYER
145
+ if "type" in kwargs:
146
+ _layer_type = layer_type_map[kwargs["type"]]
147
+ else:
148
+ _layer_type = layer_type_map[layer_type]
149
+ if "material" in kwargs:
150
+ _material = kwargs["material"]
151
+ else:
152
+ _material = "copper"
147
153
  layer = GrpcStackupLayer.create(
148
- name=name, layer_type=_layer_type, thickness=thickness, material="copper", elevation=elevation
154
+ name=name, layer_type=_layer_type, thickness=thickness, material=_material, elevation=elevation
149
155
  )
156
+ if "fill_material" in kwargs:
157
+ layer.set_fill_material(kwargs["fill_material"])
150
158
  return self._layer_collection.add_layer_bottom(layer)
151
159
 
152
160
  def add_layer_below(self, name, base_layer_name, layer_type="signal", **kwargs):
@@ -170,11 +178,19 @@ class LayerCollection(GrpcLayerCollection):
170
178
  if "thickness" in kwargs:
171
179
  thickness = GrpcValue(kwargs["thickness"])
172
180
  elevation = GrpcValue(0.0)
173
- _layer_type = GrpcLayerType.SIGNAL_LAYER
174
- if layer_type.lower() == "dielectric":
175
- _layer_type = GrpcLayerType.DIELECTRIC_LAYER
181
+ if "type" in kwargs:
182
+ _l_map = {"signal": GrpcLayerType.SIGNAL_LAYER, "dielectric": GrpcLayerType.DIELECTRIC_LAYER}
183
+ _layer_type = _l_map[kwargs["type"]]
184
+ else:
185
+ _layer_type = GrpcLayerType.SIGNAL_LAYER
186
+ if layer_type.lower() == "dielectric":
187
+ _layer_type = GrpcLayerType.DIELECTRIC_LAYER
188
+ if "material" in kwargs:
189
+ material = kwargs["material"]
190
+ else:
191
+ material = "copper"
176
192
  layer = GrpcStackupLayer.create(
177
- name=name, layer_type=_layer_type, thickness=thickness, material="copper", elevation=elevation
193
+ name=name, layer_type=_layer_type, thickness=thickness, material=material, elevation=elevation
178
194
  )
179
195
  return self._layer_collection.add_layer_below(layer, base_layer_name)
180
196
 
@@ -695,8 +711,8 @@ class Stackup(LayerCollection):
695
711
 
696
712
  """
697
713
  new_layer_collection = LayerCollection.create()
698
- for lyr in self.layers:
699
- if not (lyr.name == name):
714
+ for layer_name, lyr in self.layers.items():
715
+ if not (layer_name == name):
700
716
  new_layer_collection.add_layer_bottom(lyr)
701
717
 
702
718
  self._pedb.layout.layer_collection = new_layer_collection
@@ -20,11 +20,11 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- from ansys.edb.core.terminal.terminals import (
23
+ from ansys.edb.core.terminal.bundle_terminal import BundleTerminal as GrpcBundleTerminal
24
+ from ansys.edb.core.terminal.terminal import (
24
25
  SourceTermToGroundType as GrpcSourceTermToGroundType,
25
26
  )
26
- from ansys.edb.core.terminal.terminals import BundleTerminal as GrpcBundleTerminal
27
- from ansys.edb.core.terminal.terminals import HfssPIType as GrpcHfssPIType
27
+ from ansys.edb.core.terminal.terminal import HfssPIType as GrpcHfssPIType
28
28
  from ansys.edb.core.utility.value import Value as GrpcValue
29
29
 
30
30
  from pyedb.grpc.database.hierarchy.component import Component
@@ -20,8 +20,10 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- from ansys.edb.core.terminal.terminals import BundleTerminal as GrpcBundleTerminal
24
- from ansys.edb.core.terminal.terminals import EdgeTerminal as GrpcEdgeTerminal
23
+ import re
24
+
25
+ from ansys.edb.core.terminal.bundle_terminal import BundleTerminal as GrpcBundleTerminal
26
+ from ansys.edb.core.terminal.edge_terminal import EdgeTerminal as GrpcEdgeTerminal
25
27
 
26
28
 
27
29
  class EdgeTerminal(GrpcEdgeTerminal):
@@ -29,6 +31,65 @@ class EdgeTerminal(GrpcEdgeTerminal):
29
31
  super().__init__(edb_object.msg)
30
32
  self._pedb = pedb
31
33
  self._edb_object = edb_object
34
+ self._hfss_type = "Gap"
35
+
36
+ @property
37
+ def _edb_properties(self):
38
+ from ansys.edb.core.database import ProductIdType as GrpcProductIdType
39
+
40
+ try:
41
+ p = self._edb_object.get_product_property(GrpcProductIdType.DESIGNER, 1)
42
+ except:
43
+ p = ""
44
+ return p
45
+
46
+ @_edb_properties.setter
47
+ def _edb_properties(self, value):
48
+ from ansys.edb.core.database import ProductIdType as GrpcProductIdType
49
+
50
+ self._edb_object.set_product_property(GrpcProductIdType.DESIGNER, 1, value)
51
+
52
+ @property
53
+ def is_wave_port(self):
54
+ if self._hfss_port_property:
55
+ return True
56
+ return False
57
+
58
+ @property
59
+ def _hfss_port_property(self):
60
+ """HFSS port property."""
61
+ hfss_prop = re.search(r"HFSS\(.*?\)", self._edb_properties)
62
+ p = {}
63
+ if hfss_prop:
64
+ hfss_type = re.search(r"'HFSS Type'='([^']+)'", hfss_prop.group())
65
+ orientation = re.search(r"'Orientation'='([^']+)'", hfss_prop.group())
66
+ horizontal_ef = re.search(r"'Horizontal Extent Factor'='([^']+)'", hfss_prop.group())
67
+ vertical_ef = re.search(r"'Vertical Extent Factor'='([^']+)'", hfss_prop.group())
68
+ radial_ef = re.search(r"'Radial Extent Factor'='([^']+)'", hfss_prop.group())
69
+ pec_w = re.search(r"'PEC Launch Width'='([^']+)'", hfss_prop.group())
70
+
71
+ p["HFSS Type"] = hfss_type.group(1) if hfss_type else ""
72
+ p["Orientation"] = orientation.group(1) if orientation else ""
73
+ p["Horizontal Extent Factor"] = float(horizontal_ef.group(1)) if horizontal_ef else ""
74
+ p["Vertical Extent Factor"] = float(vertical_ef.group(1)) if vertical_ef else ""
75
+ p["Radial Extent Factor"] = float(radial_ef.group(1)) if radial_ef else ""
76
+ p["PEC Launch Width"] = pec_w.group(1) if pec_w else ""
77
+ else:
78
+ p["HFSS Type"] = ""
79
+ p["Orientation"] = ""
80
+ p["Horizontal Extent Factor"] = ""
81
+ p["Vertical Extent Factor"] = ""
82
+ p["Radial Extent Factor"] = ""
83
+ p["PEC Launch Width"] = ""
84
+ return p
85
+
86
+ @_hfss_port_property.setter
87
+ def _hfss_port_property(self, value):
88
+ txt = []
89
+ for k, v in value.items():
90
+ txt.append("'{}'='{}'".format(k, v))
91
+ txt = ",".join(txt)
92
+ self._edb_properties = "HFSS({})".format(txt)
32
93
 
33
94
  def couple_ports(self, port):
34
95
  """Create a bundle wave port.
@@ -49,3 +110,35 @@ class EdgeTerminal(GrpcEdgeTerminal):
49
110
  temp.extend([i for i in port])
50
111
  bundle_terminal = GrpcBundleTerminal.create(temp)
51
112
  return self._pedb.ports[bundle_terminal.name]
113
+
114
+ @property
115
+ def is_port(self):
116
+ return True
117
+
118
+ @property
119
+ def ref_terminal(self):
120
+ """Return refeference terminal.
121
+
122
+ ..deprecated:: 0.44.0
123
+ Use: func:`reference_terminal` property instead.
124
+
125
+ """
126
+ self._pedb.logger.warning("ref_terminal is deprecated, use reference_terminal property instead.")
127
+ return self.reference_terminal
128
+
129
+ @ref_terminal.setter
130
+ def ref_terminal(self, value):
131
+ self._pedb.logger.warning("ref_terminal is deprecated, use reference_terminal property instead.")
132
+ self.reference_terminal = value
133
+
134
+ @property
135
+ def hfss_type(self):
136
+ return self._hfss_type
137
+
138
+ @hfss_type.setter
139
+ def hfss_type(self, value):
140
+ self._hfss_type = value
141
+
142
+ @property
143
+ def terminal_type(self):
144
+ return "EdgeTerminal"