pyedb 0.43.0__py3-none-any.whl → 0.44.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 (52) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_boundaries.py +20 -14
  3. pyedb/configuration/cfg_components.py +1 -1
  4. pyedb/configuration/cfg_general.py +6 -4
  5. pyedb/configuration/cfg_modeler.py +1 -0
  6. pyedb/configuration/cfg_package_definition.py +41 -1
  7. pyedb/configuration/cfg_padstacks.py +611 -256
  8. pyedb/configuration/cfg_ports_sources.py +75 -15
  9. pyedb/configuration/cfg_s_parameter_models.py +30 -0
  10. pyedb/configuration/cfg_setup.py +94 -21
  11. pyedb/configuration/cfg_stackup.py +44 -0
  12. pyedb/dotnet/database/edb_data/design_options.py +19 -1
  13. pyedb/dotnet/database/edb_data/padstacks_data.py +9 -4
  14. pyedb/dotnet/database/geometry/polygon_data.py +4 -2
  15. pyedb/dotnet/database/padstack.py +6 -2
  16. pyedb/dotnet/database/utilities/simulation_setup.py +7 -17
  17. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +30 -0
  18. pyedb/grpc/database/components.py +1 -1
  19. pyedb/grpc/database/definition/component_def.py +15 -0
  20. pyedb/grpc/database/definition/component_pin.py +1 -1
  21. pyedb/grpc/database/definition/materials.py +27 -0
  22. pyedb/grpc/database/definition/package_def.py +20 -2
  23. pyedb/grpc/database/definition/padstack_def.py +5 -2
  24. pyedb/grpc/database/hierarchy/component.py +4 -2
  25. pyedb/grpc/database/hierarchy/pingroup.py +12 -8
  26. pyedb/grpc/database/layers/layer.py +28 -0
  27. pyedb/grpc/database/layers/stackup_layer.py +281 -40
  28. pyedb/grpc/database/layout/layout.py +12 -6
  29. pyedb/grpc/database/modeler.py +8 -8
  30. pyedb/grpc/database/primitive/bondwire.py +3 -3
  31. pyedb/grpc/database/primitive/circle.py +1 -1
  32. pyedb/grpc/database/primitive/padstack_instance.py +13 -3
  33. pyedb/grpc/database/primitive/path.py +2 -2
  34. pyedb/grpc/database/primitive/polygon.py +3 -3
  35. pyedb/grpc/database/primitive/primitive.py +1 -1
  36. pyedb/grpc/database/primitive/rectangle.py +2 -2
  37. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +73 -30
  38. pyedb/grpc/database/source_excitations.py +7 -7
  39. pyedb/grpc/database/stackup.py +14 -6
  40. pyedb/grpc/database/terminal/bundle_terminal.py +3 -3
  41. pyedb/grpc/database/terminal/edge_terminal.py +2 -2
  42. pyedb/grpc/database/terminal/padstack_instance_terminal.py +42 -2
  43. pyedb/grpc/database/terminal/pingroup_terminal.py +35 -2
  44. pyedb/grpc/database/terminal/point_terminal.py +10 -1
  45. pyedb/grpc/database/terminal/terminal.py +4 -4
  46. pyedb/grpc/database/utility/hfss_extent_info.py +14 -10
  47. pyedb/grpc/edb.py +8 -8
  48. pyedb/misc/misc.py +13 -0
  49. {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/METADATA +1 -1
  50. {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/RECORD +52 -52
  51. {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/LICENSE +0 -0
  52. {pyedb-0.43.0.dist-info → pyedb-0.44.0.dist-info}/WHEEL +0 -0
@@ -216,3 +216,18 @@ class ComponentDef(GrpcComponentDef):
216
216
  n_port_model.reference_file = fpath
217
217
  self.add_component_model(n_port_model)
218
218
  return n_port_model
219
+
220
+ def get_properties(self):
221
+ data = {}
222
+ temp = []
223
+ for i in self.component_pins:
224
+ temp.append(i.name)
225
+ data["pin_order"] = temp
226
+ return data
227
+
228
+ def set_properties(self, **kwargs):
229
+ pin_order = kwargs.get("pin_order")
230
+ if pin_order:
231
+ old = {i.name: i for i in self.component_pins}
232
+ temp = [old[str(i)] for i in pin_order]
233
+ self.component_pins = temp
@@ -28,5 +28,5 @@ class ComponentPin(GrpcComponentPin):
28
28
  """Class managing :class:`ComponentPin <ansys.edb.core.definition.component_pin.ComponentPin>`."""
29
29
 
30
30
  def __init__(self, pedb, edb_object):
31
- super().__init__(edb_object)
31
+ super().__init__(edb_object.msg)
32
32
  self._pedb = pedb
@@ -587,6 +587,33 @@ class Material(GrpcMaterialDef):
587
587
  class Materials(object):
588
588
  """Manages EDB methods for material management accessible from `Edb.materials` property."""
589
589
 
590
+ default_conductor_property_values = {
591
+ "conductivity": 58000000,
592
+ "dielectric_loss_tangent": 0,
593
+ "magnetic_loss_tangent": 0,
594
+ "mass_density": 8933,
595
+ "permittivity": 1,
596
+ "permeability": 0.999991,
597
+ "poisson_ratio": 0.38,
598
+ "specific_heat": 385,
599
+ "thermal_conductivity": 400,
600
+ "youngs_modulus": 120000000000,
601
+ "thermal_expansion_coefficient": 1.77e-05,
602
+ }
603
+ default_dielectric_property_values = {
604
+ "conductivity": 0,
605
+ "dielectric_loss_tangent": 0.02,
606
+ "magnetic_loss_tangent": 0,
607
+ "mass_density": 1900,
608
+ "permittivity": 4.4,
609
+ "permeability": 1,
610
+ "poisson_ratio": 0.28,
611
+ "specific_heat": 1150,
612
+ "thermal_conductivity": 0.294,
613
+ "youngs_modulus": 11000000000,
614
+ "thermal_expansion_coefficient": 1.5e-05,
615
+ }
616
+
590
617
  def __init__(self, edb: Edb):
591
618
  self.__edb = edb
592
619
  self.__syslib = os.path.join(self.__edb.base_path, "syslib")
@@ -26,6 +26,7 @@ from ansys.edb.core.utility.value import Value as GrpcValue
26
26
 
27
27
  from pyedb.edb_logger import pyedb_logger
28
28
  from pyedb.grpc.database.utility.heat_sink import HeatSink
29
+ from pyedb.misc.misc import deprecated_property
29
30
 
30
31
 
31
32
  class PackageDef(GrpcPackageDef):
@@ -45,6 +46,11 @@ class PackageDef(GrpcPackageDef):
45
46
  """
46
47
 
47
48
  def __init__(self, pedb, edb_object=None, name=None, component_part_name=None, extent_bounding_box=None):
49
+ if not edb_object:
50
+ if name:
51
+ edb_object = GrpcPackageDef.create(db=pedb.active_db, name=name)
52
+ else:
53
+ raise AttributeError("Name must be provided to create and instantiate a PackageDef object.")
48
54
  super(GrpcPackageDef, self).__init__(edb_object.msg)
49
55
  self._pedb = pedb
50
56
  self._edb_object = edb_object
@@ -129,7 +135,6 @@ class PackageDef(GrpcPackageDef):
129
135
 
130
136
  @therm_cond.setter
131
137
  def therm_cond(self, value):
132
- self.therm_cond = GrpcValue(value)
133
138
  super(PackageDef, self.__class__).thermal_conductivity.__set__(self, GrpcValue(value))
134
139
 
135
140
  @property
@@ -186,7 +191,20 @@ class PackageDef(GrpcPackageDef):
186
191
  :class:`HeatSink <pyedb.grpc.database.utility.heat_sink.HeatSink>`
187
192
  HeatSink object.
188
193
  """
189
- return HeatSink(self._pedb, super().heat_sink)
194
+ try:
195
+ return HeatSink(self._pedb, super().heat_sink)
196
+ except:
197
+ pass
198
+
199
+ @property
200
+ @deprecated_property
201
+ def heatsink(self):
202
+ """Property added for .NET compatibility.
203
+ . deprecated:: pyedb 0.43.0
204
+ Use :func:`heat_sink` instead.
205
+
206
+ """
207
+ return self.heat_sink
190
208
 
191
209
  def set_heatsink(self, fin_base_height, fin_height, fin_orientation, fin_spacing, fin_thickness):
192
210
  """Set Heat sink.
@@ -34,7 +34,7 @@ import ansys.edb.core.geometry.polygon_data
34
34
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
35
35
  from ansys.edb.core.hierarchy.structure3d import MeshClosure as GrpcMeshClosure
36
36
  from ansys.edb.core.hierarchy.structure3d import Structure3D as GrpcStructure3D
37
- from ansys.edb.core.primitive.primitive import Circle as GrpcCircle
37
+ from ansys.edb.core.primitive.circle import Circle as GrpcCircle
38
38
  from ansys.edb.core.utility.value import Value as GrpcValue
39
39
 
40
40
  from pyedb.generic.general_methods import generate_unique_name
@@ -577,7 +577,10 @@ class PadstackDef(GrpcPadstackDef):
577
577
  Possible returned values are ``"through"``, ``"begin_on_upper_pad"``,
578
578
  ``"end_on_lower_pad"``, ``"upper_pad_to_lower_pad"``, and ``"undefined"``.
579
579
  """
580
- return self.data.hole_range.name.lower()
580
+ try:
581
+ return self.data.hole_range.name.lower()
582
+ except:
583
+ return None
581
584
 
582
585
  @hole_range.setter
583
586
  def hole_range(self, value):
@@ -42,8 +42,10 @@ from ansys.edb.core.hierarchy.sparameter_model import (
42
42
  SParameterModel as GrpcSParameterModel,
43
43
  )
44
44
  from ansys.edb.core.hierarchy.spice_model import SPICEModel as GrpcSPICEModel
45
- from ansys.edb.core.primitive.primitive import PadstackInstance as GrpcPadstackInstance
46
- from ansys.edb.core.terminal.terminals import (
45
+ from ansys.edb.core.primitive.padstack_instance import (
46
+ PadstackInstance as GrpcPadstackInstance,
47
+ )
48
+ from ansys.edb.core.terminal.padstack_instance_terminal import (
47
49
  PadstackInstanceTerminal as GrpcPadstackInstanceTerminal,
48
50
  )
49
51
  from ansys.edb.core.utility.rlc import Rlc as GrpcRlc
@@ -22,7 +22,7 @@
22
22
 
23
23
 
24
24
  from ansys.edb.core.hierarchy.pin_group import PinGroup as GrpcPinGroup
25
- from ansys.edb.core.terminal.terminals import BoundaryType as GrpcBoundaryType
25
+ from ansys.edb.core.terminal.terminal import BoundaryType as GrpcBoundaryType
26
26
  from ansys.edb.core.utility.value import Value as GrpcValue
27
27
 
28
28
  from pyedb.generic.general_methods import generate_unique_name
@@ -74,9 +74,9 @@ class PinGroup(GrpcPinGroup):
74
74
 
75
75
  Returns
76
76
  -------
77
- List[:class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`].
77
+ Dict[:class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`].
78
78
  """
79
- return [PadstackInstance(self._pedb, i) for i in super().pins]
79
+ return {i.name: PadstackInstance(self._pedb, i) for i in super().pins}
80
80
 
81
81
  @property
82
82
  def net(self):
@@ -105,11 +105,15 @@ class PinGroup(GrpcPinGroup):
105
105
  """
106
106
  return self.net.name
107
107
 
108
- # @property
109
- # def terminal(self):
110
- # """Terminal."""
111
- # term = PinGroupTerminal(self._pedb, self.get_pin_group_terminal()) # TODO check method is missing
112
- # return term if not term.is_null else None
108
+ @property
109
+ def terminal(self):
110
+ """Terminal."""
111
+ term = self.pin_group_terminal
112
+ if not term.is_null:
113
+ term = PinGroupTerminal(self._pedb, term)
114
+ return term
115
+ else:
116
+ return None
113
117
 
114
118
  def create_terminal(self, name=None):
115
119
  """Create a terminal.
@@ -52,6 +52,34 @@ class Layer(GrpcLayer):
52
52
  else:
53
53
  self._pedb.logger.error(f"{k} is not a valid layer attribute")
54
54
 
55
+ @property
56
+ def properties(self):
57
+ from ansys.edb.core.layer.stackup_layer import StackupLayer as GrpcStackupLayer
58
+
59
+ from pyedb.grpc.database.stackup import StackupLayer
60
+
61
+ if isinstance(self.cast(), GrpcStackupLayer):
62
+ return StackupLayer(self._pedb, self.cast()).properties
63
+ else:
64
+ data = {"name": self.name, "type": self.type, "color": self.color}
65
+ return data
66
+
67
+ @properties.setter
68
+ def properties(self, params):
69
+ name = params.get("name", "")
70
+ if name:
71
+ self.name = name
72
+ type = params.get("type", "")
73
+ if type:
74
+ self.type = type
75
+ color = params.get("color", "")
76
+ if color:
77
+ self.color = color
78
+
79
+ @property
80
+ def type(self):
81
+ return super().type.name.lower().split("_")[0]
82
+
55
83
  @property
56
84
  def _layer_name_mapping_reversed(self):
57
85
  return {j: i for i, j in self._layer_name_mapping.items()}
@@ -56,13 +56,77 @@ class StackupLayer(GrpcStackupLayer):
56
56
  str
57
57
  Layer name.
58
58
  """
59
- return super().type.name.lower()
59
+ return super().type.name.lower().split("_")[0]
60
60
 
61
61
  @type.setter
62
62
  def type(self, value):
63
63
  if value in self._stackup_layer_mapping:
64
64
  super(StackupLayer, self.__class__).type.__set__(self, self._stackup_layer_mapping[value])
65
65
 
66
+ def update(self, **kwargs):
67
+ for k, v in kwargs.items():
68
+ if k in dir(self):
69
+ self.__setattr__(k, v)
70
+ elif k == "roughness":
71
+ self.roughness_enabled = v["enabled"]
72
+ if "top" in v:
73
+ top_roughness = v["top"]
74
+ if top_roughness:
75
+ if top_roughness["model"] == "huray":
76
+ nodule_radius = top_roughness["nodule_radius"]
77
+ surface_ratio = top_roughness["surface_ratio"]
78
+ self.assign_roughness_model(
79
+ model_type="huray",
80
+ huray_radius=nodule_radius,
81
+ huray_surface_ratio=surface_ratio,
82
+ apply_on_surface="top",
83
+ )
84
+ elif top_roughness["model"] == "groisse":
85
+ roughness = top_roughness["roughness"]
86
+ self.assign_roughness_model(
87
+ model_type="groisse", groisse_roughness=roughness, apply_on_surface="top"
88
+ )
89
+ if "bottom" in v:
90
+ bottom_roughness = v["bottom"]
91
+ if bottom_roughness:
92
+ if bottom_roughness["model"] == "huray":
93
+ nodule_radius = bottom_roughness["nodule_radius"]
94
+ surface_ratio = bottom_roughness["surface_ratio"]
95
+ self.assign_roughness_model(
96
+ model_type="huray",
97
+ huray_radius=nodule_radius,
98
+ huray_surface_ratio=surface_ratio,
99
+ apply_on_surface="bottom",
100
+ )
101
+ elif bottom_roughness["model"] == "groisse":
102
+ roughness = bottom_roughness["roughness"]
103
+ self.assign_roughness_model(
104
+ model_type="groisse", groisse_roughness=roughness, apply_on_surface="bottom"
105
+ )
106
+ if "side" in v:
107
+ side_roughness = v["side"]
108
+ if side_roughness:
109
+ if side_roughness["model"] == "huray":
110
+ nodule_radius = side_roughness["nodule_radius"]
111
+ surface_ratio = side_roughness["surface_ratio"]
112
+ self.assign_roughness_model(
113
+ model_type="huray",
114
+ huray_radius=nodule_radius,
115
+ huray_surface_ratio=surface_ratio,
116
+ apply_on_surface="side",
117
+ )
118
+ elif side_roughness["model"] == "groisse":
119
+ roughness = side_roughness["roughness"]
120
+ self.assign_roughness_model(
121
+ model_type="groisse", groisse_roughness=roughness, apply_on_surface="side"
122
+ )
123
+
124
+ elif k == "etching":
125
+ self.etch_factor_enabled = v["enabled"]
126
+ self.etch_factor = float(v["factor"])
127
+ else:
128
+ self._pedb.logger.error(f"{k} is not a valid layer attribute")
129
+
66
130
  def _create(self, layer_type):
67
131
  if layer_type in self._stackup_layer_mapping:
68
132
  layer_type = self._stackup_layer_mapping[layer_type]
@@ -99,12 +163,12 @@ class StackupLayer(GrpcStackupLayer):
99
163
  str
100
164
  Material name.
101
165
  """
102
- if self.is_stackup_layer:
166
+ if self.type == "signal":
103
167
  return self.get_fill_material()
104
168
 
105
169
  @fill_material.setter
106
170
  def fill_material(self, value):
107
- if self.is_stackup_layer:
171
+ if self.type == "signal":
108
172
  self.set_fill_material(value)
109
173
 
110
174
  @property
@@ -258,16 +322,24 @@ class StackupLayer(GrpcStackupLayer):
258
322
  float
259
323
  Nodule radius value.
260
324
  """
261
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
262
- if top_roughness_model:
263
- return top_roughness_model.nodule_radius.value
264
- else:
325
+ try:
326
+ top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
327
+ if len(top_roughness_model) == 2:
328
+ return top_roughness_model[0].value
329
+ else:
330
+ return None
331
+ except:
265
332
  return None
266
333
 
267
334
  @top_hallhuray_nodule_radius.setter
268
335
  def top_hallhuray_nodule_radius(self, value):
269
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
270
- top_roughness_model.nodule_radius = GrpcValue(value)
336
+ try:
337
+ top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
338
+ if len(top_roughness_model) == 2:
339
+ top_roughness_model[0] = GrpcValue(value)
340
+ self.set_roughness_model(top_roughness_model, GrpcRoughnessRegion.TOP)
341
+ except:
342
+ pass
271
343
 
272
344
  @property
273
345
  def top_hallhuray_surface_ratio(self):
@@ -278,16 +350,24 @@ class StackupLayer(GrpcStackupLayer):
278
350
  float
279
351
  Surface ratio.
280
352
  """
281
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
282
- if top_roughness_model:
283
- return top_roughness_model.surface_ratio.value
284
- else:
353
+ try:
354
+ top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
355
+ if len(top_roughness_model) == 2:
356
+ return top_roughness_model[1].value
357
+ else:
358
+ return None
359
+ except:
285
360
  return None
286
361
 
287
362
  @top_hallhuray_surface_ratio.setter
288
363
  def top_hallhuray_surface_ratio(self, value):
289
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
290
- top_roughness_model.surface_roughness = GrpcValue(value)
364
+ try:
365
+ top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
366
+ if len(top_roughness_model) == 2:
367
+ top_roughness_model[1] = GrpcValue(value)
368
+ self.set_roughness_model(top_roughness_model, GrpcRoughnessRegion.TOP)
369
+ except:
370
+ pass
291
371
 
292
372
  @property
293
373
  def bottom_hallhuray_nodule_radius(self):
@@ -298,15 +378,24 @@ class StackupLayer(GrpcStackupLayer):
298
378
  float
299
379
  Nodule radius.
300
380
  """
301
- bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
302
- if bottom_roughness_model:
303
- return bottom_roughness_model.nodule_radius.value
304
- return None
381
+ try:
382
+ bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
383
+ if len(bottom_roughness_model) == 2:
384
+ return round(bottom_roughness_model[0].value, 9)
385
+ else:
386
+ return None
387
+ except:
388
+ return None
305
389
 
306
390
  @bottom_hallhuray_nodule_radius.setter
307
391
  def bottom_hallhuray_nodule_radius(self, value):
308
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
309
- top_roughness_model.nodule_radius = GrpcValue(value)
392
+ try:
393
+ bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
394
+ if len(bottom_roughness_model) == 2:
395
+ bottom_roughness_model[0] = GrpcValue(value)
396
+ self.set_roughness_model(bottom_roughness_model, GrpcRoughnessRegion.BOTTOM)
397
+ except:
398
+ pass
310
399
 
311
400
  @property
312
401
  def bottom_hallhuray_surface_ratio(self):
@@ -317,15 +406,24 @@ class StackupLayer(GrpcStackupLayer):
317
406
  float
318
407
  Surface ratio value.
319
408
  """
320
- bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
321
- if bottom_roughness_model:
322
- return bottom_roughness_model.surface_ratio.value
323
- return None
409
+ try:
410
+ bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
411
+ if len(bottom_roughness_model) == 2:
412
+ return bottom_roughness_model[1].value
413
+ else:
414
+ return None
415
+ except:
416
+ return None
324
417
 
325
418
  @bottom_hallhuray_surface_ratio.setter
326
419
  def bottom_hallhuray_surface_ratio(self, value):
327
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
328
- top_roughness_model.surface_ratio = GrpcValue(value)
420
+ try:
421
+ bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
422
+ if len(bottom_roughness_model) == 2:
423
+ bottom_roughness_model[1] = GrpcValue(value)
424
+ self.set_roughness_model(bottom_roughness_model, GrpcRoughnessRegion.BOTTOM)
425
+ except:
426
+ pass
329
427
 
330
428
  @property
331
429
  def side_hallhuray_nodule_radius(self):
@@ -337,15 +435,23 @@ class StackupLayer(GrpcStackupLayer):
337
435
  Nodule radius value.
338
436
 
339
437
  """
340
- side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
341
- if side_roughness_model:
342
- return side_roughness_model.nodule_radius.value
343
- return None
438
+ try:
439
+ side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
440
+ if len(side_roughness_model) == 2:
441
+ return round(side_roughness_model[0].value, 9)
442
+ return None
443
+ except:
444
+ return None
344
445
 
345
446
  @side_hallhuray_nodule_radius.setter
346
447
  def side_hallhuray_nodule_radius(self, value):
347
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
348
- top_roughness_model.nodule_radius = GrpcValue(value)
448
+ try:
449
+ side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
450
+ if len(side_roughness_model) == 2:
451
+ side_roughness_model[0] = GrpcValue(value)
452
+ self.set_roughness_model(side_roughness_model, GrpcRoughnessRegion.SIDE)
453
+ except:
454
+ pass
349
455
 
350
456
  @property
351
457
  def side_hallhuray_surface_ratio(self):
@@ -356,16 +462,107 @@ class StackupLayer(GrpcStackupLayer):
356
462
  float
357
463
  surface ratio.
358
464
  """
359
- side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
360
- if side_roughness_model:
361
- return side_roughness_model.surface_ratio.value
362
- else:
465
+ try:
466
+ side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
467
+ if len(side_roughness_model) == 2:
468
+ return side_roughness_model[1].value
469
+ return None
470
+ except:
363
471
  return None
364
472
 
365
473
  @side_hallhuray_surface_ratio.setter
366
474
  def side_hallhuray_surface_ratio(self, value):
367
- top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
368
- top_roughness_model.surface_ratio = GrpcValue(value)
475
+ try:
476
+ side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
477
+ if len(side_roughness_model) == 2:
478
+ side_roughness_model[1] = GrpcValue(value)
479
+ self.set_roughness_model(side_roughness_model, GrpcRoughnessRegion.SIDE)
480
+ except:
481
+ pass
482
+
483
+ @property
484
+ def top_groisse_roughness(self):
485
+ """Groisse model on layer top.
486
+
487
+ Returns
488
+ -------
489
+ float
490
+ Roughness value.
491
+ """
492
+ try:
493
+ top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
494
+ if isinstance(top_roughness_model, GrpcValue):
495
+ return top_roughness_model.value
496
+ else:
497
+ return None
498
+ except:
499
+ return None
500
+
501
+ @top_groisse_roughness.setter
502
+ def top_groisse_roughness(self, value):
503
+ try:
504
+ top_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.TOP)
505
+ if isinstance(top_roughness_model, GrpcValue):
506
+ top_roughness_model = GrpcValue(value)
507
+ self.set_roughness_model(top_roughness_model, GrpcRoughnessRegion.TOP)
508
+ except:
509
+ pass
510
+
511
+ @property
512
+ def bottom_groisse_roughness(self):
513
+ """Groisse model on layer bottom.
514
+
515
+ Returns
516
+ -------
517
+ float
518
+ Roughness value.
519
+ """
520
+ try:
521
+ bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
522
+ if isinstance(bottom_roughness_model, GrpcValue):
523
+ return bottom_roughness_model.value
524
+ else:
525
+ return None
526
+ except:
527
+ return None
528
+
529
+ @bottom_groisse_roughness.setter
530
+ def bottom_groisse_roughness(self, value):
531
+ try:
532
+ bottom_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
533
+ if isinstance(bottom_roughness_model, GrpcValue):
534
+ bottom_roughness_model = GrpcValue(value)
535
+ self.set_roughness_model(bottom_roughness_model, GrpcRoughnessRegion.BOTTOM)
536
+ except:
537
+ pass
538
+
539
+ @property
540
+ def side_groisse_roughness(self):
541
+ """Groisse model on layer bottom.
542
+
543
+ Returns
544
+ -------
545
+ float
546
+ Roughness value.
547
+ """
548
+ try:
549
+ side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.SIDE)
550
+ if isinstance(side_roughness_model, GrpcValue):
551
+ return side_roughness_model.value
552
+ else:
553
+ return None
554
+ except:
555
+ return None
556
+
557
+ @side_groisse_roughness.setter
558
+ def side_groisse_roughness(self, value):
559
+ try:
560
+ side_roughness_model = self.get_roughness_model(GrpcRoughnessRegion.BOTTOM)
561
+ if isinstance(side_roughness_model, GrpcValue):
562
+ side_roughness_model = GrpcValue(value)
563
+ self.set_roughness_model(side_roughness_model, GrpcRoughnessRegion.BOTTOM)
564
+ except Exception as e:
565
+ self._pedb.logger.error(e)
369
566
 
370
567
  def assign_roughness_model(
371
568
  self,
@@ -400,7 +597,7 @@ class StackupLayer(GrpcStackupLayer):
400
597
  elif apply_on_surface == "bottom":
401
598
  regions = [GrpcRoughnessRegion.BOTTOM]
402
599
  elif apply_on_surface == "side":
403
- regions = [GrpcRoughnessRegion.BOTTOM]
600
+ regions = [GrpcRoughnessRegion.SIDE]
404
601
  self.roughness_enabled = True
405
602
  for r in regions:
406
603
  if model_type == "huray":
@@ -408,3 +605,47 @@ class StackupLayer(GrpcStackupLayer):
408
605
  else:
409
606
  model = GrpcValue(groisse_roughness)
410
607
  self.set_roughness_model(model, r)
608
+
609
+ @property
610
+ def properties(self):
611
+ data = {"name": self.name, "type": self.type, "color": self.color}
612
+ if self.type == "signal" or self.type == "dielectric":
613
+ data["material"] = self.material
614
+ data["thickness"] = self.thickness
615
+ if self.type == "signal":
616
+ data["fill_material"] = self.fill_material
617
+ roughness = {"top": {}, "bottom": {}, "side": {}}
618
+ if self.top_hallhuray_nodule_radius:
619
+ roughness["top"]["model"] = "huray"
620
+ roughness["top"]["nodule_radius"] = self.top_hallhuray_nodule_radius
621
+ roughness["top"]["surface_ratio"] = self.top_hallhuray_surface_ratio
622
+
623
+ elif self.top_groisse_roughness:
624
+ roughness["top"]["model"] = "groisse"
625
+ roughness["top"]["roughness"] = self.top_groisse_roughness
626
+
627
+ if self.bottom_hallhuray_nodule_radius:
628
+ roughness["bottom"]["model"] = "huray"
629
+ roughness["bottom"]["nodule_radius"] = self.bottom_hallhuray_nodule_radius
630
+ roughness["bottom"]["surface_ratio"] = self.bottom_hallhuray_surface_ratio
631
+
632
+ elif self.bottom_groisse_roughness:
633
+ roughness["bottom"]["model"] = "groisse"
634
+ roughness["bottom"]["roughness"] = self.bottom_groisse_roughness
635
+
636
+ if self.side_hallhuray_nodule_radius:
637
+ roughness["side"]["model"] = "huray"
638
+ roughness["side"]["nodule_radius"] = self.side_hallhuray_nodule_radius
639
+ roughness["side"]["surface_ratio"] = self.side_hallhuray_surface_ratio
640
+
641
+ elif self.side_groisse_roughness:
642
+ roughness["side"]["model"] = "groisse"
643
+ roughness["side"]["roughness"] = self.side_groisse_roughness
644
+
645
+ if roughness["top"] or roughness["bottom"] or roughness["side"]:
646
+ roughness["enabled"] = True
647
+ else:
648
+ roughness["enabled"] = False
649
+ data["roughness"] = roughness
650
+ data["etching"] = {"enabled": self.etch_factor_enabled, "factor": self.etch_factor}
651
+ return data