pyedb 0.7.0__py3-none-any.whl → 0.8.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 (46) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/dotnet/clr_module.py +1 -1
  3. pyedb/dotnet/edb.py +7 -7
  4. pyedb/dotnet/edb_core/cell/hierarchy/model.py +1 -1
  5. pyedb/dotnet/edb_core/components.py +15 -12
  6. pyedb/dotnet/edb_core/configuration.py +232 -25
  7. pyedb/dotnet/edb_core/definition/component_def.py +10 -1
  8. pyedb/dotnet/edb_core/definition/component_model.py +1 -1
  9. pyedb/dotnet/edb_core/definition/definition_obj.py +1 -1
  10. pyedb/dotnet/edb_core/definition/definitions.py +8 -2
  11. pyedb/dotnet/edb_core/definition/package_def.py +61 -15
  12. pyedb/dotnet/edb_core/dotnet/database.py +5 -4
  13. pyedb/dotnet/edb_core/edb_data/components_data.py +3 -2
  14. pyedb/dotnet/edb_core/edb_data/connectable.py +1 -1
  15. pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +14 -13
  16. pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +2 -2
  17. pyedb/dotnet/edb_core/edb_data/layer_data.py +9 -3
  18. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +6 -5
  19. pyedb/dotnet/edb_core/edb_data/primitives_data.py +16 -13
  20. pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +7 -1
  21. pyedb/dotnet/edb_core/edb_data/sources.py +10 -0
  22. pyedb/dotnet/edb_core/geometry/__init__.py +0 -0
  23. pyedb/dotnet/edb_core/{edb_data/obj_base.py → geometry/point_data.py} +12 -26
  24. pyedb/dotnet/edb_core/geometry/polygon_data.py +77 -0
  25. pyedb/dotnet/edb_core/layout.py +59 -0
  26. pyedb/dotnet/edb_core/materials.py +715 -597
  27. pyedb/dotnet/edb_core/nets.py +3 -3
  28. pyedb/dotnet/edb_core/obj_base.py +94 -0
  29. pyedb/dotnet/edb_core/padstack.py +57 -6
  30. pyedb/dotnet/edb_core/siwave.py +11 -4
  31. pyedb/dotnet/edb_core/stackup.py +152 -131
  32. pyedb/dotnet/edb_core/utilities/__init__.py +3 -0
  33. pyedb/dotnet/edb_core/utilities/heatsink.py +69 -0
  34. pyedb/dotnet/sim_setup_data/data/siw_dc_ir_settings.py +46 -0
  35. pyedb/edb_logger.py +15 -1
  36. pyedb/exceptions.py +6 -0
  37. pyedb/generic/filesystem.py +7 -3
  38. pyedb/generic/general_methods.py +4 -0
  39. pyedb/generic/process.py +4 -1
  40. pyedb/generic/settings.py +30 -8
  41. pyedb/siwave.py +50 -1
  42. {pyedb-0.7.0.dist-info → pyedb-0.8.0.dist-info}/METADATA +31 -53
  43. {pyedb-0.7.0.dist-info → pyedb-0.8.0.dist-info}/RECORD +46 -39
  44. /pyedb/dotnet/edb_core/{edb_data → utilities}/simulation_setup.py +0 -0
  45. {pyedb-0.7.0.dist-info → pyedb-0.8.0.dist-info}/LICENSE +0 -0
  46. {pyedb-0.7.0.dist-info → pyedb-0.8.0.dist-info}/WHEEL +0 -0
@@ -31,7 +31,6 @@ from collections import OrderedDict
31
31
  import json
32
32
  import logging
33
33
  import math
34
- import re
35
34
  import warnings
36
35
 
37
36
  from pyedb.dotnet.edb_core.edb_data.layer_data import (
@@ -47,9 +46,15 @@ from pyedb.generic.general_methods import (
47
46
  )
48
47
  from pyedb.misc.aedtlib_personalib_install import write_pretty_xml
49
48
 
49
+ colors = None
50
50
  pd = None
51
51
  np = None
52
52
  if not is_ironpython:
53
+ try:
54
+ import matplotlib.colors as colors
55
+ except ImportError:
56
+ colors = None
57
+
53
58
  try:
54
59
  import numpy as np
55
60
  except ImportError:
@@ -199,7 +204,7 @@ class Stackup(object):
199
204
  inner_layer_thickness="17um",
200
205
  outer_layer_thickness="50um",
201
206
  dielectric_thickness="100um",
202
- dielectric_material="fr4_epoxy",
207
+ dielectric_material="FR4_epoxy",
203
208
  soldermask=True,
204
209
  soldermask_thickness="20um",
205
210
  ): # pragma: no cover
@@ -242,7 +247,7 @@ class Stackup(object):
242
247
  self.add_layer(
243
248
  "D" + str(int(layer_count / 2)),
244
249
  None,
245
- material="fr4_epoxy",
250
+ material="FR4_epoxy",
246
251
  thickness=dielectric_thickness,
247
252
  layer_type="dielectric",
248
253
  fillMaterial=dielectric_material,
@@ -258,7 +263,7 @@ class Stackup(object):
258
263
  self.add_layer(
259
264
  "SMT",
260
265
  None,
261
- material="solder_mask",
266
+ material="SolderMask",
262
267
  thickness=soldermask_thickness,
263
268
  layer_type="dielectric",
264
269
  fillMaterial=dielectric_material,
@@ -266,14 +271,14 @@ class Stackup(object):
266
271
  self.add_layer(
267
272
  "SMB",
268
273
  None,
269
- material="solder_mask",
274
+ material="SolderMask",
270
275
  thickness=soldermask_thickness,
271
276
  layer_type="dielectric",
272
277
  fillMaterial=dielectric_material,
273
278
  method="add_on_bottom",
274
279
  )
275
- self.stackup_layers["TOP"].dielectric_fill = "solder_mask"
276
- self.stackup_layers["BOT"].dielectric_fill = "solder_mask"
280
+ self.stackup_layers["TOP"].dielectric_fill = "SolderMask"
281
+ self.stackup_layers["BOT"].dielectric_fill = "SolderMask"
277
282
 
278
283
  for layer_num in np.arange(int(layer_count / 2), 1, -1):
279
284
  # Generate upper half
@@ -633,6 +638,7 @@ class Stackup(object):
633
638
  else:
634
639
  return False
635
640
 
641
+ # TODO: Update optional argument material into material_name and fillMaterial into fill_material_name
636
642
  @pyedb_function_handler()
637
643
  def add_layer(
638
644
  self,
@@ -641,7 +647,7 @@ class Stackup(object):
641
647
  method="add_on_top",
642
648
  layer_type="signal",
643
649
  material="copper",
644
- fillMaterial="fr4_epoxy",
650
+ fillMaterial="FR4_epoxy",
645
651
  thickness="35um",
646
652
  etch_factor=None,
647
653
  is_negative=False,
@@ -685,25 +691,25 @@ class Stackup(object):
685
691
  if layer_name in self.layers:
686
692
  logger.error("layer {} exists.".format(layer_name))
687
693
  return False
688
- materials_lower = {m.lower(): m for m in list(self._pedb.materials.materials.keys())}
689
694
  if not material:
690
- if layer_type == "signal":
691
- material = "copper"
692
- else:
693
- material = "fr4_epoxy"
695
+ material = "copper" if layer_type == "signal" else "FR4_epoxy"
694
696
  if not fillMaterial:
695
- fillMaterial = "fr4_epoxy"
697
+ fillMaterial = "FR4_epoxy"
696
698
 
697
- if material.lower() not in materials_lower:
698
- logger.error(material + " does not exist in material library")
699
- else:
700
- material = materials_lower[material.lower()]
699
+ materials = self._pedb.materials
700
+ if material not in materials:
701
+ logger.warning(
702
+ f"Material '{material}' does not exist in material library. Intempt to create it from syslib."
703
+ )
704
+ material_properties = self._pedb.materials.read_syslib_material(material)
705
+ materials.add_material(material, **material_properties)
701
706
 
702
- if layer_type != "dielectric":
703
- if fillMaterial.lower() not in materials_lower:
704
- logger.error(fillMaterial + " does not exist in material library")
705
- else:
706
- fillMaterial = materials_lower[fillMaterial.lower()]
707
+ if layer_type != "dielectric" and fillMaterial not in materials:
708
+ logger.warning(
709
+ f"Material '{fillMaterial}' does not exist in material library. Intempt to create it from syslib."
710
+ )
711
+ material_properties = self._pedb.materials.read_syslib_material(fillMaterial)
712
+ materials.add_material(fillMaterial, **material_properties)
707
713
 
708
714
  if layer_type in ["signal", "dielectric"]:
709
715
  new_layer = self._create_stackup_layer(layer_name, thickness, layer_type)
@@ -878,6 +884,7 @@ class Stackup(object):
878
884
  else:
879
885
  return False
880
886
 
887
+ # TODO: This method might need some refactoring
881
888
  @pyedb_function_handler()
882
889
  def _import_layer_stackup(self, input_file=None):
883
890
  if input_file:
@@ -886,7 +893,12 @@ class Stackup(object):
886
893
  for k, v in json_dict.items():
887
894
  if k == "materials":
888
895
  for material in v.values():
889
- self._pedb.materials._load_materials(material)
896
+ material_name = material["name"]
897
+ del material["name"]
898
+ if material_name not in self._pedb.materials:
899
+ self._pedb.materials.add_material(material_name, **material)
900
+ else:
901
+ self._pedb.materials.update_material(material_name, material)
890
902
  if k == "layers":
891
903
  if len(list(v.values())) == len(list(self.stackup_layers.values())):
892
904
  imported_layers_list = [l_dict["name"] for l_dict in list(v.values())]
@@ -1667,36 +1679,63 @@ class Stackup(object):
1667
1679
  temp_data = {name: area / outline_area * 100 for name, area in temp_data.items()}
1668
1680
  return temp_data
1669
1681
 
1682
+ # TODO: This method might need some refactoring
1670
1683
  @pyedb_function_handler()
1671
- def _import_dict(self, json_dict):
1684
+ def _import_dict(self, json_dict, rename=False):
1672
1685
  """Import stackup from a dictionary."""
1673
- mats = json_dict["materials"]
1674
- for material in mats.values():
1675
- self._pedb.materials._load_materials(material)
1676
-
1686
+ if not "materials" in json_dict:
1687
+ self._logger.warning("Configuration file does not have material definition")
1688
+ self._logger.warning(
1689
+ "Please check your json or xml file, if no material are defined your project will"
1690
+ "likely fail to simulate"
1691
+ )
1692
+ else:
1693
+ mats = json_dict["materials"]
1694
+ for material in mats.values():
1695
+ material_name = material["name"]
1696
+ del material["name"]
1697
+ if material_name not in self._pedb.materials:
1698
+ self._pedb.materials.add_material(material_name, **material)
1699
+ else:
1700
+ self._pedb.materials.update_material(material_name, material)
1677
1701
  temp = {i: j for i, j in json_dict["layers"].items() if j["type"] in ["signal", "dielectric"]}
1702
+ config_file_layers = list(temp.keys())
1703
+ layout_layers = list(self.stackup_layers.keys())
1704
+ renamed_layers = {}
1705
+ if rename and len(config_file_layers) == len(layout_layers):
1706
+ for lay_ind in range(len(list(temp.keys()))):
1707
+ if not config_file_layers[lay_ind] == layout_layers[lay_ind]:
1708
+ renamed_layers[layout_layers[lay_ind]] = config_file_layers[lay_ind]
1678
1709
  for name in list(self.stackup_layers.keys()):
1710
+ layer = None
1679
1711
  if name in temp:
1680
1712
  layer = temp[name]
1681
- default_layer = {
1682
- "name": "default",
1683
- "type": "signal",
1684
- "material": "copper",
1685
- "dielectric_fill": "fr4_epoxy",
1686
- "thickness": 3.5e-05,
1687
- "etch_factor": 0.0,
1688
- "roughness_enabled": False,
1689
- "top_hallhuray_nodule_radius": 0.0,
1690
- "top_hallhuray_surface_ratio": 0.0,
1691
- "bottom_hallhuray_nodule_radius": 0.0,
1692
- "bottom_hallhuray_surface_ratio": 0.0,
1693
- "side_hallhuray_nodule_radius": 0.0,
1694
- "side_hallhuray_surface_ratio": 0.0,
1695
- "upper_elevation": 0.0,
1696
- "lower_elevation": 0.0,
1697
- "color": [242, 140, 102],
1698
- }
1699
-
1713
+ elif name in renamed_layers:
1714
+ layer = temp[renamed_layers[name]]
1715
+ self.stackup_layers[name].name = renamed_layers[name]
1716
+ name = renamed_layers[name]
1717
+ else: # Remove layers not in config file.
1718
+ self.remove_layer(name)
1719
+ self._logger.warning(f"Layer {name} were not found in configuration file, removing layer")
1720
+ default_layer = {
1721
+ "name": "default",
1722
+ "type": "signal",
1723
+ "material": "copper",
1724
+ "dielectric_fill": "FR4_epoxy",
1725
+ "thickness": 3.5e-05,
1726
+ "etch_factor": 0.0,
1727
+ "roughness_enabled": False,
1728
+ "top_hallhuray_nodule_radius": 0.0,
1729
+ "top_hallhuray_surface_ratio": 0.0,
1730
+ "bottom_hallhuray_nodule_radius": 0.0,
1731
+ "bottom_hallhuray_surface_ratio": 0.0,
1732
+ "side_hallhuray_nodule_radius": 0.0,
1733
+ "side_hallhuray_surface_ratio": 0.0,
1734
+ "upper_elevation": 0.0,
1735
+ "lower_elevation": 0.0,
1736
+ "color": [242, 140, 102],
1737
+ }
1738
+ if layer:
1700
1739
  if "color" in layer:
1701
1740
  default_layer["color"] = layer["color"]
1702
1741
  elif not layer["type"] == "signal":
@@ -1704,20 +1743,16 @@ class Stackup(object):
1704
1743
 
1705
1744
  for k, v in layer.items():
1706
1745
  default_layer[k] = v
1707
-
1708
1746
  self.stackup_layers[name]._load_layer(default_layer)
1709
- else: # Remove layers not in config file.
1710
- self.remove_layer(name)
1711
-
1712
- for layer_name, layer in temp.items():
1747
+ for layer_name, layer in temp.items(): # looping over potential new layers to add
1713
1748
  if layer_name in self.stackup_layers:
1714
1749
  continue # if layer exist, skip
1715
-
1750
+ # adding layer
1716
1751
  default_layer = {
1717
1752
  "name": "default",
1718
1753
  "type": "signal",
1719
1754
  "material": "copper",
1720
- "dielectric_fill": "fr4_epoxy",
1755
+ "dielectric_fill": "FR4_epoxy",
1721
1756
  "thickness": 3.5e-05,
1722
1757
  "etch_factor": 0.0,
1723
1758
  "roughness_enabled": False,
@@ -1786,12 +1821,12 @@ class Stackup(object):
1786
1821
  return True
1787
1822
 
1788
1823
  @pyedb_function_handler()
1789
- def _import_json(self, file_path):
1824
+ def _import_json(self, file_path, rename=False):
1790
1825
  """Import stackup from a json file."""
1791
1826
  if file_path:
1792
1827
  f = open(file_path)
1793
1828
  json_dict = json.load(f) # pragma: no cover
1794
- return self._import_dict(json_dict)
1829
+ return self._import_dict(json_dict, rename)
1795
1830
 
1796
1831
  @pyedb_function_handler()
1797
1832
  def _import_csv(self, file_path):
@@ -2035,40 +2070,39 @@ class Stackup(object):
2035
2070
  material["Conductivity"] = val.conductivity
2036
2071
  else:
2037
2072
  material["Permittivity"] = val.permittivity
2038
- material["DielectricLossTangent"] = val.loss_tangent
2073
+ material["DielectricLossTangent"] = val.dielectric_loss_tangent
2039
2074
  materials[name] = material
2040
2075
 
2041
2076
  return layers, materials, roughness_models, non_stackup_layers
2042
2077
 
2043
2078
  @pyedb_function_handler()
2044
2079
  def _add_materials_from_dictionary(self, material_dict):
2045
- mat_keys = [i.lower() for i in self._pedb.materials.materials.keys()]
2046
- mat_keys_case = [i for i in self._pedb.materials.materials.keys()]
2047
- for name, attr in material_dict.items():
2048
- if not name.lower() in mat_keys:
2049
- if "Conductivity" in attr:
2050
- self._pedb.materials.add_conductor_material(name, attr["Conductivity"])
2080
+ materials = self.self._pedb.materials.materials
2081
+ for name, material_properties in material_dict.items():
2082
+ if not name in materials:
2083
+ if "Conductivity" in material_properties:
2084
+ materials.add_conductor_material(name, material_properties["Conductivity"])
2051
2085
  else:
2052
- self._pedb.materials.add_dielectric_material(
2086
+ materials.add_dielectric_material(
2053
2087
  name,
2054
- attr["Permittivity"],
2055
- attr["DielectricLossTangent"],
2088
+ material_properties["Permittivity"],
2089
+ material_properties["DielectricLossTangent"],
2056
2090
  )
2057
2091
  else:
2058
- local_material = self._pedb.materials[mat_keys_case[mat_keys.index(name.lower())]]
2059
- if "Conductivity" in attr:
2060
- local_material.conductivity = attr["Conductivity"]
2092
+ material = materials[name]
2093
+ if "Conductivity" in material_properties:
2094
+ material.conductivity = material_properties["Conductivity"]
2061
2095
  else:
2062
- local_material.permittivity = attr["Permittivity"]
2063
- local_material.loss_tanget = attr["DielectricLossTangent"]
2096
+ material.permittivity = material_properties["Permittivity"]
2097
+ material.loss_tanget = material_properties["DielectricLossTangent"]
2064
2098
  return True
2065
2099
 
2066
2100
  @pyedb_function_handler()
2067
- def _import_xml(self, file_path):
2068
- """Read external xml file and update stackup.
2069
- 1, all existing layers must exist in xml file.
2070
- 2, xml can have more layers than the existing stackup.
2071
- 3, if xml has different layer order, reorder the layers according to xml definition.
2101
+ def _import_xml(self, file_path, rename=False):
2102
+ """Read external xml file and convert into json file.
2103
+ You can use xml file to import layer stackup but using json file is recommended.
2104
+ see :class:`pyedb.dotnet.edb_core.edb_data.simulation_configuration.SimulationConfiguration´ class to
2105
+ generate files`.
2072
2106
 
2073
2107
  Parameters
2074
2108
  ----------
@@ -2080,60 +2114,42 @@ class Stackup(object):
2080
2114
  bool
2081
2115
  ``True`` when successful, ``False`` when failed.
2082
2116
  """
2117
+ if not colors:
2118
+ self._pedb.logger.error("Matplotlib is needed. Please, install it first.")
2119
+ return False
2083
2120
  tree = ET.parse(file_path)
2084
- material_dict = {}
2085
2121
  root = tree.getroot()
2086
2122
  stackup = root.find("Stackup")
2087
- for m in stackup.find("Materials").findall("Material"):
2088
- material = {}
2089
- for i in list(m):
2090
- material[i.tag] = list(i)[0].text
2091
- material_dict[m.attrib["Name"]] = material
2092
-
2093
- self._add_materials_from_dictionary(material_dict)
2094
-
2095
- lc_import = self._pedb.edb_api.Cell.LayerCollection()
2096
-
2097
- if not lc_import.ImportFromControlFile(file_path): # pragma: no cover
2098
- logger.error("Import xml failed. Please check xml content.")
2099
- return False
2100
-
2101
- if not len(self.stackup_layers):
2102
- self._pedb.layout.layer_collection = lc_import
2103
- self.refresh_layer_collection()
2104
- return True
2105
-
2106
- dumy_layers = OrderedDict()
2107
- for i in list(lc_import.Layers(self._pedb.edb_api.cell.layer_type_set.AllLayerSet)):
2108
- dumy_layers[i.GetName()] = i.Clone()
2109
-
2110
- for name in self.layers.keys():
2111
- if not name in dumy_layers:
2112
- logger.error("{} doesn't exist in xml".format(name))
2113
- return False
2114
-
2115
- for name, l in dumy_layers.items():
2116
- layer_type = re.sub(r"Layer$", "", l.GetLayerType().ToString()).lower()
2117
- if name in self.layers:
2118
- layer = self.layers[name]
2119
- layer.type = layer_type
2120
- else:
2121
- layer = self.add_layer(name, layer_type=layer_type, material="copper", fillMaterial="copper")
2122
-
2123
- if l.IsStackupLayer():
2124
- layer.material = l.GetMaterial()
2125
- layer.thickness = l.GetThicknessValue().ToDouble()
2126
- layer.dielectric_fill = l.GetFillMaterial()
2127
- layer.etch_factor = l.GetEtchFactor().ToDouble()
2128
-
2129
- lc_new = self._pedb.edb_api.Cell.LayerCollection()
2130
- for name, _ in dumy_layers.items():
2131
- layer = self.layers[name]
2132
- lc_new.AddLayerBottom(layer._edb_layer)
2133
-
2134
- self._pedb.layout.layer_collection = lc_new
2135
- self.refresh_layer_collection()
2136
- return True
2123
+ stackup_dict = {}
2124
+ if stackup.find("Materials"):
2125
+ stackup_dict["materials"] = {}
2126
+ for m in stackup.find("Materials").findall("Material"):
2127
+ material = {"name": m.attrib["Name"]}
2128
+ for i in list(m):
2129
+ material[i.tag.lower()] = float(list(i)[0].text)
2130
+ if material:
2131
+ stackup_dict["materials"][material["name"]] = material
2132
+ stackup_section = stackup.find("Layers")
2133
+ if stackup_section:
2134
+ length_unit = stackup_section.attrib["LengthUnit"]
2135
+ stackup_dict["layers"] = {}
2136
+ for l in stackup.find("Layers").findall("Layer"):
2137
+ layer = {"name": l.attrib["Name"]}
2138
+ for k, v in l.attrib.items():
2139
+ if k == "Color":
2140
+ layer[k.lower()] = [int(x * 255) for x in list(colors.to_rgb(v))]
2141
+ elif k == "Thickness":
2142
+ layer[k.lower()] = v + length_unit
2143
+ elif v == "conductor":
2144
+ layer[k.lower()] = "signal"
2145
+ elif k == "FillMaterial":
2146
+ layer["dielectric_fill"] = v
2147
+ else:
2148
+ layer[k.lower()] = v
2149
+ if layer:
2150
+ if layer["type"] == "signal" or layer["type"] == "dielectric":
2151
+ stackup_dict["layers"][layer["name"]] = layer
2152
+ return self._import_dict(stackup_dict, rename=rename)
2137
2153
 
2138
2154
  @pyedb_function_handler()
2139
2155
  def _export_xml(self, file_path):
@@ -2187,7 +2203,7 @@ class Stackup(object):
2187
2203
  return True
2188
2204
 
2189
2205
  @pyedb_function_handler()
2190
- def load(self, file_path):
2206
+ def load(self, file_path, rename=False):
2191
2207
  """Import stackup from a file. The file format can be XML, CSV, or JSON.
2192
2208
 
2193
2209
 
@@ -2195,6 +2211,11 @@ class Stackup(object):
2195
2211
  ----------
2196
2212
  file_path : str
2197
2213
  Path to stackup file.
2214
+ rename : bool
2215
+ If rename is ``False`` then layer in layout not found in the stackup file are deleted.
2216
+ Otherwise, if the number of layer in the stackup file equals the number of stackup layer
2217
+ in the layout, layers are renamed according the the file.
2218
+ Note that layer order matters, and has to be writtent from top to bottom layer in the file.
2198
2219
 
2199
2220
  Returns
2200
2221
  -------
@@ -2213,9 +2234,9 @@ class Stackup(object):
2213
2234
  elif file_path.endswith(".csv"):
2214
2235
  return self._import_csv(file_path)
2215
2236
  elif file_path.endswith(".json"):
2216
- return self._import_json(file_path)
2237
+ return self._import_json(file_path, rename=rename)
2217
2238
  elif file_path.endswith(".xml"):
2218
- return self._import_xml(file_path)
2239
+ return self._import_xml(file_path, rename=rename)
2219
2240
  else:
2220
2241
  return False
2221
2242
 
@@ -0,0 +1,3 @@
1
+ from pathlib import Path
2
+
3
+ workdir = Path(__file__).parent
@@ -0,0 +1,69 @@
1
+ class HeatSink:
2
+
3
+ """Heatsink model description.
4
+
5
+ Parameters
6
+ ----------
7
+ pedb : :class:`pyedb.dotnet.edb.Edb`
8
+ Inherited object.
9
+ edb_object : :class:`Ansys.Ansoft.Edb.Utility.HeatSink`,
10
+ """
11
+
12
+ def __init__(self, pedb, edb_object=None):
13
+ self._pedb = pedb
14
+ self._fin_orientation_type = {
15
+ "x_oriented": self._pedb.edb_api.utility.utility.HeatSinkFinOrientation.XOriented,
16
+ "y_oriented": self._pedb.edb_api.utility.utility.HeatSinkFinOrientation.YOriented,
17
+ "other_oriented": self._pedb.edb_api.utility.utility.HeatSinkFinOrientation.OtherOriented,
18
+ }
19
+
20
+ if edb_object:
21
+ self._edb_object = edb_object
22
+ else:
23
+ self._edb_object = self._pedb.edb_api.utility.utility.HeatSink()
24
+
25
+ @property
26
+ def fin_base_height(self):
27
+ """The base elevation of the fins."""
28
+ return self._edb_object.FinBaseHeight.ToDouble()
29
+
30
+ @fin_base_height.setter
31
+ def fin_base_height(self, value):
32
+ self._edb_object.FinBaseHeight = self._pedb.edb_value(value)
33
+
34
+ @property
35
+ def fin_height(self):
36
+ """The fin height."""
37
+ return self._edb_object.FinHeight.ToDouble()
38
+
39
+ @fin_height.setter
40
+ def fin_height(self, value):
41
+ self._edb_object.FinHeight = self._pedb.edb_value(value)
42
+
43
+ @property
44
+ def fin_orientation(self):
45
+ """The fin orientation."""
46
+ temp = self._edb_object.FinOrientation
47
+ return list(self._fin_orientation_type.keys())[list(self._fin_orientation_type.values()).index(temp)]
48
+
49
+ @fin_orientation.setter
50
+ def fin_orientation(self, value):
51
+ self._edb_object.FinOrientation = self._fin_orientation_type[value]
52
+
53
+ @property
54
+ def fin_spacing(self):
55
+ """The fin spacing."""
56
+ return self._edb_object.FinSpacing.ToDouble()
57
+
58
+ @fin_spacing.setter
59
+ def fin_spacing(self, value):
60
+ self._edb_object.FinSpacing = self._pedb.edb_value(value)
61
+
62
+ @property
63
+ def fin_thickness(self):
64
+ """The fin thickness."""
65
+ return self._edb_object.FinThickness.ToDouble()
66
+
67
+ @fin_thickness.setter
68
+ def fin_thickness(self, value):
69
+ self._edb_object.FinThickness = self._pedb.edb_value(value)
@@ -0,0 +1,46 @@
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
+
24
+ class SiwaveDCIRSettings:
25
+ """Class for DC IR settings."""
26
+
27
+ def __init__(self, parent):
28
+ self._parent = parent
29
+
30
+ @property
31
+ def export_dc_thermal_data(self):
32
+ """Export DC Thermal Data.
33
+
34
+ Returns
35
+ -------
36
+ bool
37
+ ``True`` when activated, ``False`` deactivated.
38
+ """
39
+ return self._parent.get_sim_setup_info.SimulationSettings.DCIRSettings.ExportDCThermalData
40
+
41
+ @export_dc_thermal_data.setter
42
+ def export_dc_thermal_data(self, value):
43
+ edb_setup_info = self._parent.get_sim_setup_info
44
+ edb_setup_info.SimulationSettings.DCIRSettings.ExportDCThermalData = value
45
+ self._parent._edb_object = self._parent._set_edb_setup_info(edb_setup_info)
46
+ self._parent._update_setup()
pyedb/edb_logger.py CHANGED
@@ -415,4 +415,18 @@ class EdbLogger(object):
415
415
  return self._global
416
416
 
417
417
 
418
- pyedb_logger = EdbLogger(to_stdout=settings.enable_screen_logs)
418
+ logger = logging.getLogger("Global")
419
+ if any("aedt_logger" in str(i) for i in logger.filters):
420
+ from pyaedt.generic.settings import settings as pyaedt_settings
421
+
422
+ from pyedb.generic.settings import settings as pyaedb_settings
423
+
424
+ pyedb_logger = pyaedt_settings.logger
425
+ pyaedb_settings.use_pyaedt_log = True
426
+ pyaedb_settings.logger = pyedb_logger
427
+
428
+ else:
429
+ pyedb_logger = EdbLogger(to_stdout=settings.enable_screen_logs)
430
+ from pyedb.generic.settings import settings as pyaedb_settings
431
+
432
+ pyaedb_settings.logger = pyedb_logger
pyedb/exceptions.py ADDED
@@ -0,0 +1,6 @@
1
+ """
2
+ """
3
+
4
+
5
+ class MaterialModelException(Exception):
6
+ """Exception triggered when handling material model."""
@@ -108,7 +108,7 @@ class Scratch:
108
108
 
109
109
  return dst_file
110
110
 
111
- def copyfolder(self, src_folder, destfolder):
111
+ def copyfolder(self, src_folder, destfolder=None):
112
112
  """
113
113
 
114
114
  Parameters
@@ -124,8 +124,12 @@ class Scratch:
124
124
  """
125
125
  from distutils.dir_util import copy_tree
126
126
 
127
- copy_tree(src_folder, destfolder)
128
- return True
127
+ if destfolder:
128
+ copy_tree(src_folder, destfolder)
129
+ else:
130
+ destfolder = os.path.join(self.path, os.path.split(src_folder)[-1])
131
+ copy_tree(src_folder, destfolder)
132
+ return destfolder
129
133
 
130
134
  def __enter__(self):
131
135
  return self
@@ -44,6 +44,7 @@ import tempfile
44
44
  import time
45
45
  import traceback
46
46
 
47
+ from pyedb.exceptions import MaterialModelException
47
48
  from pyedb.generic.constants import CSS4_COLORS
48
49
  from pyedb.generic.settings import settings
49
50
 
@@ -179,6 +180,9 @@ def _function_handler_wrapper(user_function): # pragma: no cover
179
180
  except IOError:
180
181
  _exception(sys.exc_info(), user_function, args, kwargs, "IO Error")
181
182
  return False
183
+ except MaterialModelException:
184
+ _exception(sys.exc_info(), user_function, args, kwargs, "Material Model")
185
+ return False
182
186
 
183
187
  return wrapper
184
188