pyedb 0.38.0__py3-none-any.whl → 0.39.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 (205) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/common/nets.py +53 -139
  3. pyedb/configuration/cfg_components.py +1 -1
  4. pyedb/configuration/cfg_general.py +4 -2
  5. pyedb/configuration/cfg_modeler.py +1 -1
  6. pyedb/configuration/cfg_package_definition.py +1 -1
  7. pyedb/configuration/cfg_padstacks.py +1 -1
  8. pyedb/configuration/cfg_ports_sources.py +56 -23
  9. pyedb/configuration/configuration.py +18 -1
  10. pyedb/dotnet/{application → database}/Variables.py +21 -21
  11. pyedb/dotnet/{edb_core → database}/cell/connectable.py +5 -5
  12. pyedb/dotnet/{edb_core → database}/cell/hierarchy/component.py +11 -11
  13. pyedb/dotnet/{edb_core → database}/cell/hierarchy/hierarchy_obj.py +1 -1
  14. pyedb/dotnet/{edb_core → database}/cell/hierarchy/model.py +1 -1
  15. pyedb/dotnet/{edb_core → database}/cell/layout.py +17 -17
  16. pyedb/dotnet/{edb_core → database}/cell/layout_obj.py +3 -3
  17. pyedb/dotnet/{edb_core → database}/cell/primitive/bondwire.py +1 -1
  18. pyedb/dotnet/{edb_core → database}/cell/primitive/path.py +4 -4
  19. pyedb/dotnet/{edb_core → database}/cell/primitive/primitive.py +14 -14
  20. pyedb/dotnet/{edb_core → database}/cell/terminal/bundle_terminal.py +2 -2
  21. pyedb/dotnet/{edb_core → database}/cell/terminal/edge_terminal.py +4 -4
  22. pyedb/dotnet/{edb_core → database}/cell/terminal/padstack_instance_terminal.py +2 -2
  23. pyedb/dotnet/{edb_core → database}/cell/terminal/pingroup_terminal.py +2 -2
  24. pyedb/dotnet/{edb_core → database}/cell/terminal/point_terminal.py +2 -2
  25. pyedb/dotnet/{edb_core → database}/cell/terminal/terminal.py +11 -11
  26. pyedb/dotnet/{edb_core → database}/cell/voltage_regulator.py +2 -2
  27. pyedb/dotnet/{edb_core → database}/components.py +101 -124
  28. pyedb/dotnet/{edb_core → database}/definition/component_def.py +5 -5
  29. pyedb/dotnet/{edb_core → database}/definition/component_model.py +1 -1
  30. pyedb/dotnet/{edb_core → database}/definition/definition_obj.py +1 -1
  31. pyedb/dotnet/{edb_core → database}/definition/definitions.py +2 -2
  32. pyedb/dotnet/{edb_core → database}/definition/package_def.py +4 -4
  33. pyedb/dotnet/{edb_core → database}/dotnet/database.py +8 -8
  34. pyedb/dotnet/{edb_core → database}/dotnet/primitive.py +9 -9
  35. pyedb/dotnet/{edb_core → database}/edb_data/control_file.py +12 -12
  36. pyedb/dotnet/{edb_core → database}/edb_data/hfss_extent_info.py +7 -7
  37. pyedb/dotnet/{edb_core → database}/edb_data/nets_data.py +10 -13
  38. pyedb/dotnet/{edb_core → database}/edb_data/padstacks_data.py +16 -16
  39. pyedb/dotnet/{edb_core → database}/edb_data/ports.py +4 -4
  40. pyedb/dotnet/{edb_core → database}/edb_data/primitives_data.py +5 -5
  41. pyedb/dotnet/{edb_core → database}/edb_data/raptor_x_simulation_setup_data.py +4 -4
  42. pyedb/dotnet/{edb_core → database}/edb_data/simulation_configuration.py +10 -10
  43. pyedb/dotnet/{edb_core → database}/edb_data/sources.py +4 -4
  44. pyedb/dotnet/{edb_core → database}/edb_data/variables.py +1 -1
  45. pyedb/dotnet/{edb_core → database}/geometry/polygon_data.py +4 -4
  46. pyedb/dotnet/{edb_core → database}/hfss.py +8 -8
  47. pyedb/dotnet/{edb_core → database}/layout_obj_instance.py +1 -1
  48. pyedb/dotnet/{edb_core → database}/layout_validation.py +2 -2
  49. pyedb/dotnet/{edb_core → database}/materials.py +23 -8
  50. pyedb/dotnet/{edb_core → database}/modeler.py +27 -27
  51. pyedb/dotnet/{edb_core → database}/net_class.py +8 -8
  52. pyedb/dotnet/{edb_core → database}/nets.py +12 -12
  53. pyedb/dotnet/{edb_core → database}/padstack.py +15 -15
  54. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/mesh_operation.py +1 -1
  55. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/settings.py +3 -3
  56. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sim_setup_info.py +2 -2
  57. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/simulation_settings.py +1 -1
  58. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/siw_dc_ir_settings.py +1 -1
  59. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sweep_data.py +1 -1
  60. pyedb/dotnet/{edb_core → database}/siwave.py +10 -10
  61. pyedb/dotnet/{edb_core → database}/stackup.py +12 -12
  62. pyedb/dotnet/{edb_core → database}/utilities/hfss_simulation_setup.py +15 -15
  63. pyedb/dotnet/{edb_core → database}/utilities/obj_base.py +1 -1
  64. pyedb/dotnet/{edb_core → database}/utilities/simulation_setup.py +3 -3
  65. pyedb/dotnet/{edb_core → database}/utilities/siwave_simulation_setup.py +6 -6
  66. pyedb/dotnet/edb.py +117 -112
  67. pyedb/generic/design_types.py +26 -19
  68. pyedb/generic/general_methods.py +1 -1
  69. pyedb/generic/plot.py +0 -2
  70. pyedb/grpc/database/__init__.py +1 -0
  71. pyedb/grpc/database/components.py +2354 -0
  72. pyedb/grpc/database/control_file.py +1277 -0
  73. pyedb/grpc/database/definition/component_def.py +218 -0
  74. pyedb/grpc/database/definition/component_model.py +39 -0
  75. pyedb/grpc/database/definition/component_pin.py +32 -0
  76. pyedb/grpc/database/definition/materials.py +1207 -0
  77. pyedb/grpc/database/definition/n_port_component_model.py +34 -0
  78. pyedb/grpc/database/definition/package_def.py +227 -0
  79. pyedb/grpc/database/definition/padstack_def.py +842 -0
  80. pyedb/grpc/database/definitions.py +70 -0
  81. pyedb/grpc/database/general.py +43 -0
  82. pyedb/grpc/database/geometry/__init__.py +0 -0
  83. pyedb/grpc/database/geometry/arc_data.py +93 -0
  84. pyedb/grpc/database/geometry/point_3d_data.py +79 -0
  85. pyedb/grpc/database/geometry/point_data.py +30 -0
  86. pyedb/grpc/database/geometry/polygon_data.py +133 -0
  87. pyedb/grpc/database/hfss.py +1279 -0
  88. pyedb/grpc/database/hierarchy/__init__.py +0 -0
  89. pyedb/grpc/database/hierarchy/component.py +1301 -0
  90. pyedb/grpc/database/hierarchy/model.py +31 -0
  91. pyedb/grpc/database/hierarchy/netlist_model.py +30 -0
  92. pyedb/grpc/database/hierarchy/pin_pair_model.py +128 -0
  93. pyedb/grpc/database/hierarchy/pingroup.py +245 -0
  94. pyedb/grpc/database/hierarchy/s_parameter_model.py +33 -0
  95. pyedb/grpc/database/hierarchy/spice_model.py +48 -0
  96. pyedb/grpc/database/layers/__init__.py +0 -0
  97. pyedb/grpc/database/layers/layer.py +57 -0
  98. pyedb/grpc/database/layers/stackup_layer.py +410 -0
  99. pyedb/grpc/database/layout/__init__.py +0 -0
  100. pyedb/grpc/database/layout/cell.py +30 -0
  101. pyedb/grpc/database/layout/layout.py +196 -0
  102. pyedb/grpc/database/layout/voltage_regulator.py +149 -0
  103. pyedb/grpc/database/layout_validation.py +319 -0
  104. pyedb/grpc/database/modeler.py +1468 -0
  105. pyedb/grpc/database/net/__init__.py +0 -0
  106. pyedb/grpc/database/net/differential_pair.py +138 -0
  107. pyedb/grpc/database/net/extended_net.py +340 -0
  108. pyedb/grpc/database/net/net.py +198 -0
  109. pyedb/grpc/database/net/net_class.py +93 -0
  110. pyedb/grpc/database/nets.py +633 -0
  111. pyedb/grpc/database/padstacks.py +1500 -0
  112. pyedb/grpc/database/ports/__init__.py +0 -0
  113. pyedb/grpc/database/ports/ports.py +396 -0
  114. pyedb/grpc/database/primitive/__init__.py +3 -0
  115. pyedb/grpc/database/primitive/bondwire.py +181 -0
  116. pyedb/grpc/database/primitive/circle.py +75 -0
  117. pyedb/grpc/database/primitive/padstack_instance.py +1116 -0
  118. pyedb/grpc/database/primitive/path.py +346 -0
  119. pyedb/grpc/database/primitive/polygon.py +276 -0
  120. pyedb/grpc/database/primitive/primitive.py +739 -0
  121. pyedb/grpc/database/primitive/rectangle.py +146 -0
  122. pyedb/grpc/database/simulation_setup/__init__.py +0 -0
  123. pyedb/grpc/database/simulation_setup/adaptive_frequency.py +33 -0
  124. pyedb/grpc/database/simulation_setup/hfss_advanced_meshing_settings.py +32 -0
  125. pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +59 -0
  126. pyedb/grpc/database/simulation_setup/hfss_dcr_settings.py +35 -0
  127. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +61 -0
  128. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +78 -0
  129. pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +118 -0
  130. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +355 -0
  131. pyedb/grpc/database/simulation_setup/hfss_solver_settings.py +34 -0
  132. pyedb/grpc/database/simulation_setup/mesh_operation.py +34 -0
  133. pyedb/grpc/database/simulation_setup/raptor_x_advanced_settings.py +34 -0
  134. pyedb/grpc/database/simulation_setup/raptor_x_general_settings.py +33 -0
  135. pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +64 -0
  136. pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +125 -0
  137. pyedb/grpc/database/simulation_setup/siwave_dcir_simulation_setup.py +34 -0
  138. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +119 -0
  139. pyedb/grpc/database/simulation_setup/sweep_data.py +32 -0
  140. pyedb/grpc/database/siwave.py +1023 -0
  141. pyedb/grpc/database/source_excitations.py +2572 -0
  142. pyedb/grpc/database/stackup.py +2574 -0
  143. pyedb/grpc/database/terminal/__init__.py +0 -0
  144. pyedb/grpc/database/terminal/bundle_terminal.py +218 -0
  145. pyedb/grpc/database/terminal/edge_terminal.py +51 -0
  146. pyedb/grpc/database/terminal/padstack_instance_terminal.py +171 -0
  147. pyedb/grpc/database/terminal/pingroup_terminal.py +162 -0
  148. pyedb/grpc/database/terminal/point_terminal.py +99 -0
  149. pyedb/grpc/database/terminal/terminal.py +470 -0
  150. pyedb/grpc/database/utility/__init__.py +3 -0
  151. pyedb/grpc/database/utility/constants.py +25 -0
  152. pyedb/grpc/database/utility/heat_sink.py +124 -0
  153. pyedb/grpc/database/utility/hfss_extent_info.py +448 -0
  154. pyedb/grpc/database/utility/layout_statistics.py +277 -0
  155. pyedb/grpc/database/utility/rlc.py +80 -0
  156. pyedb/grpc/database/utility/simulation_configuration.py +3305 -0
  157. pyedb/grpc/database/utility/sources.py +388 -0
  158. pyedb/grpc/database/utility/sweep_data_distribution.py +83 -0
  159. pyedb/grpc/database/utility/xml_control_file.py +1277 -0
  160. pyedb/grpc/edb.py +4151 -0
  161. pyedb/grpc/edb_init.py +481 -0
  162. pyedb/grpc/rpc_session.py +177 -0
  163. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +3 -2
  164. pyedb/ipc2581/ecad/cad_data/feature.py +4 -3
  165. pyedb/ipc2581/ecad/cad_data/layer_feature.py +32 -20
  166. pyedb/ipc2581/ecad/cad_data/outline.py +3 -2
  167. pyedb/ipc2581/ecad/cad_data/package.py +4 -3
  168. pyedb/ipc2581/ecad/cad_data/path.py +82 -31
  169. pyedb/ipc2581/ecad/cad_data/polygon.py +122 -60
  170. pyedb/ipc2581/ecad/cad_data/profile.py +13 -12
  171. pyedb/ipc2581/ecad/cad_data/step.py +53 -21
  172. pyedb/ipc2581/ipc2581.py +47 -49
  173. pyedb/modeler/geometry_operators.py +1 -1
  174. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/METADATA +5 -2
  175. pyedb-0.39.0.dist-info/RECORD +288 -0
  176. pyedb-0.38.0.dist-info/RECORD +0 -195
  177. /pyedb/dotnet/{edb_core → database}/__init__.py +0 -0
  178. /pyedb/dotnet/{application → database/cell}/__init__.py +0 -0
  179. /pyedb/dotnet/{edb_core/cell → database/cell/hierarchy}/__init__.py +0 -0
  180. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/netlist_model.py +0 -0
  181. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/pin_pair_model.py +0 -0
  182. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/s_parameter_model.py +0 -0
  183. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/spice_model.py +0 -0
  184. /pyedb/dotnet/{edb_core → database}/cell/primitive/__init__.py +0 -0
  185. /pyedb/dotnet/{edb_core/cell/hierarchy → database/cell/terminal}/__init__.py +0 -0
  186. /pyedb/dotnet/{edb_core/cell/terminal → database/definition}/__init__.py +0 -0
  187. /pyedb/dotnet/{edb_core/definition → database/dotnet}/__init__.py +0 -0
  188. /pyedb/dotnet/{edb_core/dotnet → database/edb_data}/__init__.py +0 -0
  189. /pyedb/dotnet/{edb_core → database}/edb_data/design_options.py +0 -0
  190. /pyedb/dotnet/{edb_core → database}/edb_data/edbvalue.py +0 -0
  191. /pyedb/dotnet/{edb_core → database}/edb_data/layer_data.py +0 -0
  192. /pyedb/dotnet/{edb_core → database}/edb_data/utilities.py +0 -0
  193. /pyedb/dotnet/{edb_core → database}/general.py +0 -0
  194. /pyedb/dotnet/{edb_core/edb_data → database/geometry}/__init__.py +0 -0
  195. /pyedb/dotnet/{edb_core → database}/geometry/point_data.py +0 -0
  196. /pyedb/dotnet/{edb_core → database}/sim_setup_data/__init__.py +0 -0
  197. /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/__init__.py +0 -0
  198. /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/adaptive_frequency_data.py +0 -0
  199. /pyedb/dotnet/{edb_core/geometry → database/sim_setup_data/io}/__init__.py +0 -0
  200. /pyedb/dotnet/{edb_core → database}/sim_setup_data/io/siwave.py +0 -0
  201. /pyedb/dotnet/{edb_core → database}/utilities/__init__.py +0 -0
  202. /pyedb/dotnet/{edb_core → database}/utilities/heatsink.py +0 -0
  203. /pyedb/{dotnet/edb_core/sim_setup_data/io → grpc/database/definition}/__init__.py +0 -0
  204. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/LICENSE +0 -0
  205. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,1116 @@
1
+ # Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ import math
24
+ import re
25
+
26
+ from ansys.edb.core.database import ProductIdType as GrpcProductIdType
27
+ from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
28
+ from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
29
+ from ansys.edb.core.hierarchy.pin_group import PinGroup as GrpcPinGroup
30
+ from ansys.edb.core.primitive.primitive import PadstackInstance as GrpcPadstackInstance
31
+ from ansys.edb.core.terminal.terminals import PinGroupTerminal as GrpcPinGroupTerminal
32
+ from ansys.edb.core.utility.value import Value as GrpcValue
33
+
34
+ from pyedb.grpc.database.definition.padstack_def import PadstackDef
35
+ from pyedb.grpc.database.terminal.padstack_instance_terminal import (
36
+ PadstackInstanceTerminal,
37
+ )
38
+ from pyedb.modeler.geometry_operators import GeometryOperators
39
+
40
+
41
+ class PadstackInstance(GrpcPadstackInstance):
42
+ """Manages EDB functionalities for a padstack.
43
+
44
+ Parameters
45
+ ----------
46
+ :class:`PadstackInstance <pyedb.grpc.dataybase.primitive.PadstackInstance>`
47
+ PadstackInstance object.
48
+
49
+ Examples
50
+ --------
51
+ >>> from pyedb import Edb
52
+ >>> edb = Edb(myedb, edbversion="2021.2")
53
+ >>> edb_padstack_instance = edb.padstacks.instances[0]
54
+ """
55
+
56
+ def __init__(self, pedb, edb_instance):
57
+ super().__init__(edb_instance.msg)
58
+ self._edb_object = edb_instance
59
+ self._bounding_box = []
60
+ self._position = []
61
+ self._pdef = None
62
+ self._pedb = pedb
63
+ self._object_instance = None
64
+
65
+ @property
66
+ def definition(self):
67
+ """Padstack definition.
68
+
69
+ Returns
70
+ -------
71
+ :class:`PadstackDef`<pyedb.grpc.database.definition.padstack_def.PadstackDef>`
72
+ """
73
+ return PadstackDef(self._pedb, self.padstack_def)
74
+
75
+ @property
76
+ def padstack_definition(self):
77
+ """Padstack definition name.
78
+
79
+ Returns
80
+ -------
81
+ str
82
+ Padstack definition name.
83
+
84
+ """
85
+ return self.padstack_def.name
86
+
87
+ @property
88
+ def terminal(self):
89
+ """PadstackInstanceTerminal.
90
+
91
+ Returns
92
+ -------
93
+ :class:`PadstackInstanceTerminal <pyedb.grpc.database.terminal.padstack_instance_terminal.
94
+ PadstackInstanceTerminal>`
95
+ PadstackInstanceTerminal object.
96
+ """
97
+ from pyedb.grpc.database.terminal.padstack_instance_terminal import (
98
+ PadstackInstanceTerminal,
99
+ )
100
+
101
+ term = PadstackInstanceTerminal(self._pedb, self._edb_object)
102
+ return term if not term.is_null else None
103
+
104
+ def create_terminal(self, name=None):
105
+ """Create a padstack instance terminal.
106
+
107
+ Returns
108
+ -------
109
+ :class:`PadstackInstanceTerminal <pyedb.grpc.database.terminal.padstack_instance_terminal.
110
+ PadstackInstanceTerminal>`
111
+ PadstackInstanceTerminal object.
112
+
113
+ """
114
+ if not name:
115
+ name = self.name
116
+ term = PadstackInstanceTerminal.create(
117
+ layout=self.layout,
118
+ name=name,
119
+ padstack_instance=self,
120
+ layer=self.get_layer_range()[0],
121
+ net=self.net,
122
+ is_ref=False,
123
+ )
124
+ return PadstackInstanceTerminal(self._pedb, term)
125
+
126
+ def get_terminal(self, create_new_terminal=True):
127
+ """Returns padstack instance terminal.
128
+
129
+ Parameters
130
+ ----------
131
+ create_new_terminal : bool, optional
132
+ If terminal instance is not created,
133
+ and value is ``True``, a new PadstackInstanceTerminal is created.
134
+
135
+ Returns
136
+ -------
137
+ :class:`PadstackInstanceTerminal <pyedb.grpc.database.terminal.padstack_instance_terminal.
138
+ PadstackInstanceTerminal>`
139
+ PadstackInstanceTerminal object.
140
+
141
+ """
142
+ inst_term = self.get_padstack_instance_terminal()
143
+ if inst_term.is_null and create_new_terminal:
144
+ inst_term = self.create_terminal()
145
+ return PadstackInstanceTerminal(self._pedb, inst_term)
146
+
147
+ def create_coax_port(self, name=None, radial_extent_factor=0):
148
+ """Create a coax port.
149
+
150
+ Parameters
151
+ ----------
152
+ name : str, optional.
153
+ Port name, the default is ``None``, in which case a name is automatically assigned.
154
+ radial_extent_factor : int, float, optional
155
+ Radial extent of coaxial port.
156
+
157
+ Returns
158
+ -------
159
+ :class:`Terminal <pyedb.grpc.database.terminal.terminal.Terminal>`
160
+ Port terminal.
161
+ """
162
+ port = self.create_port(name)
163
+ port.radial_extent_factor = radial_extent_factor
164
+ return port
165
+
166
+ def create_port(self, name=None, reference=None, is_circuit_port=False):
167
+ """Create a port on the padstack instance.
168
+
169
+ Parameters
170
+ ----------
171
+ name : str, optional
172
+ Name of the port. The default is ``None``, in which case a name is automatically assigned.
173
+ reference : reference net or pingroup optional
174
+ Negative terminal of the port.
175
+ is_circuit_port : bool, optional
176
+ Whether it is a circuit port.
177
+
178
+ Returns
179
+ -------
180
+ :class:`Terminal <pyedb.grpc.database.terminal.terminal.Terminal>`
181
+ Port terminal.
182
+ """
183
+ if not reference:
184
+ return self.create_terminal(name)
185
+ else:
186
+ positive_terminal = self.create_terminal()
187
+ if positive_terminal.is_null:
188
+ self._pedb.logger(
189
+ f"Positive terminal on padsatck instance {self.name} is null. Make sure a terminal"
190
+ f"is not already defined."
191
+ )
192
+ negative_terminal = None
193
+ if isinstance(reference, list):
194
+ pg = GrpcPinGroup.create(self.layout, name=f"pingroup_{self.name}_ref", padstack_instances=reference)
195
+ negative_terminal = GrpcPinGroupTerminal.create(
196
+ layout=self.layout,
197
+ name=f"pingroup_term{self.name}_ref)",
198
+ pin_group=pg,
199
+ net=reference[0].net,
200
+ is_ref=True,
201
+ )
202
+ is_circuit_port = True
203
+ else:
204
+ if isinstance(reference, PadstackInstance):
205
+ negative_terminal = reference.create_terminal()
206
+ elif isinstance(reference, str):
207
+ if reference in self._pedb.padstacks.instances:
208
+ reference = self._pedb.padstacks.instances[reference]
209
+ else:
210
+ pin_groups = [pg for pg in self._pedb.active_layout.pin_groups if pg.name == reference]
211
+ if pin_groups:
212
+ reference = pin_groups[0]
213
+ else:
214
+ self._pedb.logger.error(f"No reference found for {reference}")
215
+ return False
216
+ negative_terminal = reference.create_terminal()
217
+ if negative_terminal:
218
+ positive_terminal.reference_terminal = negative_terminal
219
+ else:
220
+ self._pedb.logger.error("No reference terminal created")
221
+ return False
222
+ positive_terminal.is_circuit_port = is_circuit_port
223
+ negative_terminal.is_circuit_port = is_circuit_port
224
+ return positive_terminal
225
+
226
+ @property
227
+ def _em_properties(self):
228
+ """Get EM properties."""
229
+ from ansys.edb.core.database import ProductIdType
230
+
231
+ default = (
232
+ r"$begin 'EM properties'\n"
233
+ r"\tType('Mesh')\n"
234
+ r"\tDataId='EM properties1'\n"
235
+ r"\t$begin 'Properties'\n"
236
+ r"\t\tGeneral=''\n"
237
+ r"\t\tModeled='true'\n"
238
+ r"\t\tUnion='true'\n"
239
+ r"\t\t'Use Precedence'='false'\n"
240
+ r"\t\t'Precedence Value'='1'\n"
241
+ r"\t\tPlanarEM=''\n"
242
+ r"\t\tRefined='true'\n"
243
+ r"\t\tRefineFactor='1'\n"
244
+ r"\t\tNoEdgeMesh='false'\n"
245
+ r"\t\tHFSS=''\n"
246
+ r"\t\t'Solve Inside'='false'\n"
247
+ r"\t\tSIwave=''\n"
248
+ r"\t\t'DCIR Equipotential Region'='false'\n"
249
+ r"\t$end 'Properties'\n"
250
+ r"$end 'EM properties'\n"
251
+ )
252
+
253
+ p = self.get_product_property(ProductIdType.DESIGNER, 18)
254
+ if p:
255
+ return p
256
+ else:
257
+ return default
258
+
259
+ @_em_properties.setter
260
+ def _em_properties(self, em_prop):
261
+ """Set EM properties"""
262
+ pid = self._pedb.edb_api.ProductId.Designer
263
+ self.set_product_property(pid, 18, em_prop)
264
+
265
+ @property
266
+ def dcir_equipotential_region(self):
267
+ """Check whether dcir equipotential region is enabled.
268
+
269
+ Returns
270
+ -------
271
+ bool
272
+
273
+ """
274
+ pattern = r"'DCIR Equipotential Region'='([^']+)'"
275
+ em_pp = self._em_properties
276
+ result = re.search(pattern, em_pp).group(1)
277
+ if result == "true":
278
+ return True
279
+ else:
280
+ return False
281
+
282
+ @dcir_equipotential_region.setter
283
+ def dcir_equipotential_region(self, value):
284
+ """Set dcir equipotential region."""
285
+ pp = r"'DCIR Equipotential Region'='true'" if value else r"'DCIR Equipotential Region'='false'"
286
+ em_pp = self._em_properties
287
+ pattern = r"'DCIR Equipotential Region'='([^']+)'"
288
+ new_em_pp = re.sub(pattern, pp, em_pp)
289
+ self._em_properties = new_em_pp
290
+
291
+ @property
292
+ def object_instance(self):
293
+ """Layout object instance.
294
+
295
+ Returns
296
+ -------
297
+ :class:`LayoutObjInstance <ansys.edb.core.layout_instance.layout_obj_instance import.LayoutObjInstance>`
298
+
299
+ """
300
+ if not self._object_instance:
301
+ self._object_instance = self.layout.layout_instance.get_layout_obj_instance_in_context(self, None)
302
+ return self._object_instance
303
+
304
+ @property
305
+ def bounding_box(self):
306
+ """Padstack instance bounding box.
307
+ Because this method is slow, the bounding box is stored in a variable and reused.
308
+
309
+ Returns
310
+ -------
311
+ list of float
312
+ """
313
+ # TODO check to implement in grpc
314
+ if self._bounding_box:
315
+ return self._bounding_box
316
+ return self._bounding_box
317
+
318
+ def in_polygon(self, polygon_data, include_partial=True):
319
+ """Check if padstack Instance is in given polygon data.
320
+
321
+ Parameters
322
+ ----------
323
+ polygon_data : PolygonData Object
324
+ include_partial : bool, optional
325
+ Whether to include partial intersecting instances. The default is ``True``.
326
+ simple_check : bool, optional
327
+ Whether to perform a single check based on the padstack center or check the padstack bounding box.
328
+
329
+ Returns
330
+ -------
331
+ bool
332
+ ``True`` when successful, ``False`` when failed.
333
+ """
334
+ int_val = 1 if polygon_data.point_in_polygon(GrpcPointData(self.position)) else 0
335
+ if int_val == 0:
336
+ return False
337
+ else:
338
+ int_val = polygon_data.intersection_type(GrpcPolygonData(self.bounding_box))
339
+ # Intersection type:
340
+ # 0 = objects do not intersect
341
+ # 1 = this object fully inside other (no common contour points)
342
+ # 2 = other object fully inside this
343
+ # 3 = common contour points 4 = undefined intersection
344
+ if int_val == 0:
345
+ return False
346
+ elif include_partial:
347
+ return True
348
+ elif int_val < 3:
349
+ return True
350
+ else:
351
+ return False
352
+
353
+ @property
354
+ def start_layer(self):
355
+ """Starting layer.
356
+
357
+ Returns
358
+ -------
359
+ str
360
+ Name of the starting layer.
361
+ """
362
+ return self.get_layer_range()[0].name
363
+
364
+ @start_layer.setter
365
+ def start_layer(self, layer_name):
366
+ stop_layer = self._pedb.stackup.signal_layers[self.stop_layer]
367
+ start_layer = self._pedb.stackup.signal_layers[layer_name]
368
+ self.set_layer_range(start_layer, stop_layer)
369
+
370
+ @property
371
+ def stop_layer(self):
372
+ """Stopping layer.
373
+
374
+ Returns
375
+ -------
376
+ str
377
+ Name of the stopping layer.
378
+ """
379
+ return self.get_layer_range()[-1].name
380
+
381
+ @stop_layer.setter
382
+ def stop_layer(self, layer_name):
383
+ start_layer = self._pedb.stackup.signal_layers[self.start_layer]
384
+ stop_layer = self._pedb.stackup.signal_layers[layer_name]
385
+ self.set_layer_range(start_layer, stop_layer)
386
+
387
+ @property
388
+ def layer_range_names(self):
389
+ """List of all layers to which the padstack instance belongs.
390
+
391
+ Returns
392
+ -------
393
+ List[str]
394
+ List of layer names.
395
+
396
+ """
397
+ start_layer, stop_layer = self.get_layer_range()
398
+ started = False
399
+ layer_list = []
400
+ start_layer_name = start_layer.name
401
+ stop_layer_name = stop_layer.name
402
+ for layer_name in list(self._pedb.stackup.layers.keys()):
403
+ if started:
404
+ layer_list.append(layer_name)
405
+ if layer_name == stop_layer_name or layer_name == start_layer_name:
406
+ break
407
+ elif layer_name == start_layer_name:
408
+ started = True
409
+ layer_list.append(layer_name)
410
+ if layer_name == stop_layer_name:
411
+ break
412
+ elif layer_name == stop_layer_name:
413
+ started = True
414
+ layer_list.append(layer_name)
415
+ if layer_name == start_layer_name:
416
+ break
417
+ return layer_list
418
+
419
+ @property
420
+ def net_name(self):
421
+ """Net name.
422
+
423
+ Returns
424
+ -------
425
+ str
426
+ Name of the net.
427
+ """
428
+ if self.is_null:
429
+ return ""
430
+ elif self.net.is_null:
431
+ return ""
432
+ else:
433
+ return self.net.name
434
+
435
+ @net_name.setter
436
+ def net_name(self, val):
437
+ if not self.is_null and not self.net.is_null:
438
+ self.net = self._pedb.nets.nets[val]
439
+
440
+ @property
441
+ def layout_object_instance(self):
442
+ """Layout object instance.
443
+
444
+ Returns
445
+ -------
446
+ :class:`LayoutObjInstance <ansys.edb.core.layout_instance.layout_obj_instance.LayoutObjInstance>`
447
+
448
+ """
449
+ obj_inst = [
450
+ obj
451
+ for obj in self._pedb.layout_instance.query_layout_obj_instances(
452
+ spatial_filter=GrpcPointData(self.position)
453
+ )
454
+ if obj.layout_obj.id == self.id
455
+ ]
456
+ return obj_inst[0] if obj_inst else None
457
+
458
+ @property
459
+ def is_pin(self):
460
+ """Determines whether this padstack instance is a layout pin.
461
+
462
+ Returns
463
+ -------
464
+ bool
465
+ True if this padstack type is a layout pin, False otherwise.
466
+ """
467
+ return self.is_layout_pin
468
+
469
+ @is_pin.setter
470
+ def is_pin(self, value):
471
+ self.is_layout_pin = value
472
+
473
+ @property
474
+ def component(self):
475
+ """Component.
476
+
477
+ Returns
478
+ -------
479
+ :class:`Component <pyedb.grpc.database.hierarchy.component.Component>`
480
+
481
+ """
482
+ from pyedb.grpc.database.hierarchy.component import Component
483
+
484
+ comp = Component(self._pedb, super().component)
485
+ return comp if not comp.is_null else False
486
+
487
+ @property
488
+ def position(self):
489
+ """Padstack instance position.
490
+
491
+ Returns
492
+ -------
493
+ list
494
+ List of ``[x, y]`` coordinates for the padstack instance position.
495
+ """
496
+ position = self.get_position_and_rotation()
497
+ if self.component:
498
+ out2 = self.component.transform.transform_point(GrpcPointData(position[:2]))
499
+ self._position = [round(out2[0].value, 6), round(out2[1].value, 6)]
500
+ else:
501
+ self._position = [round(pt.value, 6) for pt in position[:2]]
502
+ return self._position
503
+
504
+ @position.setter
505
+ def position(self, value):
506
+ pos = []
507
+ for v in value:
508
+ if isinstance(v, (float, int, str)):
509
+ pos.append(GrpcValue(v, self._pedb.active_cell))
510
+ else:
511
+ pos.append(v)
512
+ point_data = GrpcPointData(pos[0], pos[1])
513
+ self.set_position_and_rotation(
514
+ x=point_data.x, y=point_data.y, rotation=GrpcValue(self.rotation, self._pedb.active_cell)
515
+ )
516
+
517
+ @property
518
+ def rotation(self):
519
+ """Padstack instance rotation.
520
+
521
+ Returns
522
+ -------
523
+ float
524
+ Rotatation value for the padstack instance.
525
+ """
526
+ return self.get_position_and_rotation()[-1].value
527
+
528
+ @property
529
+ def name(self):
530
+ """Padstack Instance Name.
531
+
532
+ Returns
533
+ -------
534
+ str
535
+ If it is a pin, the syntax will be like in AEDT ComponentName-PinName.
536
+
537
+ """
538
+ if not super().name:
539
+ return self.aedt_name
540
+ else:
541
+ return super().name
542
+
543
+ @name.setter
544
+ def name(self, value):
545
+ super(PadstackInstance, self.__class__).name.__set__(self, value)
546
+ self.set_product_property(GrpcProductIdType.DESIGNER, 11, value)
547
+
548
+ @property
549
+ def backdrill_type(self):
550
+ """Backdrill type.
551
+
552
+
553
+ Returns
554
+ -------
555
+ str
556
+ Backdrill type.
557
+
558
+ """
559
+ return self.get_backdrill_type()
560
+
561
+ @property
562
+ def backdrill_top(self):
563
+ if self.get_back_drill_type(False).value == 0:
564
+ return False
565
+ else:
566
+ try:
567
+ if self.get_back_drill_by_layer(from_bottom=False):
568
+ return True
569
+ except:
570
+ return False
571
+
572
+ @property
573
+ def backdrill_bottom(self):
574
+ """Check is backdrill is starting at bottom.
575
+
576
+
577
+ Returns
578
+ -------
579
+ bool
580
+
581
+ """
582
+ if self.get_back_drill_type(True).value == 0:
583
+ return False
584
+ else:
585
+ try:
586
+ if self.get_back_drill_by_layer(True):
587
+ return True
588
+ except:
589
+ return False
590
+
591
+ @property
592
+ def metal_volume(self):
593
+ """Metal volume of the via hole instance in cubic units (m3). Metal plating ratio is accounted.
594
+
595
+ Returns
596
+ -------
597
+ float
598
+ Metal volume of the via hole instance.
599
+
600
+ """
601
+ volume = 0
602
+ if not self.start_layer == self.stop_layer:
603
+ start_layer = self.start_layer
604
+ stop_layer = self.stop_layer
605
+ via_length = (
606
+ self._pedb.stackup.signal_layers[start_layer].upper_elevation
607
+ - self._pedb.stackup.signal_layers[stop_layer].lower_elevation
608
+ )
609
+ if self.get_backdrill_type == "layer_drill":
610
+ layer, _, _ = self.get_back_drill_by_layer()
611
+ start_layer = self._pedb.stackup.signal_layers[0]
612
+ stop_layer = self._pedb.stackup.signal_layers[layer.name]
613
+ via_length = (
614
+ self._pedb.stackup.signal_layers[start_layer].upper_elevation
615
+ - self._pedb.stackup.signal_layers[stop_layer].lower_elevation
616
+ )
617
+ elif self.get_backdrill_type == "depth_drill":
618
+ drill_depth, _ = self.get_back_drill_by_depth()
619
+ start_layer = self._pedb.stackup.signal_layers[0]
620
+ via_length = self._pedb.stackup.signal_layers[start_layer].upper_elevation - drill_depth
621
+ padstack_def = self._pedb.padstacks.definitions[self.padstack_def.name]
622
+ hole_diameter = padstack_def.hole_diameter
623
+ if hole_diameter:
624
+ hole_finished_size = padstack_def.hole_finished_size
625
+ volume = (math.pi * (hole_diameter / 2) ** 2 - math.pi * (hole_finished_size / 2) ** 2) * via_length
626
+ return volume
627
+
628
+ @property
629
+ def component_pin(self):
630
+ """Component pin.
631
+
632
+ Returns
633
+ -------
634
+ str
635
+ Component pin name.
636
+
637
+ """
638
+ return self.name
639
+
640
+ @property
641
+ def aedt_name(self):
642
+ """Retrieve the pin name that is shown in AEDT.
643
+
644
+ .. note::
645
+ To obtain the EDB core pin name, use `pin.name`.
646
+
647
+ Returns
648
+ -------
649
+ str
650
+ Name of the pin in AEDT.
651
+
652
+ Examples
653
+ --------
654
+
655
+ >>> from pyedb import Edb
656
+ >>> edbapp = Edb("myaedbfolder", "project name", "release version")
657
+ >>> edbapp.padstacks.instances[111].get_aedt_pin_name()
658
+
659
+ """
660
+
661
+ name = self.get_product_property(GrpcProductIdType.DESIGNER, 11)
662
+ return str(name).strip("'")
663
+
664
+ def get_backdrill_type(self, from_bottom=True):
665
+ """Return backdrill type
666
+ Parameters
667
+ ----------
668
+ from_bottom : bool, optional
669
+ default value is `True.`
670
+
671
+ Return
672
+ ------
673
+ str
674
+ Back drill type, `"layer_drill"`,`"depth_drill"`, `"no_drill"`.
675
+
676
+ """
677
+ return super().get_back_drill_type(from_bottom).name.lower()
678
+
679
+ def get_back_drill_by_layer(self, from_bottom=True):
680
+ """Get backdrill by layer.
681
+
682
+ Parameters
683
+ ----------
684
+ from_bottom : bool, optional.
685
+ Default value is `True`.
686
+
687
+ Return
688
+ ------
689
+ tuple (layer, offset, diameter) (str, [float, float], float).
690
+
691
+ """
692
+ back_drill = super().get_back_drill_by_layer(from_bottom)
693
+ layer = back_drill[0].name
694
+ offset = round(back_drill[1].value, 9)
695
+ diameter = round(back_drill[2].value, 9)
696
+ return layer, offset, diameter
697
+
698
+ def get_back_drill_by_depth(self, from_bottom=True):
699
+ """Get back drill by depth parameters
700
+ Parameters
701
+ ----------
702
+ from_bottom : bool, optional
703
+ Default value is `True`.
704
+
705
+ Return
706
+ ------
707
+ tuple (drill_depth, drill_diameter) (float, float)
708
+ """
709
+ back_drill = super().get_back_drill_by_depth(from_bottom)
710
+ drill_depth = back_drill[0].value
711
+ drill_diameter = back_drill[1].value
712
+ return drill_depth, drill_diameter
713
+
714
+ def set_back_drill_by_depth(self, drill_depth, diameter, from_bottom=True):
715
+ """Set back drill by depth.
716
+
717
+ Parameters
718
+ ----------
719
+ drill_depth : str, float
720
+ drill depth value
721
+ diameter : str, float
722
+ drill diameter
723
+ from_bottom : bool, optional
724
+ Default value is `True`.
725
+ """
726
+ super().set_back_drill_by_depth(
727
+ drill_depth=GrpcValue(drill_depth), diameter=GrpcValue(diameter), from_bottom=from_bottom
728
+ )
729
+
730
+ def set_back_drill_by_layer(self, drill_to_layer, offset, diameter, from_bottom=True):
731
+ """Set back drill layer.
732
+
733
+ Parameters
734
+ ----------
735
+ drill_to_layer : str, Layer
736
+ Layer to drill to.
737
+ offset : str, float
738
+ Offset value
739
+ diameter : str, float
740
+ Drill diameter
741
+ from_bottom : bool, optional
742
+ Default value is `True`
743
+ """
744
+ if isinstance(drill_to_layer, str):
745
+ drill_to_layer = self._pedb.stackup.layers[drill_to_layer]
746
+ super().set_back_drill_by_layer(
747
+ drill_to_layer=drill_to_layer,
748
+ offset=GrpcValue(offset),
749
+ diameter=GrpcValue(diameter),
750
+ from_bottom=from_bottom,
751
+ )
752
+
753
+ def parametrize_position(self, prefix=None):
754
+ """Parametrize the instance position.
755
+
756
+ Parameters
757
+ ----------
758
+ prefix : str, optional
759
+ Prefix for the variable name. Default is ``None``.
760
+ Example `"MyVariableName"` will create 2 Project variables $MyVariableNamesX and $MyVariableNamesY.
761
+
762
+ Returns
763
+ -------
764
+ List
765
+ List of variables created.
766
+ """
767
+ p = self.position
768
+ if not prefix:
769
+ var_name = "${}_pos".format(self.name)
770
+ else:
771
+ var_name = "${}".format(prefix)
772
+ self._pedb.add_project_variable(var_name + "X", p[0])
773
+ self._pedb.add_project_variable(var_name + "Y", p[1])
774
+ self.position = [var_name + "X", var_name + "Y"]
775
+ return [var_name + "X", var_name + "Y"]
776
+
777
+ def in_voids(self, net_name=None, layer_name=None):
778
+ """Check if this padstack instance is in any void.
779
+
780
+ Parameters
781
+ ----------
782
+ net_name : str
783
+ Net name of the voids to be checked. Default is ``None``.
784
+ layer_name : str
785
+ Layer name of the voids to be checked. Default is ``None``.
786
+
787
+ Returns
788
+ -------
789
+ List[:class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`]
790
+ List of the voids that include this padstack instance.
791
+ """
792
+ x_pos = GrpcValue(self.position[0])
793
+ y_pos = GrpcValue(self.position[1])
794
+ point_data = GrpcPointData([x_pos, y_pos])
795
+
796
+ voids = []
797
+ for prim in self._pedb.modeler.get_primitives(net_name, layer_name, is_void=True):
798
+ if prim.polygon_data.point_in_polygon(point_data):
799
+ voids.append(prim)
800
+ return voids
801
+
802
+ @property
803
+ def pingroups(self):
804
+ """Pin groups that the pin belongs to.
805
+
806
+ Returns
807
+ -------
808
+ List[:class:`PinGroup <ansys.edb.core.hierarchy.pin_group>`]
809
+ List of pin groups that the pin belongs to.
810
+ """
811
+ return self.pin_groups
812
+
813
+ @property
814
+ def placement_layer(self):
815
+ """Placement layer name.
816
+
817
+ Returns
818
+ -------
819
+ str
820
+ Name of the placement layer.
821
+ """
822
+ return self.component.placement_layer
823
+
824
+ @property
825
+ def layer(self):
826
+ """Placement layer object.
827
+
828
+ Returns
829
+ -------
830
+ :class:`pyedb.grpc.database.layers.stackup_layer.StackupLayer`
831
+ Placement layer.
832
+ """
833
+ return self.component.layer
834
+
835
+ @property
836
+ def lower_elevation(self):
837
+ """Lower elevation of the placement layer.
838
+
839
+ Returns
840
+ -------
841
+ float
842
+ Lower elavation of the placement layer.
843
+ """
844
+ return self._pedb.stackup.layers[self.component.placement_layer].lower_elevation
845
+
846
+ @property
847
+ def upper_elevation(self):
848
+ """Upper elevation of the placement layer.
849
+
850
+ Returns
851
+ -------
852
+ float
853
+ Upper elevation of the placement layer.
854
+ """
855
+ return self._pedb.stackup.layers[self.component.placement_layer].upper_elevation
856
+
857
+ @property
858
+ def top_bottom_association(self):
859
+ """Top/bottom association of the placement layer.
860
+
861
+ Returns
862
+ -------
863
+ int
864
+ Top/bottom association of the placement layer.
865
+
866
+ * 0 Top associated.
867
+ * 1 No association.
868
+ * 2 Bottom associated.
869
+ * 4 Number of top/bottom association type.
870
+ * -1 Undefined.
871
+ """
872
+ return self._pedb.stackup.layers[self.component.placement_layer].top_bottom_association.value
873
+
874
+ def create_rectangle_in_pad(self, layer_name, return_points=False, partition_max_order=16):
875
+ """Create a rectangle inscribed inside a padstack instance pad.
876
+
877
+ The rectangle is fully inscribed in the pad and has the maximum area.
878
+ It is necessary to specify the layer on which the rectangle will be created.
879
+
880
+ Parameters
881
+ ----------
882
+ layer_name : str
883
+ Name of the layer on which to create the polygon.
884
+ return_points : bool, optional
885
+ If `True` does not create the rectangle and just returns a list containing the rectangle vertices.
886
+ Default is `False`.
887
+ partition_max_order : float, optional
888
+ Order of the lattice partition used to find the quasi-lattice polygon that approximates ``polygon``.
889
+ Default is ``16``.
890
+
891
+ Returns
892
+ -------
893
+ bool, List, :class:`Primitive <pyedb.grpc.database.primitive.primitive.Primitive>`
894
+ Polygon when successful, ``False`` when failed, list of list if `return_points=True`.
895
+
896
+ Examples
897
+ --------
898
+ >>> from pyedb import Edb
899
+ >>> edbapp = Edb("myaedbfolder", edbversion="2021.2")
900
+ >>> edb_layout = edbapp.modeler
901
+ >>> list_of_padstack_instances = list(edbapp.padstacks.instances.values())
902
+ >>> padstack_inst = list_of_padstack_instances[0]
903
+ >>> padstack_inst.create_rectangle_in_pad("TOP")
904
+ """
905
+ # TODO check if still used anf fix if yes.
906
+ padstack_center = self.position
907
+ rotation = self.rotation # in radians
908
+ # padstack = self._pedb.padstacks.definitions[self.padstack_def.name]
909
+ try:
910
+ padstack_pad = PadstackDef(self._pedb, self.padstack_def).pad_by_layer[layer_name]
911
+ except KeyError: # pragma: no cover
912
+ try:
913
+ padstack_pad = PadstackDef(self._pedb, self.padstack_def).pad_by_layer[
914
+ PadstackDef(self._pedb, self.padstack_def).start_layer
915
+ ]
916
+ except KeyError: # pragma: no cover
917
+ return False
918
+
919
+ try:
920
+ pad_shape = padstack_pad.geometry_type
921
+ params = padstack_pad.parameters_values
922
+ polygon_data = padstack_pad.polygon_data
923
+ except:
924
+ self._pedb.logger.warning(f"No pad defined on padstack definition {self.padstack_def.name}")
925
+ return False
926
+
927
+ def _rotate(p):
928
+ x = p[0] * math.cos(rotation) - p[1] * math.sin(rotation)
929
+ y = p[0] * math.sin(rotation) + p[1] * math.cos(rotation)
930
+ return [x, y]
931
+
932
+ def _translate(p):
933
+ x = p[0] + padstack_center[0]
934
+ y = p[1] + padstack_center[1]
935
+ return [x, y]
936
+
937
+ rect = None
938
+
939
+ if pad_shape == 1:
940
+ # Circle
941
+ diameter = params[0]
942
+ r = diameter * 0.5
943
+ p1 = [r, 0.0]
944
+ p2 = [0.0, r]
945
+ p3 = [-r, 0.0]
946
+ p4 = [0.0, -r]
947
+ rect = [_translate(p1), _translate(p2), _translate(p3), _translate(p4)]
948
+ elif pad_shape == 2:
949
+ # Square
950
+ square_size = params[0]
951
+ s2 = square_size * 0.5
952
+ p1 = [s2, s2]
953
+ p2 = [-s2, s2]
954
+ p3 = [-s2, -s2]
955
+ p4 = [s2, -s2]
956
+ rect = [
957
+ _translate(_rotate(p1)),
958
+ _translate(_rotate(p2)),
959
+ _translate(_rotate(p3)),
960
+ _translate(_rotate(p4)),
961
+ ]
962
+ elif pad_shape == 3:
963
+ # Rectangle
964
+ x_size = float(params[0])
965
+ y_size = float(params[1])
966
+ sx2 = x_size * 0.5
967
+ sy2 = y_size * 0.5
968
+ p1 = [sx2, sy2]
969
+ p2 = [-sx2, sy2]
970
+ p3 = [-sx2, -sy2]
971
+ p4 = [sx2, -sy2]
972
+ rect = [
973
+ _translate(_rotate(p1)),
974
+ _translate(_rotate(p2)),
975
+ _translate(_rotate(p3)),
976
+ _translate(_rotate(p4)),
977
+ ]
978
+ elif pad_shape == 4:
979
+ # Oval
980
+ x_size = params[0]
981
+ y_size = params[1]
982
+ corner_radius = float(params[2])
983
+ if corner_radius >= min(x_size, y_size):
984
+ r = min(x_size, y_size)
985
+ else:
986
+ r = corner_radius
987
+ sx = x_size * 0.5 - r
988
+ sy = y_size * 0.5 - r
989
+ k = r / math.sqrt(2)
990
+ p1 = [sx + k, sy + k]
991
+ p2 = [-sx - k, sy + k]
992
+ p3 = [-sx - k, -sy - k]
993
+ p4 = [sx + k, -sy - k]
994
+ rect = [
995
+ _translate(_rotate(p1)),
996
+ _translate(_rotate(p2)),
997
+ _translate(_rotate(p3)),
998
+ _translate(_rotate(p4)),
999
+ ]
1000
+ elif pad_shape == 5:
1001
+ # Bullet
1002
+ x_size = params[0]
1003
+ y_size = params[1]
1004
+ corner_radius = params[2]
1005
+ if corner_radius >= min(x_size, y_size):
1006
+ r = min(x_size, y_size)
1007
+ else:
1008
+ r = corner_radius
1009
+ sx = x_size * 0.5 - r
1010
+ sy = y_size * 0.5 - r
1011
+ k = r / math.sqrt(2)
1012
+ p1 = [sx + k, sy + k]
1013
+ p2 = [-x_size * 0.5, sy + k]
1014
+ p3 = [-x_size * 0.5, -sy - k]
1015
+ p4 = [sx + k, -sy - k]
1016
+ rect = [
1017
+ _translate(_rotate(p1)),
1018
+ _translate(_rotate(p2)),
1019
+ _translate(_rotate(p3)),
1020
+ _translate(_rotate(p4)),
1021
+ ]
1022
+ elif pad_shape == 6:
1023
+ # N-Sided Polygon
1024
+ size = params[0]
1025
+ num_sides = params[1]
1026
+ ext_radius = size * 0.5
1027
+ apothem = ext_radius * math.cos(math.pi / num_sides)
1028
+ p1 = [apothem, 0.0]
1029
+ p2 = [0.0, apothem]
1030
+ p3 = [-apothem, 0.0]
1031
+ p4 = [0.0, -apothem]
1032
+ rect = [
1033
+ _translate(_rotate(p1)),
1034
+ _translate(_rotate(p2)),
1035
+ _translate(_rotate(p3)),
1036
+ _translate(_rotate(p4)),
1037
+ ]
1038
+ elif pad_shape == 7 and polygon_data is not None:
1039
+ # Polygon
1040
+ points = []
1041
+ i = 0
1042
+ while i < len(polygon_data.points):
1043
+ point = polygon_data.points[i]
1044
+ i += 1
1045
+ if point.is_arc:
1046
+ continue
1047
+ else:
1048
+ points.append([point.x.value, point.y.value])
1049
+ xpoly, ypoly = zip(*points)
1050
+ polygon = [list(xpoly), list(ypoly)]
1051
+ rectangles = GeometryOperators.find_largest_rectangle_inside_polygon(
1052
+ polygon, partition_max_order=partition_max_order
1053
+ )
1054
+ rect = rectangles[0]
1055
+ for i in range(4):
1056
+ rect[i] = _translate(_rotate(rect[i]))
1057
+
1058
+ # if rect is None or len(rect) != 4:
1059
+ # return False
1060
+ rect = [GrpcPointData(pt) for pt in rect]
1061
+ path = GrpcPolygonData(rect)
1062
+ new_rect = []
1063
+ for point in path.points:
1064
+ if self.component:
1065
+ p_transf = self.component.transform.transform_point(point)
1066
+ new_rect.append([p_transf.x.value, p_transf.y.value])
1067
+ if return_points:
1068
+ return new_rect
1069
+ else:
1070
+ created_polygon = self._pedb.modeler.create_polygon(path, layer_name)
1071
+ return created_polygon
1072
+
1073
+ def get_reference_pins(self, reference_net="GND", search_radius=5e-3, max_limit=0, component_only=True):
1074
+ """Search for reference pins using given criteria.
1075
+
1076
+ Parameters
1077
+ ----------
1078
+ reference_net : str, optional
1079
+ Reference net. The default is ``"GND"``.
1080
+ search_radius : float, optional
1081
+ Search radius for finding padstack instances. The default is ``5e-3``.
1082
+ max_limit : int, optional
1083
+ Maximum limit for the padstack instances found. The default is ``0``, in which
1084
+ case no limit is applied. The maximum limit value occurs on the nearest
1085
+ reference pins from the positive one that is found.
1086
+ component_only : bool, optional
1087
+ Whether to limit the search to component padstack instances only. The
1088
+ default is ``True``. When ``False``, the search is extended to the entire layout.
1089
+
1090
+ Returns
1091
+ -------
1092
+ List[:class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`]
1093
+
1094
+ Examples
1095
+ --------
1096
+ >>> edbapp = Edb("target_path")
1097
+ >>> pin = edbapp.components.instances["J5"].pins["19"]
1098
+ >>> reference_pins = pin.get_reference_pins(reference_net="GND", search_radius=5e-3, max_limit=0,
1099
+ >>> component_only=True)
1100
+ """
1101
+ return self._pedb.padstacks.get_reference_pins(
1102
+ positive_pin=self,
1103
+ reference_net=reference_net,
1104
+ search_radius=search_radius,
1105
+ max_limit=max_limit,
1106
+ component_only=component_only,
1107
+ )
1108
+
1109
+ def get_connected_objects(self):
1110
+ """Get connected objects.
1111
+
1112
+ Returns
1113
+ -------
1114
+ List[:class:`LayoutObjInstance <ansys.edb.core.layout_instance.layout_obj_instance.LayoutObjInstance>`]
1115
+ """
1116
+ return self._pedb.get_connected_objects(self.object_instance)