pyedb 0.2.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 (128) hide show
  1. pyedb/__init__.py +17 -0
  2. pyedb/dotnet/__init__.py +0 -0
  3. pyedb/dotnet/application/Variables.py +2261 -0
  4. pyedb/dotnet/application/__init__.py +0 -0
  5. pyedb/dotnet/clr_module.py +103 -0
  6. pyedb/dotnet/edb.py +4237 -0
  7. pyedb/dotnet/edb_core/__init__.py +1 -0
  8. pyedb/dotnet/edb_core/cell/__init__.py +0 -0
  9. pyedb/dotnet/edb_core/cell/hierarchy/__init__.py +0 -0
  10. pyedb/dotnet/edb_core/cell/hierarchy/model.py +66 -0
  11. pyedb/dotnet/edb_core/components.py +2669 -0
  12. pyedb/dotnet/edb_core/configuration.py +423 -0
  13. pyedb/dotnet/edb_core/definition/__init__.py +0 -0
  14. pyedb/dotnet/edb_core/definition/component_def.py +166 -0
  15. pyedb/dotnet/edb_core/definition/component_model.py +30 -0
  16. pyedb/dotnet/edb_core/definition/definition_obj.py +18 -0
  17. pyedb/dotnet/edb_core/definition/definitions.py +12 -0
  18. pyedb/dotnet/edb_core/dotnet/__init__.py +0 -0
  19. pyedb/dotnet/edb_core/dotnet/database.py +1218 -0
  20. pyedb/dotnet/edb_core/dotnet/layout.py +238 -0
  21. pyedb/dotnet/edb_core/dotnet/primitive.py +1517 -0
  22. pyedb/dotnet/edb_core/edb_data/__init__.py +0 -0
  23. pyedb/dotnet/edb_core/edb_data/components_data.py +938 -0
  24. pyedb/dotnet/edb_core/edb_data/connectable.py +113 -0
  25. pyedb/dotnet/edb_core/edb_data/control_file.py +1268 -0
  26. pyedb/dotnet/edb_core/edb_data/design_options.py +35 -0
  27. pyedb/dotnet/edb_core/edb_data/edbvalue.py +45 -0
  28. pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +330 -0
  29. pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +1607 -0
  30. pyedb/dotnet/edb_core/edb_data/layer_data.py +576 -0
  31. pyedb/dotnet/edb_core/edb_data/nets_data.py +281 -0
  32. pyedb/dotnet/edb_core/edb_data/obj_base.py +19 -0
  33. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +2080 -0
  34. pyedb/dotnet/edb_core/edb_data/ports.py +287 -0
  35. pyedb/dotnet/edb_core/edb_data/primitives_data.py +1397 -0
  36. pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +2914 -0
  37. pyedb/dotnet/edb_core/edb_data/simulation_setup.py +716 -0
  38. pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1205 -0
  39. pyedb/dotnet/edb_core/edb_data/sources.py +514 -0
  40. pyedb/dotnet/edb_core/edb_data/terminals.py +632 -0
  41. pyedb/dotnet/edb_core/edb_data/utilities.py +148 -0
  42. pyedb/dotnet/edb_core/edb_data/variables.py +91 -0
  43. pyedb/dotnet/edb_core/general.py +181 -0
  44. pyedb/dotnet/edb_core/hfss.py +1646 -0
  45. pyedb/dotnet/edb_core/layout.py +1244 -0
  46. pyedb/dotnet/edb_core/layout_validation.py +272 -0
  47. pyedb/dotnet/edb_core/materials.py +939 -0
  48. pyedb/dotnet/edb_core/net_class.py +335 -0
  49. pyedb/dotnet/edb_core/nets.py +1215 -0
  50. pyedb/dotnet/edb_core/padstack.py +1389 -0
  51. pyedb/dotnet/edb_core/siwave.py +1427 -0
  52. pyedb/dotnet/edb_core/stackup.py +2703 -0
  53. pyedb/edb_logger.py +396 -0
  54. pyedb/generic/__init__.py +0 -0
  55. pyedb/generic/constants.py +1063 -0
  56. pyedb/generic/data_handlers.py +320 -0
  57. pyedb/generic/design_types.py +104 -0
  58. pyedb/generic/filesystem.py +150 -0
  59. pyedb/generic/general_methods.py +1535 -0
  60. pyedb/generic/plot.py +1840 -0
  61. pyedb/generic/process.py +285 -0
  62. pyedb/generic/settings.py +224 -0
  63. pyedb/ipc2581/__init__.py +0 -0
  64. pyedb/ipc2581/bom/__init__.py +0 -0
  65. pyedb/ipc2581/bom/bom.py +21 -0
  66. pyedb/ipc2581/bom/bom_item.py +32 -0
  67. pyedb/ipc2581/bom/characteristics.py +37 -0
  68. pyedb/ipc2581/bom/refdes.py +16 -0
  69. pyedb/ipc2581/content/__init__.py +0 -0
  70. pyedb/ipc2581/content/color.py +38 -0
  71. pyedb/ipc2581/content/content.py +55 -0
  72. pyedb/ipc2581/content/dictionary_color.py +29 -0
  73. pyedb/ipc2581/content/dictionary_fill.py +28 -0
  74. pyedb/ipc2581/content/dictionary_line.py +30 -0
  75. pyedb/ipc2581/content/entry_color.py +13 -0
  76. pyedb/ipc2581/content/entry_line.py +14 -0
  77. pyedb/ipc2581/content/fill.py +15 -0
  78. pyedb/ipc2581/content/layer_ref.py +10 -0
  79. pyedb/ipc2581/content/standard_geometries_dictionary.py +72 -0
  80. pyedb/ipc2581/ecad/__init__.py +0 -0
  81. pyedb/ipc2581/ecad/cad_data/__init__.py +0 -0
  82. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +26 -0
  83. pyedb/ipc2581/ecad/cad_data/cad_data.py +37 -0
  84. pyedb/ipc2581/ecad/cad_data/component.py +41 -0
  85. pyedb/ipc2581/ecad/cad_data/drill.py +30 -0
  86. pyedb/ipc2581/ecad/cad_data/feature.py +54 -0
  87. pyedb/ipc2581/ecad/cad_data/layer.py +41 -0
  88. pyedb/ipc2581/ecad/cad_data/layer_feature.py +151 -0
  89. pyedb/ipc2581/ecad/cad_data/logical_net.py +32 -0
  90. pyedb/ipc2581/ecad/cad_data/outline.py +25 -0
  91. pyedb/ipc2581/ecad/cad_data/package.py +104 -0
  92. pyedb/ipc2581/ecad/cad_data/padstack_def.py +38 -0
  93. pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +24 -0
  94. pyedb/ipc2581/ecad/cad_data/padstack_instance.py +62 -0
  95. pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +26 -0
  96. pyedb/ipc2581/ecad/cad_data/path.py +89 -0
  97. pyedb/ipc2581/ecad/cad_data/phy_net.py +80 -0
  98. pyedb/ipc2581/ecad/cad_data/pin.py +31 -0
  99. pyedb/ipc2581/ecad/cad_data/polygon.py +169 -0
  100. pyedb/ipc2581/ecad/cad_data/profile.py +40 -0
  101. pyedb/ipc2581/ecad/cad_data/stackup.py +31 -0
  102. pyedb/ipc2581/ecad/cad_data/stackup_group.py +42 -0
  103. pyedb/ipc2581/ecad/cad_data/stackup_layer.py +21 -0
  104. pyedb/ipc2581/ecad/cad_data/step.py +275 -0
  105. pyedb/ipc2581/ecad/cad_header.py +33 -0
  106. pyedb/ipc2581/ecad/ecad.py +19 -0
  107. pyedb/ipc2581/ecad/spec.py +46 -0
  108. pyedb/ipc2581/history_record.py +37 -0
  109. pyedb/ipc2581/ipc2581.py +387 -0
  110. pyedb/ipc2581/logistic_header.py +25 -0
  111. pyedb/misc/__init__.py +0 -0
  112. pyedb/misc/aedtlib_personalib_install.py +14 -0
  113. pyedb/misc/downloads.py +322 -0
  114. pyedb/misc/misc.py +67 -0
  115. pyedb/misc/pyedb.runtimeconfig.json +13 -0
  116. pyedb/misc/siw_feature_config/__init__.py +0 -0
  117. pyedb/misc/siw_feature_config/emc/__init__.py +0 -0
  118. pyedb/misc/siw_feature_config/emc/component_tags.py +46 -0
  119. pyedb/misc/siw_feature_config/emc/net_tags.py +37 -0
  120. pyedb/misc/siw_feature_config/emc/tag_library.py +62 -0
  121. pyedb/misc/siw_feature_config/emc/xml_generic.py +78 -0
  122. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +179 -0
  123. pyedb/misc/utilities.py +27 -0
  124. pyedb/modeler/geometry_operators.py +2082 -0
  125. pyedb-0.2.0.dist-info/LICENSE +21 -0
  126. pyedb-0.2.0.dist-info/METADATA +208 -0
  127. pyedb-0.2.0.dist-info/RECORD +128 -0
  128. pyedb-0.2.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,37 @@
1
+ from datetime import date
2
+
3
+ from pyedb.generic.general_methods import ET
4
+
5
+
6
+ class HistoryRecord(object):
7
+ def __init__(self):
8
+ self.number = "1"
9
+ self.origination = date.today()
10
+ self.software = "Ansys PyEDB"
11
+ self.last_changes = date.today()
12
+ self.file_revision = "1"
13
+ self.comment = ""
14
+ self.software_package = "Ansys AEDT"
15
+ self.revision = "R2023.1"
16
+ self.vendor = "Ansys"
17
+ self.certification_status = "CERTIFIED"
18
+
19
+ def write_xml(self, root): # pragma no cover
20
+ history_record = ET.SubElement(root, "HistoryRecord")
21
+ history_record.set("number", self.number)
22
+ history_record.set(
23
+ "origination", "{}_{}_{}".format(self.origination.day, self.origination.month, self.origination.year)
24
+ )
25
+ history_record.set("software", self.software)
26
+ history_record.set(
27
+ "lastChange", "{}_{}_{}".format(self.origination.day, self.origination.month, self.origination.year)
28
+ )
29
+ file_revision = ET.SubElement(history_record, "FileRevision")
30
+ file_revision.set("fileRevisionId", self.file_revision)
31
+ file_revision.set("comment", self.comment)
32
+ software_package = ET.SubElement(file_revision, "SoftwarePackage")
33
+ software_package.set("name", self.software_package)
34
+ software_package.set("revision", self.revision)
35
+ software_package.set("vendor", self.vendor)
36
+ certification = ET.SubElement(software_package, "Certification")
37
+ certification.set("certificationStatus", self.certification_status)
@@ -0,0 +1,387 @@
1
+ import os.path
2
+
3
+ from pyedb.generic.general_methods import ET, pyedb_function_handler
4
+ from pyedb.ipc2581.bom.bom import Bom
5
+ from pyedb.ipc2581.bom.bom_item import BomItem
6
+ from pyedb.ipc2581.content.content import Content
7
+ from pyedb.ipc2581.ecad.cad_data.padstack_def import PadstackDef
8
+ from pyedb.ipc2581.ecad.ecad import Ecad
9
+ from pyedb.ipc2581.history_record import HistoryRecord
10
+ from pyedb.ipc2581.logistic_header import LogisticHeader
11
+
12
+
13
+ class Ipc2581(object):
14
+ """Manages the Ipc2581 exporter."""
15
+
16
+ def __init__(self, pedb, units):
17
+ self.revision = "C"
18
+ self._pedb = pedb
19
+ self.units = units
20
+ self.content = Content(self)
21
+ self.logistic_header = LogisticHeader()
22
+ self.history_record = HistoryRecord()
23
+ self.bom = Bom(pedb)
24
+ self.ecad = Ecad(self, pedb, units)
25
+ self.file_path = ""
26
+ self.design_name = ""
27
+ self.top_bottom_layers = []
28
+
29
+ @pyedb_function_handler()
30
+ def load_ipc_model(self):
31
+ self.design_name = self._pedb.cell_names[0]
32
+ self.content.step_ref = self.design_name
33
+ self._pedb.logger.info("Parsing Layers...")
34
+ self.add_layers_info()
35
+ self._pedb.logger.info("Parsing BOM...")
36
+ self.add_bom()
37
+ self._pedb.logger.info("Parsing Padstack Definitions...")
38
+ self.add_pdstack_definition()
39
+ self.add_profile()
40
+ self._pedb.logger.info("Parsing Components...")
41
+ self.add_components()
42
+ self._pedb.logger.info("Parsing Logical Nets...")
43
+ self.add_logical_nets()
44
+ self._pedb.logger.info("Parsing Layout Primitives...")
45
+ self.add_layer_features()
46
+ self._pedb.logger.info("Parsing Drills...")
47
+ self.add_drills()
48
+ self._pedb.logger.info("Parsing EDB Completed!")
49
+
50
+ @pyedb_function_handler()
51
+ def add_pdstack_definition(self):
52
+ for padstack_name, padstackdef in self._pedb.padstacks.definitions.items():
53
+ padstack_def = PadstackDef()
54
+ padstack_def.name = padstack_name
55
+ padstack_def.padstack_hole_def.name = padstack_name
56
+ if padstackdef.hole_properties:
57
+ padstack_def.padstack_hole_def.diameter = self.from_meter_to_units(
58
+ padstackdef.hole_properties[0], self.units
59
+ )
60
+ for layer, pad in padstackdef.pad_by_layer.items():
61
+ if pad.parameters_values:
62
+ if pad.geometry_type == 1:
63
+ primitive_ref = "CIRCLE_{}".format(
64
+ self.from_meter_to_units(pad.parameters_values[0], self.units)
65
+ )
66
+ if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
67
+ self.content.standard_geometries_dict.standard_circ_dict[
68
+ primitive_ref
69
+ ] = self.from_meter_to_units(pad.parameters_values[0], self.units)
70
+ elif pad.geometry_type == 2:
71
+ primitive_ref = "RECT_{}_{}".format(
72
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
73
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
74
+ )
75
+ if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
76
+ self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
77
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
78
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
79
+ ]
80
+ elif pad.geometry_type == 3:
81
+ primitive_ref = "RECT_{}_{}".format(
82
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
83
+ self.from_meter_to_units(pad.parameters_values[1], self.units),
84
+ )
85
+ if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
86
+ self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
87
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
88
+ self.from_meter_to_units(pad.parameters_values[1], self.units),
89
+ ]
90
+
91
+ elif pad.geometry_type == 4:
92
+ primitive_ref = "OVAL_{}_{}_{}".format(
93
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
94
+ self.from_meter_to_units(pad.parameters_values[1], self.units),
95
+ self.from_meter_to_units(pad.parameters_values[2], self.units),
96
+ )
97
+ if not primitive_ref in self.content.standard_geometries_dict.standard_oval_dict:
98
+ self.content.standard_geometries_dict.standard_oval_dict[primitive_ref] = [
99
+ self.from_meter_to_units(pad.parameters_values[0], self.units),
100
+ self.from_meter_to_units(pad.parameters_values[1], self.units),
101
+ self.from_meter_to_units(pad.parameters_values[2], self.units),
102
+ ]
103
+ else:
104
+ primitive_ref = "Default"
105
+ padstack_def.add_padstack_pad_def(layer=layer, pad_use="REGULAR", primitive_ref=primitive_ref)
106
+ for layer, antipad in padstackdef.antipad_by_layer.items():
107
+ if antipad.parameters_values:
108
+ if antipad.geometry_type == 1:
109
+ primitive_ref = "CIRCLE_{}".format(
110
+ self.from_meter_to_units(antipad.parameters_values[0], self.units)
111
+ )
112
+ if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
113
+ self.content.standard_geometries_dict.standard_circ_dict[
114
+ primitive_ref
115
+ ] = self.from_meter_to_units(antipad.parameters_values[0], self.units)
116
+ elif antipad.geometry_type == 2:
117
+ primitive_ref = "RECT_{}_{}".format(
118
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
119
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
120
+ )
121
+ if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
122
+ self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
123
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
124
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
125
+ ]
126
+ elif antipad.geometry_type == 3:
127
+ primitive_ref = "RECT_{}_{}".format(
128
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
129
+ self.from_meter_to_units(antipad.parameters_values[1], self.units),
130
+ )
131
+ if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
132
+ self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
133
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
134
+ self.from_meter_to_units(antipad.parameters_values[1], self.units),
135
+ ]
136
+ elif antipad.geometry_type == 4:
137
+ primitive_ref = "OVAL_{}_{}_{}".format(
138
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
139
+ self.from_meter_to_units(antipad.parameters_values[1], self.units),
140
+ self.from_meter_to_units(antipad.parameters_values[2], self.units),
141
+ )
142
+ if not primitive_ref in self.content.standard_geometries_dict.standard_oval_dict:
143
+ self.content.standard_geometries_dict.standard_oval_dict[primitive_ref] = [
144
+ self.from_meter_to_units(antipad.parameters_values[0], self.units),
145
+ self.from_meter_to_units(antipad.parameters_values[1], self.units),
146
+ self.from_meter_to_units(antipad.parameters_values[2], self.units),
147
+ ]
148
+ else:
149
+ primitive_ref = "Default"
150
+ padstack_def.add_padstack_pad_def(layer=layer, pad_use="ANTIPAD", primitive_ref=primitive_ref)
151
+ for layer, thermalpad in padstackdef.thermalpad_by_layer.items():
152
+ if thermalpad.parameters_values:
153
+ if thermalpad.geometry_type == 1:
154
+ primitive_ref = "CIRCLE_{}".format(
155
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units)
156
+ )
157
+ if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
158
+ self.content.standard_geometries_dict[primitive_ref] = self.from_meter_to_units(
159
+ thermalpad.parameters_values[0], self.units
160
+ )
161
+ elif thermalpad.geometry_type == 2:
162
+ primitive_ref = "RECT_{}_{}".format(
163
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
164
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
165
+ )
166
+ if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
167
+ self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
168
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
169
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
170
+ ]
171
+ elif thermalpad.geometry_type == 3:
172
+ primitive_ref = "RECT_{}_{}".format(
173
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
174
+ self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
175
+ )
176
+ if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
177
+ self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
178
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
179
+ self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
180
+ ]
181
+ elif thermalpad.geometry_type == 4:
182
+ primitive_ref = "OVAL_{}_{}_{}".format(
183
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
184
+ self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
185
+ self.from_meter_to_units(thermalpad.parameters_values[2], self.units),
186
+ )
187
+ if not primitive_ref in self.content.standard_geometries_dict.standard_oval_dict:
188
+ self.content.standard_geometries_dict.standard_oval_dict[primitive_ref] = [
189
+ self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
190
+ self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
191
+ self.from_meter_to_units(thermalpad.parameters_values[2], self.units),
192
+ ]
193
+ else:
194
+ primitive_ref = "Default"
195
+ padstack_def.add_padstack_pad_def(layer=layer, pad_use="THERMAL", primitive_ref=primitive_ref)
196
+ if not padstack_def.name in self.ecad.cad_data.cad_data_step.padstack_defs:
197
+ self.ecad.cad_data.cad_data_step.padstack_defs[padstack_def.name] = padstack_def
198
+
199
+ @pyedb_function_handler()
200
+ def add_bom(self):
201
+ # Bom
202
+ for part_name, components in self._pedb.components.components_by_partname.items():
203
+ bom_item = BomItem()
204
+ bom_item.part_name = part_name
205
+ bom_item.quantity = len(components)
206
+ bom_item.pin_count = components[0].numpins
207
+ bom_item.category = "ELECTRICAL"
208
+ bom_item.charactistics.device_type = components[0].type
209
+ bom_item.charactistics.category = "ELECTRICAL"
210
+ bom_item.charactistics.component_class = "DISCRETE"
211
+ if components[0].type == "Resistor":
212
+ bom_item.charactistics.value = components[0].res_value
213
+ elif components[0].type == "Capacitor":
214
+ bom_item.charactistics.value = components[0].cap_value
215
+ elif components[0].type == "Inductor":
216
+ bom_item.charactistics.value = components[0].ind_value
217
+ for cmp in components:
218
+ bom_item.add_refdes(
219
+ component_name=cmp.refdes, placement_layer=cmp.placement_layer, package_def="", populate=True
220
+ )
221
+ self.bom.bom_items.append(bom_item)
222
+
223
+ @pyedb_function_handler()
224
+ def add_layers_info(self):
225
+ self.design_name = self._pedb.layout.cell.GetName()
226
+ self.ecad.design_name = self.design_name
227
+ self.ecad.cad_header.units = self.units
228
+ self.ecad.cad_data.stackup.total_thickness = self.from_meter_to_units(
229
+ self._pedb.stackup.get_layout_thickness(), self.units
230
+ )
231
+ self.ecad.cad_data.stackup.stackup_group.thickness = self.ecad.cad_data.stackup.total_thickness
232
+ self.layers_name = list(self._pedb.stackup.signal_layers.keys())
233
+ self.top_bottom_layers = [self.layers_name[0], self.layers_name[-1]]
234
+ sequence = 0
235
+ for layer_name in list(self._pedb.stackup.stackup_layers.keys()):
236
+ sequence += 1
237
+ self.content.add_layer_ref(layer_name)
238
+ layer_color = self._pedb.stackup.layers[layer_name].color
239
+ self.content.dict_colors.add_color(
240
+ "{}".format(layer_name), str(layer_color[0]), str(layer_color[1]), str(layer_color[2])
241
+ )
242
+ # Ecad layers
243
+ layer_type = "CONDUCTOR"
244
+ conductivity = 5e6
245
+ permitivity = 1
246
+ loss_tg = 0
247
+ embedded = "NOT_EMBEDDED"
248
+ # try:
249
+ material_name = self._pedb.stackup.layers[layer_name]._edb_layer.GetMaterial()
250
+ edb_material = self._pedb.edb_api.definition.MaterialDef.FindByName(self._pedb.active_db, material_name)
251
+ material_type = "CONDUCTOR"
252
+ if self._pedb.stackup.layers[layer_name].type == "dielectric":
253
+ layer_type = "DIELPREG"
254
+ material_type = "DIELECTRIC"
255
+
256
+ permitivity = edb_material.GetProperty(self._pedb.edb_api.definition.MaterialPropertyId.Permittivity)[1]
257
+ if not isinstance(permitivity, float):
258
+ permitivity = permitivity.ToDouble()
259
+ loss_tg = edb_material.GetProperty(
260
+ self._pedb.edb_api.definition.MaterialPropertyId.DielectricLossTangent
261
+ )[1]
262
+ if not isinstance(loss_tg, float):
263
+ loss_tg = loss_tg.ToDouble()
264
+ conductivity = 0
265
+ if layer_type == "CONDUCTOR":
266
+ conductivity = edb_material.GetProperty(self._pedb.edb_api.definition.MaterialPropertyId.Conductivity)[
267
+ 1
268
+ ]
269
+ if not isinstance(conductivity, float):
270
+ conductivity = conductivity.ToDouble()
271
+ self.ecad.cad_header.add_spec(
272
+ name=layer_name,
273
+ material=self._pedb.stackup.layers[layer_name]._edb_layer.GetMaterial(),
274
+ layer_type=material_type,
275
+ conductivity=str(conductivity),
276
+ dielectric_constant=str(permitivity),
277
+ loss_tg=str(loss_tg),
278
+ embedded=embedded,
279
+ )
280
+ layer_position = "INTERNAL"
281
+ if layer_name == self.top_bottom_layers[0]:
282
+ layer_position = "TOP"
283
+ if layer_name == self.top_bottom_layers[1]:
284
+ layer_position = "BOTTOM"
285
+ self.ecad.cad_data.add_layer(
286
+ layer_name=layer_name, layer_function=layer_type, layer_side=layer_position, polarity="POSITIVE"
287
+ )
288
+ layer_thickness_with_units = self.from_meter_to_units(
289
+ self._pedb.stackup.layers[layer_name].thickness, self.units
290
+ )
291
+ self.ecad.cad_data.stackup.stackup_group.add_stackup_layer(
292
+ layer_name=layer_name, thickness=layer_thickness_with_units, sequence=str(sequence)
293
+ )
294
+ # except:
295
+ # pass
296
+ self.ecad.cad_data.add_layer(layer_name="Drill", layer_function="DRILL", layer_side="ALL", polarity="POSITIVE")
297
+ self.content.add_layer_ref("Drill")
298
+ self.content.dict_colors.add_color("{}".format("Drill"), "255", "255", "255")
299
+
300
+ @pyedb_function_handler()
301
+ def add_components(self):
302
+ for item in self._pedb.components.components.values():
303
+ self.ecad.cad_data.cad_data_step.add_component(item)
304
+
305
+ @pyedb_function_handler()
306
+ def add_logical_nets(self):
307
+ nets = [i for i in self._pedb.nets.nets.values()]
308
+ for net in nets:
309
+ self.ecad.cad_data.cad_data_step.add_logical_net(net)
310
+
311
+ @pyedb_function_handler()
312
+ def add_profile(self):
313
+ profile = self._pedb.modeler.primitives_by_layer["Outline"]
314
+ for prim in profile:
315
+ self.ecad.cad_data.cad_data_step.add_profile(prim)
316
+
317
+ @pyedb_function_handler()
318
+ def add_layer_features(self):
319
+ layers = {i: j for i, j in self._pedb.stackup.layers.items()}
320
+ padstack_instances = list(self._pedb.padstacks.instances.values())
321
+ padstack_defs = {i: k for i, k in self._pedb.padstacks.definitions.items()}
322
+ polys = {i: j for i, j in self._pedb.modeler.primitives_by_layer.items()}
323
+ for layer_name, layer in layers.items():
324
+ self.ecad.cad_data.cad_data_step.add_layer_feature(layer, polys[layer_name])
325
+ self.ecad.cad_data.cad_data_step.add_padstack_instances(padstack_instances, padstack_defs)
326
+
327
+ @pyedb_function_handler()
328
+ def add_drills(self):
329
+ via_list = [
330
+ obj for obj in list(self._pedb.padstacks.instances.values()) if not obj.start_layer == obj.stop_layer
331
+ ]
332
+ l1 = len(list(self._pedb.stackup.signal_layers.keys()))
333
+
334
+ self.ecad.cad_data.cad_data_step.add_drill_layer_feature(via_list, "DRILL_1-{}".format(l1))
335
+
336
+ @pyedb_function_handler()
337
+ def from_meter_to_units(self, value, units):
338
+ if isinstance(value, str):
339
+ value = float(value)
340
+ if isinstance(value, list):
341
+ returned_list = []
342
+ for val in value:
343
+ if isinstance(val, str):
344
+ val = float(val)
345
+ if units.lower() == "mm":
346
+ returned_list.append(round(val * 1000, 4))
347
+ if units.lower() == "um":
348
+ returned_list.append(round(val * 1e6, 4))
349
+ if units.lower() == "mils":
350
+ returned_list.append(round(val * 39370.079, 4))
351
+ if units.lower() == "inch":
352
+ returned_list.append(round(val * 39.370079, 4))
353
+ if units.lower() == "cm":
354
+ returned_list.append(round(val * 100, 4))
355
+ return returned_list
356
+ else:
357
+ if units.lower() == "millimeter":
358
+ return round(value * 1000, 4)
359
+ if units.lower() == "micrometer":
360
+ return round(value * 1e6, 4)
361
+ if units.lower() == "mils":
362
+ return round(value * 39370.079, 4)
363
+ if units.lower() == "inch":
364
+ return round(value * 39.370079, 4)
365
+ if units.lower() == "centimeter":
366
+ return round(value * 100, 4)
367
+
368
+ @pyedb_function_handler()
369
+ def write_xml(self):
370
+ if self.file_path:
371
+ ipc = ET.Element("IPC-2581")
372
+ ipc.set("revision", self.revision)
373
+ ipc.set("xmlns", "http://webstds.ipc.org/2581")
374
+ ipc.set("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
375
+ ipc.set("xmlns:xsd", "http://www.w3.org/2001/XMLSchema")
376
+ self.content.write_wml(ipc)
377
+ self.logistic_header.write_xml(ipc)
378
+ self.history_record.write_xml(ipc)
379
+ self.bom.write_xml(ipc)
380
+ self.ecad.write_xml(ipc)
381
+ try:
382
+ ET.indent(ipc)
383
+ except AttributeError:
384
+ pass
385
+ tree = ET.ElementTree(ipc)
386
+ tree.write(self.file_path)
387
+ return True if os.path.exists(self.file_path) else False
@@ -0,0 +1,25 @@
1
+ from pyedb.generic.general_methods import ET
2
+
3
+
4
+ class LogisticHeader(object):
5
+ def __init__(self):
6
+ self.owner = "PyEDB"
7
+ self.sender = "Ansys"
8
+ self.enterprise = "Ansys"
9
+ self.code = "UNKNOWN"
10
+ self.person_name = "eba"
11
+ self.enterprise_ref = "UNKNOWN"
12
+ self.role_ref = "PyEDB"
13
+
14
+ def write_xml(self, root): # pragma no cover
15
+ logistic_header = ET.SubElement(root, "LogisticHeader")
16
+ role = ET.SubElement(logistic_header, "Role")
17
+ role.set("id", self.owner)
18
+ role.set("roleFunction", self.sender)
19
+ enterprise = ET.SubElement(logistic_header, "Enterprise")
20
+ enterprise.set("id", self.enterprise)
21
+ enterprise.set("code", self.code)
22
+ person = ET.SubElement(logistic_header, "Person")
23
+ person.set("name", self.person_name)
24
+ person.set("enterpriseRef", self.enterprise_ref)
25
+ person.set("roleRef", self.role_ref)
pyedb/misc/__init__.py ADDED
File without changes
@@ -0,0 +1,14 @@
1
+ from xml.dom.minidom import parseString
2
+ import xml.etree.ElementTree as ET
3
+
4
+
5
+ def write_pretty_xml(root, file_path):
6
+ """Write the XML in a pretty format."""
7
+ # If we use the commented code below, then the previously existing lines will have double lines added. We need to
8
+ # split and ignore the double lines.
9
+ # xml_str = parseString(ET.tostring(root)).toprettyxml(indent=" " * 4)
10
+ lines = [line for line in parseString(ET.tostring(root)).toprettyxml(indent=" " * 4).split("\n") if line.strip()]
11
+ xml_str = "\n".join(lines)
12
+
13
+ with open(file_path, "w") as f:
14
+ f.write(xml_str)