pyedb 0.56.0__py3-none-any.whl → 0.57.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 (99) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_data.py +3 -0
  3. pyedb/configuration/cfg_terminals.py +232 -0
  4. pyedb/configuration/configuration.py +146 -3
  5. pyedb/dotnet/clr_module.py +1 -2
  6. pyedb/dotnet/database/Variables.py +30 -22
  7. pyedb/dotnet/database/cell/layout.py +5 -1
  8. pyedb/dotnet/database/cell/primitive/primitive.py +2 -2
  9. pyedb/dotnet/database/cell/terminal/bundle_terminal.py +12 -0
  10. pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
  11. pyedb/dotnet/database/cell/terminal/terminal.py +38 -0
  12. pyedb/dotnet/database/components.py +14 -16
  13. pyedb/dotnet/database/dotnet/database.py +1 -0
  14. pyedb/dotnet/database/edb_data/control_file.py +6 -3
  15. pyedb/dotnet/database/edb_data/nets_data.py +3 -3
  16. pyedb/dotnet/database/edb_data/padstacks_data.py +5 -2
  17. pyedb/dotnet/database/edb_data/ports.py +0 -25
  18. pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
  19. pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +18 -19
  20. pyedb/dotnet/database/edb_data/simulation_configuration.py +3 -3
  21. pyedb/dotnet/database/hfss.py +9 -8
  22. pyedb/dotnet/database/layout_validation.py +6 -3
  23. pyedb/dotnet/database/materials.py +1 -3
  24. pyedb/dotnet/database/modeler.py +7 -3
  25. pyedb/dotnet/database/nets.py +27 -19
  26. pyedb/dotnet/database/padstack.py +4 -2
  27. pyedb/dotnet/database/sim_setup_data/io/siwave.py +1 -1
  28. pyedb/dotnet/database/siwave.py +4 -3
  29. pyedb/dotnet/database/stackup.py +50 -26
  30. pyedb/dotnet/database/utilities/heatsink.py +0 -1
  31. pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
  32. pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
  33. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +5 -2
  34. pyedb/dotnet/edb.py +39 -34
  35. pyedb/exceptions.py +1 -2
  36. pyedb/extensions/create_cell_array.py +19 -5
  37. pyedb/generic/data_handlers.py +13 -23
  38. pyedb/generic/design_types.py +9 -35
  39. pyedb/generic/filesystem.py +4 -2
  40. pyedb/generic/general_methods.py +4 -5
  41. pyedb/generic/plot.py +2 -2
  42. pyedb/grpc/database/_typing.py +0 -0
  43. pyedb/grpc/database/components.py +7 -8
  44. pyedb/grpc/database/control_file.py +14 -35
  45. pyedb/grpc/database/definition/materials.py +1 -1
  46. pyedb/grpc/database/definition/package_def.py +6 -3
  47. pyedb/grpc/database/definition/padstack_def.py +4 -7
  48. pyedb/grpc/database/hfss.py +1 -4
  49. pyedb/grpc/database/hierarchy/component.py +3 -4
  50. pyedb/grpc/database/hierarchy/pingroup.py +16 -3
  51. pyedb/grpc/database/layers/layer.py +1 -2
  52. pyedb/grpc/database/layers/stackup_layer.py +42 -19
  53. pyedb/grpc/database/layout/layout.py +43 -27
  54. pyedb/grpc/database/layout/voltage_regulator.py +6 -1
  55. pyedb/grpc/database/layout_validation.py +5 -2
  56. pyedb/grpc/database/modeler.py +226 -244
  57. pyedb/grpc/database/net/differential_pair.py +9 -2
  58. pyedb/grpc/database/net/extended_net.py +24 -9
  59. pyedb/grpc/database/net/net.py +14 -5
  60. pyedb/grpc/database/net/net_class.py +24 -7
  61. pyedb/grpc/database/nets.py +11 -43
  62. pyedb/grpc/database/padstacks.py +5 -16
  63. pyedb/grpc/database/primitive/bondwire.py +3 -67
  64. pyedb/grpc/database/primitive/circle.py +42 -3
  65. pyedb/grpc/database/primitive/padstack_instance.py +17 -19
  66. pyedb/grpc/database/primitive/path.py +154 -5
  67. pyedb/grpc/database/primitive/polygon.py +73 -7
  68. pyedb/grpc/database/primitive/primitive.py +2 -2
  69. pyedb/grpc/database/primitive/rectangle.py +105 -4
  70. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
  71. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
  72. pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +1 -0
  73. pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
  74. pyedb/grpc/database/siwave.py +6 -13
  75. pyedb/grpc/database/source_excitations.py +39 -56
  76. pyedb/grpc/database/stackup.py +50 -27
  77. pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
  78. pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
  79. pyedb/grpc/database/terminal/terminal.py +19 -8
  80. pyedb/grpc/database/utility/heat_sink.py +0 -1
  81. pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
  82. pyedb/grpc/database/utility/xml_control_file.py +6 -3
  83. pyedb/grpc/edb.py +24 -19
  84. pyedb/grpc/edb_init.py +1 -0
  85. pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
  86. pyedb/ipc2581/ecad/cad_data/step.py +1 -1
  87. pyedb/ipc2581/ipc2581.py +8 -7
  88. pyedb/libraries/common.py +3 -4
  89. pyedb/libraries/rf_libraries/base_functions.py +7 -16
  90. pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
  91. pyedb/misc/downloads.py +1 -0
  92. pyedb/misc/misc.py +5 -2
  93. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +1 -1
  94. pyedb/misc/utilities.py +0 -1
  95. pyedb/modeler/geometry_operators.py +3 -2
  96. {pyedb-0.56.0.dist-info → pyedb-0.57.0.dist-info}/METADATA +3 -3
  97. {pyedb-0.56.0.dist-info → pyedb-0.57.0.dist-info}/RECORD +99 -97
  98. {pyedb-0.56.0.dist-info → pyedb-0.57.0.dist-info}/WHEEL +0 -0
  99. {pyedb-0.56.0.dist-info → pyedb-0.57.0.dist-info}/licenses/LICENSE +0 -0
@@ -1137,7 +1137,7 @@ class Stackup(LayerCollection):
1137
1137
 
1138
1138
  Examples
1139
1139
  --------
1140
- >>> edb = Edb(edbpath=targetfile, edbversion="2021.2")
1140
+ >>> edb = Edb(edbpath=targetfile, edbversion="2021.2")
1141
1141
  >>> edb.stackup.flip_design()
1142
1142
  >>> edb.save()
1143
1143
  >>> edb.close_edb()
@@ -1227,8 +1227,11 @@ class Stackup(LayerCollection):
1227
1227
  sball_prop = cmp_prop.GetSolderBallProperty().Clone()
1228
1228
  sball_prop.SetPlacement(self._pedb.definition.SolderballPlacement.AbovePadstack)
1229
1229
  cmp_prop.SetSolderBallProperty(sball_prop)
1230
- except:
1231
- pass
1230
+ except Exception as e:
1231
+ self._logger.warning(
1232
+ f"A(n) {type(e).__name__} error occurred while attempting to update "
1233
+ f"SolderBallProperty for component {cmp}: {str(e)}"
1234
+ )
1232
1235
  if cmp_type == self._pedb.definition.ComponentType.IC:
1233
1236
  die_prop = cmp_prop.GetDieProperty().Clone()
1234
1237
  chip_orientation = die_prop.GetOrientation()
@@ -1356,22 +1359,28 @@ class Stackup(LayerCollection):
1356
1359
 
1357
1360
  Examples
1358
1361
  --------
1359
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1362
+ >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1360
1363
  >>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
1361
1364
 
1362
1365
  >>> hosting_cmp = edb1.components.get_component_by_name("U100")
1363
1366
  >>> mounted_cmp = edb2.components.get_component_by_name("BGA")
1364
1367
 
1365
1368
  >>> vector, rotation, solder_ball_height = edb1.components.get_component_placement_vector(
1366
- ... mounted_component=mounted_cmp,
1367
- ... hosting_component=hosting_cmp,
1368
- ... mounted_component_pin1="A12",
1369
- ... mounted_component_pin2="A14",
1370
- ... hosting_component_pin1="A12",
1371
- ... hosting_component_pin2="A14")
1372
- >>> edb2.stackup.place_in_layout(edb1.active_cell, angle=0.0, offset_x=vector[0],
1373
- ... offset_y=vector[1], flipped_stackup=False, place_on_top=True,
1374
- ... )
1369
+ ... mounted_component=mounted_cmp,
1370
+ ... hosting_component=hosting_cmp,
1371
+ ... mounted_component_pin1="A12",
1372
+ ... mounted_component_pin2="A14",
1373
+ ... hosting_component_pin1="A12",
1374
+ ... hosting_component_pin2="A14",
1375
+ ... )
1376
+ >>> edb2.stackup.place_in_layout(
1377
+ ... edb1.active_cell,
1378
+ ... angle=0.0,
1379
+ ... offset_x=vector[0],
1380
+ ... offset_y=vector[1],
1381
+ ... flipped_stackup=False,
1382
+ ... place_on_top=True,
1383
+ ... )
1375
1384
  """
1376
1385
  # if flipped_stackup and place_on_top or (not flipped_stackup and not place_on_top):
1377
1386
  self.adjust_solder_dielectrics()
@@ -1453,13 +1462,18 @@ class Stackup(LayerCollection):
1453
1462
 
1454
1463
  Examples
1455
1464
  --------
1456
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1465
+ >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1457
1466
  >>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
1458
1467
  >>> hosting_cmp = edb1.components.get_component_by_name("U100")
1459
1468
  >>> mounted_cmp = edb2.components.get_component_by_name("BGA")
1460
- >>> edb2.stackup.place_in_layout(edb1.active_cell, angle=0.0, offset_x="1mm",
1461
- ... offset_y="2mm", flipped_stackup=False, place_on_top=True,
1462
- ... )
1469
+ >>> edb2.stackup.place_in_layout(
1470
+ ... edb1.active_cell,
1471
+ ... angle=0.0,
1472
+ ... offset_x="1mm",
1473
+ ... offset_y="2mm",
1474
+ ... flipped_stackup=False,
1475
+ ... place_on_top=True,
1476
+ ... )
1463
1477
  """
1464
1478
  _angle = angle * math.pi / 180.0
1465
1479
 
@@ -1592,13 +1606,18 @@ class Stackup(LayerCollection):
1592
1606
 
1593
1607
  Examples
1594
1608
  --------
1595
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1609
+ >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1596
1610
  >>> edb2 = Edb(edbpath=targetfile2, edbversion="2021.2")
1597
1611
  >>> hosting_cmp = edb1.components.get_component_by_name("U100")
1598
1612
  >>> mounted_cmp = edb2.components.get_component_by_name("BGA")
1599
- >>> edb1.stackup.place_instance(edb2, angle=0.0, offset_x="1mm",
1600
- ... offset_y="2mm", flipped_stackup=False, place_on_top=True,
1601
- ... )
1613
+ >>> edb1.stackup.place_instance(
1614
+ ... edb2,
1615
+ ... angle=0.0,
1616
+ ... offset_x="1mm",
1617
+ ... offset_y="2mm",
1618
+ ... flipped_stackup=False,
1619
+ ... place_on_top=True,
1620
+ ... )
1602
1621
  """
1603
1622
  _angle = angle * math.pi / 180.0
1604
1623
 
@@ -1736,11 +1755,16 @@ class Stackup(LayerCollection):
1736
1755
 
1737
1756
  Examples
1738
1757
  --------
1739
- >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1758
+ >>> edb1 = Edb(edbpath=targetfile1, edbversion="2021.2")
1740
1759
  >>> a3dcomp_path = "connector.a3dcomp"
1741
- >>> edb1.stackup.place_a3dcomp_3d_placement(a3dcomp_path, angle=0.0, offset_x="1mm",
1742
- ... offset_y="2mm", flipped_stackup=False, place_on_top=True,
1743
- ... )
1760
+ >>> edb1.stackup.place_a3dcomp_3d_placement(
1761
+ ... a3dcomp_path,
1762
+ ... angle=0.0,
1763
+ ... offset_x="1mm",
1764
+ ... offset_y="2mm",
1765
+ ... flipped_stackup=False,
1766
+ ... place_on_top=True,
1767
+ ... )
1744
1768
  """
1745
1769
  zero_data = self._edb_value(0.0)
1746
1770
  one_data = self._edb_value(1.0)
@@ -1795,7 +1819,7 @@ class Stackup(LayerCollection):
1795
1819
 
1796
1820
  Examples
1797
1821
  --------
1798
- >>> edb = Edb(edbpath=targetfile1, edbversion="2021.2")
1822
+ >>> edb = Edb(edbpath=targetfile1, edbversion="2021.2")
1799
1823
  >>> edb.stackup.residual_copper_area_per_layer()
1800
1824
  """
1801
1825
  temp_data = {name: 0 for name, _ in self.signal_layers.items()}
@@ -1,5 +1,4 @@
1
1
  class HeatSink:
2
-
3
2
  """Heatsink model description.
4
3
 
5
4
  Parameters
@@ -371,11 +371,13 @@ class SimulationSetup(object):
371
371
  Examples
372
372
  --------
373
373
  >>> setup1 = edbapp.create_siwave_syz_setup("setup1")
374
- >>> setup1.add_frequency_sweep(frequency_sweep=[
375
- ... ["linear count", "0", "1kHz", 1],
376
- ... ["log scale", "1kHz", "0.1GHz", 10],
377
- ... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
378
- ... ])
374
+ >>> setup1.add_frequency_sweep(
375
+ ... frequency_sweep=[
376
+ ... ["linear count", "0", "1kHz", 1],
377
+ ... ["log scale", "1kHz", "0.1GHz", 10],
378
+ ... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
379
+ ... ]
380
+ ... )
379
381
  """
380
382
  warnings.warn("`add_frequency_sweep` is deprecated. Use `add_sweep` method instead.", DeprecationWarning)
381
383
  return self.add_sweep(name, frequency_sweep)
@@ -691,6 +691,7 @@ class SIWaveCPASimulationSetup:
691
691
  self._pedb = pedb
692
692
  self._channel_setup = ChannelSetup(pedb)
693
693
  self._solver_options = SolverOptions(pedb)
694
+ self.type = "cpa"
694
695
  if isinstance(siwave_cpa_setup_class, SIwaveCpaSetup):
695
696
  self._apply_cfg_object(siwave_cpa_setup_class)
696
697
  else:
@@ -15,6 +15,7 @@ from pyedb.dotnet.database.sim_setup_data.io.siwave import (
15
15
  )
16
16
  from pyedb.dotnet.database.utilities.simulation_setup import SimulationSetup
17
17
  from pyedb.generic.general_methods import is_linux
18
+ from pyedb.generic.settings import settings
18
19
 
19
20
 
20
21
  def _parse_value(v):
@@ -79,8 +80,10 @@ def clone_edb_sim_setup_info(source, target):
79
80
  except TypeError:
80
81
  try:
81
82
  setter.__setattr__(k, str(value))
82
- except:
83
- pass
83
+ except Exception as e:
84
+ settings.logger.warning(
85
+ f"Failed to update attribute {k} with value {value} - {type(e).__name__}: {str(e)}"
86
+ )
84
87
 
85
88
 
86
89
  class SiwaveSimulationSetup(SimulationSetup):
pyedb/dotnet/edb.py CHANGED
@@ -25,6 +25,7 @@
25
25
  This module is implicitly loaded in HFSS 3D Layout when launched.
26
26
 
27
27
  """
28
+
28
29
  from datetime import datetime
29
30
  from itertools import combinations
30
31
  import os
@@ -43,7 +44,6 @@ import rtree
43
44
 
44
45
  from pyedb.configuration.configuration import Configuration
45
46
  import pyedb.dotnet
46
- from pyedb.dotnet.database.Variables import decompose_variable_value
47
47
  from pyedb.dotnet.database.cell.layout import Layout
48
48
  from pyedb.dotnet.database.cell.terminal.terminal import Terminal
49
49
  from pyedb.dotnet.database.components import Components
@@ -92,6 +92,7 @@ from pyedb.dotnet.database.utilities.siwave_simulation_setup import (
92
92
  SiwaveSimulationSetup,
93
93
  )
94
94
  from pyedb.dotnet.database.utilities.value import Value
95
+ from pyedb.dotnet.database.Variables import decompose_variable_value
95
96
  from pyedb.generic.constants import AEDT_UNITS, SolverType, unit_converter
96
97
  from pyedb.generic.general_methods import generate_unique_name, is_linux, is_windows
97
98
  from pyedb.generic.process import SiwaveSolve
@@ -152,19 +153,19 @@ class Edb:
152
153
 
153
154
  Add a new variable named "s1" to the ``Edb`` instance.
154
155
 
155
- >>> app['s1'] = "0.25 mm"
156
- >>> app['s1'].tofloat
156
+ >>> app["s1"] = "0.25 mm"
157
+ >>> app["s1"].tofloat
157
158
  >>> 0.00025
158
- >>> app['s1'].tostring
159
+ >>> app["s1"].tostring
159
160
  >>> "0.25mm"
160
161
 
161
162
  or add a new parameter with description:
162
163
 
163
- >>> app['s2'] = ["20um", "Spacing between traces"]
164
- >>> app['s2'].value
164
+ >>> app["s2"] = ["20um", "Spacing between traces"]
165
+ >>> app["s2"].value
165
166
  >>> 1.9999999999999998e-05
166
- >>> app['s2'].description
167
- >>> 'Spacing between traces'
167
+ >>> app["s2"].description
168
+ >>> "Spacing between traces"
168
169
 
169
170
  Create an ``Edb`` object and open the specified project.
170
171
 
@@ -1852,8 +1853,11 @@ class Edb:
1852
1853
  convert_py_list_to_net_list(list(obj_data)),
1853
1854
  convert_py_list_to_net_list(voids_poly),
1854
1855
  )
1855
- except:
1856
- pass
1856
+ except Exception as e:
1857
+ self.logger.error(
1858
+ f"A(n) {type(e).__name__} error occurred in method _create_conformal of "
1859
+ f"class Edb at iteration {k} for data {i}: {str(e)}"
1860
+ )
1857
1861
  finally:
1858
1862
  unite_polys.extend(list(obj_data))
1859
1863
  _poly_unite = self.core.Geometry.PolygonData.Unite(convert_py_list_to_net_list(unite_polys))
@@ -2048,7 +2052,7 @@ class Edb:
2048
2052
  Examples
2049
2053
  --------
2050
2054
  >>> from pyedb import Edb
2051
- >>> edb = Edb(r'C:\\test.aedb', version="2022.2")
2055
+ >>> edb = Edb(r"C:\\test.aedb", version="2022.2")
2052
2056
  >>> edb.logger.info_timer("Edb Opening")
2053
2057
  >>> edb.logger.reset_timer()
2054
2058
  >>> start = time.time()
@@ -2058,7 +2062,7 @@ class Edb:
2058
2062
  >>> signal_list.append(net)
2059
2063
  >>> power_list = ["PGND"]
2060
2064
  >>> edb.cutout(signal_list=signal_list, reference_list=power_list, extent_type="Conforming")
2061
- >>> end_time = str((time.time() - start)/60)
2065
+ >>> end_time = str((time.time() - start) / 60)
2062
2066
  >>> edb.logger.info("Total legacy cutout time in min %s", end_time)
2063
2067
  >>> edb.nets.plot(signal_list, None, color_by_net=True)
2064
2068
  >>> edb.nets.plot(power_list, None, color_by_net=True)
@@ -2291,8 +2295,8 @@ class Edb:
2291
2295
  if os.path.exists(source) and not os.path.exists(target):
2292
2296
  try:
2293
2297
  shutil.copy(source, target)
2294
- except:
2295
- pass
2298
+ except Exception as e:
2299
+ self.logger.error(f"Failed to copy {source} to {target} - {type(e).__name__}: {str(e)}")
2296
2300
  elif open_cutout_at_end:
2297
2301
  self._active_cell = _cutout
2298
2302
  self._init_objects()
@@ -2708,7 +2712,7 @@ class Edb:
2708
2712
  Examples
2709
2713
  --------
2710
2714
  >>> from pyedb import Edb
2711
- >>> edb = Edb(r'C:\\test.aedb', version="2022.2")
2715
+ >>> edb = Edb(r"C:\\test.aedb", version="2022.2")
2712
2716
  >>> edb.logger.info_timer("Edb Opening")
2713
2717
  >>> edb.logger.reset_timer()
2714
2718
  >>> start = time.time()
@@ -2718,7 +2722,7 @@ class Edb:
2718
2722
  >>> signal_list.append(net)
2719
2723
  >>> power_list = ["PGND"]
2720
2724
  >>> edb.create_cutout_multithread(signal_list=signal_list, reference_list=power_list, extent_type="Conforming")
2721
- >>> end_time = str((time.time() - start)/60)
2725
+ >>> end_time = str((time.time() - start) / 60)
2722
2726
  >>> edb.logger.info("Total legacy cutout time in min %s", end_time)
2723
2727
  >>> edb.nets.plot(signal_list, None, color_by_net=True)
2724
2728
  >>> edb.nets.plot(power_list, None, color_by_net=True)
@@ -2977,8 +2981,8 @@ class Edb:
2977
2981
  try:
2978
2982
  shutil.copy(source, target)
2979
2983
  self.logger.warning("aedb def file manually created.")
2980
- except:
2981
- pass
2984
+ except Exception as e:
2985
+ self.logger.error(f"Failed to copy {source} to {target} - {type(e).__name__}: {str(e)}")
2982
2986
  return [[pt.X.ToDouble(), pt.Y.ToDouble()] for pt in list(polygonData.GetPolygonWithoutArcs().Points)]
2983
2987
 
2984
2988
  def create_cutout_on_point_list(
@@ -3107,7 +3111,7 @@ class Edb:
3107
3111
  >>> from pyedb import Edb
3108
3112
  >>> edb = Edb(edbpath="C:\\temp\\myproject.aedb", version="2023.2")
3109
3113
 
3110
- >>> options_config = {'UNITE_NETS' : 1, 'LAUNCH_Q3D' : 0}
3114
+ >>> options_config = {"UNITE_NETS": 1, "LAUNCH_Q3D": 0}
3111
3115
  >>> edb.write_export3d_option_config_file(r"C:\\temp", options_config)
3112
3116
  >>> edb.export_hfss(r"C:\\temp")
3113
3117
  """
@@ -3149,7 +3153,7 @@ class Edb:
3149
3153
 
3150
3154
  >>> from pyedb import Edb
3151
3155
  >>> edb = Edb(edbpath="C:\\temp\\myproject.aedb", version="2021.2")
3152
- >>> options_config = {'UNITE_NETS' : 1, 'LAUNCH_Q3D' : 0}
3156
+ >>> options_config = {"UNITE_NETS": 1, "LAUNCH_Q3D": 0}
3153
3157
  >>> edb.write_export3d_option_config_file("C:\\temp", options_config)
3154
3158
  >>> edb.export_q3d("C:\\temp")
3155
3159
  """
@@ -3201,7 +3205,7 @@ class Edb:
3201
3205
 
3202
3206
  >>> edb = Edb(edbpath="C:\\temp\\myproject.aedb", version="2021.2")
3203
3207
 
3204
- >>> options_config = {'UNITE_NETS' : 1, 'LAUNCH_Q3D' : 0}
3208
+ >>> options_config = {"UNITE_NETS": 1, "LAUNCH_Q3D": 0}
3205
3209
  >>> edb.write_export3d_option_config_file("C:\\temp", options_config)
3206
3210
  >>> edb.export_maxwell("C:\\temp")
3207
3211
  """
@@ -3369,8 +3373,8 @@ class Edb:
3369
3373
  >>> from pyedb import Edb
3370
3374
  >>> edb_app = Edb()
3371
3375
  >>> boolean_1, ant_length = edb_app.add_project_variable("my_local_variable", "1cm")
3372
- >>> print(edb_app["$my_local_variable"]) #using getitem
3373
- >>> edb_app["$my_local_variable"] = "1cm" #using setitem
3376
+ >>> print(edb_app["$my_local_variable"]) # using getitem
3377
+ >>> edb_app["$my_local_variable"] = "1cm" # using setitem
3374
3378
 
3375
3379
  """
3376
3380
  if not variable_name.startswith("$"):
@@ -3408,8 +3412,8 @@ class Edb:
3408
3412
  >>> from pyedb import Edb
3409
3413
  >>> edb_app = Edb()
3410
3414
  >>> boolean_1, ant_length = edb_app.add_design_variable("my_local_variable", "1cm")
3411
- >>> print(edb_app["my_local_variable"]) #using getitem
3412
- >>> edb_app["my_local_variable"] = "1cm" #using setitem
3415
+ >>> print(edb_app["my_local_variable"]) # using getitem
3416
+ >>> edb_app["my_local_variable"] = "1cm" # using setitem
3413
3417
  >>> boolean_2, para_length = edb_app.change_design_variable_value("my_parameter", "1m", is_parameter=True
3414
3418
  >>> boolean_3, project_length = edb_app.change_design_variable_value("$my_project_variable", "1m")
3415
3419
 
@@ -3449,7 +3453,7 @@ class Edb:
3449
3453
  >>> edb_app = Edb()
3450
3454
  >>> boolean, ant_length = edb_app.add_design_variable("ant_length", "1cm")
3451
3455
  >>> boolean, ant_length = edb_app.change_design_variable_value("ant_length", "1m")
3452
- >>> print(edb_app["ant_length"]) #using getitem
3456
+ >>> print(edb_app["ant_length"]) # using getitem
3453
3457
  """
3454
3458
  var_server = self.variable_exists(variable_name)
3455
3459
  if var_server[0]:
@@ -3928,11 +3932,13 @@ class Edb:
3928
3932
  >>> from pyedb import Edb
3929
3933
  >>> edbapp = Edb()
3930
3934
  >>> setup1 = edbapp.create_siwave_syz_setup("setup1")
3931
- >>> setup1.add_frequency_sweep(frequency_sweep=[
3932
- ... ["linear count", "0", "1kHz", 1],
3933
- ... ["log scale", "1kHz", "0.1GHz", 10],
3934
- ... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
3935
- ... ])
3935
+ >>> setup1.add_frequency_sweep(
3936
+ ... frequency_sweep=[
3937
+ ... ["linear count", "0", "1kHz", 1],
3938
+ ... ["log scale", "1kHz", "0.1GHz", 10],
3939
+ ... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
3940
+ ... ]
3941
+ ... )
3936
3942
  """
3937
3943
  if not name:
3938
3944
  name = generate_unique_name("Siwave_SYZ")
@@ -4687,8 +4693,7 @@ class Edb:
4687
4693
  ]
4688
4694
  if not polys:
4689
4695
  raise RuntimeWarning(
4690
- f"No polygon found with voids on layer {reference_layer} during model creation for "
4691
- f"arbitrary wave ports"
4696
+ f"No polygon found with voids on layer {reference_layer} during model creation for arbitrary wave ports"
4692
4697
  )
4693
4698
  void_padstacks = []
4694
4699
  for poly in polys:
@@ -4705,7 +4710,7 @@ class Edb:
4705
4710
 
4706
4711
  if not void_padstacks:
4707
4712
  raise RuntimeWarning(
4708
- "No padstack instances found inside evaluated voids during model creation for arbitrary" "waveports"
4713
+ "No padstack instances found inside evaluated voids during model creation for arbitrary waveports"
4709
4714
  )
4710
4715
  cloned_edb = Edb(edbpath=output_edb)
4711
4716
 
pyedb/exceptions.py CHANGED
@@ -1,5 +1,4 @@
1
- """
2
- """
1
+ """ """
3
2
 
4
3
 
5
4
  class MaterialModelException(Exception):
@@ -23,6 +23,7 @@
23
23
  """
24
24
  This module contains the array building feature from unit cell.
25
25
  """
26
+
26
27
  import itertools
27
28
  from typing import Optional, Union
28
29
 
@@ -36,8 +37,8 @@ def create_array_from_unit_cell(
36
37
  edb: Edb,
37
38
  x_number: int = 2,
38
39
  y_number: int = 2,
39
- offset_x: Optional[Union[int, float]] = None,
40
- offset_y: Optional[Union[int, float]] = None,
40
+ offset_x: Optional[Union[int, float, str]] = None,
41
+ offset_y: Optional[Union[int, float, str]] = None,
41
42
  ) -> bool:
42
43
  """
43
44
  Create a 2-D rectangular array from the current EDB unit cell.
@@ -56,10 +57,10 @@ def create_array_from_unit_cell(
56
57
  Number of columns (X-direction). Must be > 0. Defaults to 2.
57
58
  y_number : int, optional
58
59
  Number of rows (Y-direction). Must be > 0. Defaults to 2.
59
- offset_x : int | float | None, optional
60
+ offset_x : int | float | str, None, optional
60
61
  Horizontal pitch (distance between cell origins). When *None* the
61
62
  value is derived from the outline geometry.
62
- offset_y : int | float | None, optional
63
+ offset_y : int | float | str, None, optional
63
64
  Vertical pitch (distance between cell origins). When *None* the
64
65
  value is derived from the outline geometry.
65
66
 
@@ -133,8 +134,12 @@ def __create_array_from_unit_cell_impl(
133
134
  # ---------- Sanity & auto-pitch detection ----------
134
135
  if x_number <= 0 or y_number <= 0:
135
136
  raise ValueError("x_number and y_number must be positive integers")
137
+ if offset_x and not offset_y:
138
+ raise ValueError("If offset_x is provided, offset_y must be provided as well")
139
+ if offset_y and not offset_x:
140
+ raise ValueError("If offset_y is provided, offset_x must be provided as well")
136
141
 
137
- if offset_x is None or offset_y is None:
142
+ if not offset_x and not offset_y:
138
143
  edb.logger.info("Auto-detecting outline extents")
139
144
  outline_prims = [p for p in edb.modeler.primitives if p.layer_name.lower() == "outline"]
140
145
  if not outline_prims:
@@ -143,6 +148,8 @@ def __create_array_from_unit_cell_impl(
143
148
  if not adapter.is_supported_outline(outline):
144
149
  raise RuntimeError("Outline primitive is not a polygon/rectangle. Provide offset_x / offset_y.")
145
150
  offset_x, offset_y = adapter.pitch_from_outline(outline)
151
+ offset_x = edb.value(offset_x)
152
+ offset_y = edb.value(offset_y)
146
153
 
147
154
  # ---------- Collect everything we have to replicate ----------
148
155
  primitives = [p for p in edb.modeler.primitives if adapter.is_primitive_to_copy(p)]
@@ -263,6 +270,9 @@ class _GrpcAdapter(_BaseAdapter):
263
270
  width=path.width,
264
271
  layer_name=path.layer.name,
265
272
  net_name=path.net.name,
273
+ corner_style=path.corner_style,
274
+ start_cap_style=path.end_cap1,
275
+ end_cap_style=path.end_cap2,
266
276
  )
267
277
 
268
278
  def duplicate_standalone_via(self, via, dx, dy, i, j):
@@ -357,11 +367,15 @@ class _DotNetAdapter(_BaseAdapter):
357
367
  moved_path = path._edb_object.GetCenterLine()
358
368
  moved_path.Move(vector._edb_object)
359
369
  moved_path = [[pt.X.ToDouble(), pt.Y.ToDouble()] for pt in list(moved_path.Points)]
370
+ end_caps = path._edb_object.GetEndCapStyle()
371
+
360
372
  self.edb.modeler.create_trace(
361
373
  path_list=list(moved_path),
362
374
  width=path.width,
363
375
  layer_name=path.layer.name,
364
376
  net_name=path.net.name,
377
+ start_cap_style=str(end_caps[1]),
378
+ end_cap_style=str(end_caps[2]),
365
379
  )
366
380
 
367
381
  def duplicate_standalone_via(self, via, dx, dy, i, j):
@@ -72,23 +72,13 @@ def unique_string_list(element_list, only_string=True): # pragma: no cover
72
72
  -------
73
73
 
74
74
  """
75
- if element_list:
76
- if isinstance(element_list, list):
77
- element_list = set(element_list)
78
- elif isinstance(element_list, str):
79
- element_list = [element_list]
80
- else:
81
- error_message = "Invalid list data"
82
- try:
83
- error_message += " {}".format(element_list)
84
- except:
85
- pass
86
- raise Exception(error_message)
75
+ if isinstance(element_list, str):
76
+ element_list = [element_list]
87
77
 
88
- if only_string and any(not isinstance(x, str) for x in element_list):
89
- raise TypeError("Invalid list entries, some elements are not of type string.")
78
+ if only_string and any(not isinstance(x, str) for x in element_list):
79
+ raise TypeError("Invalid list entries, some elements are not of type string.")
90
80
 
91
- return element_list
81
+ return list(set(element_list))
92
82
 
93
83
 
94
84
  def string_list(element_list): # pragma: no cover
@@ -142,28 +132,28 @@ def from_rkm(code): # pragma: no cover
142
132
 
143
133
  Examples
144
134
  --------
145
- >>> from_rkm('R47')
135
+ >>> from_rkm("R47")
146
136
  '0.47'
147
137
 
148
- >>> from_rkm('4R7')
138
+ >>> from_rkm("4R7")
149
139
  '4.7'
150
140
 
151
- >>> from_rkm('470R')
141
+ >>> from_rkm("470R")
152
142
  '470'
153
143
 
154
- >>> from_rkm('4K7')
144
+ >>> from_rkm("4K7")
155
145
  '4.7k'
156
146
 
157
- >>> from_rkm('47K')
147
+ >>> from_rkm("47K")
158
148
  '47k'
159
149
 
160
- >>> from_rkm('47K3')
150
+ >>> from_rkm("47K3")
161
151
  '47.3k'
162
152
 
163
- >>> from_rkm('470K')
153
+ >>> from_rkm("470K")
164
154
  '470k'
165
155
 
166
- >>> from_rkm('4M7')
156
+ >>> from_rkm("4M7")
167
157
  '4.7M'
168
158
 
169
159
  """
@@ -32,18 +32,15 @@ if TYPE_CHECKING:
32
32
 
33
33
 
34
34
  @overload
35
- def Edb(*, grpc: Literal[True], **kwargs) -> "EdbGrpc":
36
- ...
35
+ def Edb(*, grpc: Literal[True], **kwargs) -> "EdbGrpc": ...
37
36
 
38
37
 
39
38
  @overload
40
- def Edb(*, grpc: Literal[False] = False, **kwargs) -> "EdbDotnet":
41
- ...
39
+ def Edb(*, grpc: Literal[False] = False, **kwargs) -> "EdbDotnet": ...
42
40
 
43
41
 
44
42
  @overload
45
- def Edb(*, grpc: bool, **kwargs) -> Union["EdbGrpc", "EdbDotnet"]:
46
- ...
43
+ def Edb(*, grpc: bool, **kwargs) -> Union["EdbGrpc", "EdbDotnet"]: ...
47
44
 
48
45
 
49
46
  # lazy imports
@@ -167,17 +164,10 @@ def Edb(
167
164
  4. Simulation Setup
168
165
 
169
166
  # Create SIwave SYZ setup
170
- >>> syz_setup = edb.create_siwave_syz_setup(
171
- >>> name="GHz_Setup",
172
- >>> start_freq="1GHz",
173
- >>> stop_freq="10GHz"
174
- >>> )
167
+ >>> syz_setup = edb.create_siwave_syz_setup(name="GHz_Setup", start_freq="1GHz", stop_freq="10GHz")
175
168
 
176
169
  # Create SIwave DC setup
177
- >>> dc_setup = edb.create_siwave_dc_setup(
178
- >>> name="DC_Analysis",
179
- >>> use_dc_point=True
180
- >>> )
170
+ >>> dc_setup = edb.create_siwave_dc_setup(name="DC_Analysis", use_dc_point=True)
181
171
 
182
172
  # Solve with SIwave
183
173
  >>> edb.solve_siwave()
@@ -208,17 +198,10 @@ def Edb(
208
198
  7. Port Creation
209
199
 
210
200
  # Create wave port between two pins
211
- >>> wave_port = edb.source_excitation.create_port(
212
- >>> positive_terminal=pin1,
213
- >>> negative_terminal=pin2,
214
- >>> port_type="Wave"
215
- >>> )
201
+ >>> wave_port = edb.source_excitation.create_port(positive_terminal=pin1, negative_terminal=pin2, port_type="Wave")
216
202
 
217
203
  # Create lumped port
218
- >>> lumped_port = edb.source_excitation.create_port(
219
- >>> positive_terminal=via_terminal,
220
- >>> port_type="Lumped"
221
- >>> )
204
+ >>> lumped_port = edb.source_excitation.create_port(positive_terminal=via_terminal, port_type="Lumped")
222
205
 
223
206
  8. Component Management
224
207
 
@@ -231,12 +214,7 @@ def Edb(
231
214
  9. Parametrization
232
215
 
233
216
  # Auto-parametrize design elements
234
- >>> params = edb.auto_parametrize_design(
235
- >>> traces=True,
236
- >>> pads=True,
237
- >>> antipads=True,
238
- >>> use_relative_variables=True
239
- >>> )
217
+ >>> params = edb.auto_parametrize_design(traces=True, pads=True, antipads=True, use_relative_variables=True)
240
218
  >>> print("Created parameters:", params)
241
219
 
242
220
  10. Design Statistics
@@ -255,11 +233,7 @@ def Edb(
255
233
  12. Differential Pairs
256
234
 
257
235
  # Create differential pair
258
- >>> edb.differential_pairs.create(
259
- >>> positive_net="USB_P",
260
- >>> negative_net="USB_N",
261
- >>> name="USB_DP"
262
- >>> )
236
+ >>> edb.differential_pairs.create(positive_net="USB_P", negative_net="USB_N", name="USB_DP")
263
237
 
264
238
  13. Workflow Automation
265
239