pyedb 0.47.1__py3-none-any.whl → 0.48.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 (32) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_stackup.py +35 -1
  3. pyedb/configuration/configuration.py +13 -13
  4. pyedb/dotnet/database/cell/primitive/primitive.py +8 -1
  5. pyedb/dotnet/database/cell/terminal/terminal.py +22 -4
  6. pyedb/dotnet/database/components.py +22 -3
  7. pyedb/dotnet/database/dotnet/database.py +18 -0
  8. pyedb/dotnet/database/edb_data/padstacks_data.py +20 -0
  9. pyedb/dotnet/database/edb_data/ports.py +14 -0
  10. pyedb/dotnet/database/edb_data/utilities.py +1 -1
  11. pyedb/dotnet/database/geometry/polygon_data.py +1 -1
  12. pyedb/dotnet/database/hfss.py +11 -1
  13. pyedb/dotnet/database/materials.py +78 -0
  14. pyedb/dotnet/database/modeler.py +9 -5
  15. pyedb/dotnet/database/sim_setup_data/data/mesh_operation.py +24 -0
  16. pyedb/dotnet/database/siwave.py +1 -1
  17. pyedb/dotnet/database/utilities/simulation_setup.py +51 -9
  18. pyedb/dotnet/edb.py +67 -8
  19. pyedb/grpc/database/components.py +19 -13
  20. pyedb/grpc/database/hfss.py +3 -3
  21. pyedb/grpc/database/modeler.py +4 -4
  22. pyedb/grpc/database/padstacks.py +3 -1
  23. pyedb/grpc/database/ports/ports.py +4 -0
  24. pyedb/grpc/database/primitive/path.py +2 -2
  25. pyedb/grpc/database/primitive/primitive.py +6 -1
  26. pyedb/grpc/database/source_excitations.py +16 -8
  27. pyedb/grpc/database/terminal/bundle_terminal.py +1 -1
  28. pyedb/grpc/edb.py +125 -32
  29. {pyedb-0.47.1.dist-info → pyedb-0.48.0.dist-info}/METADATA +1 -1
  30. {pyedb-0.47.1.dist-info → pyedb-0.48.0.dist-info}/RECORD +32 -32
  31. {pyedb-0.47.1.dist-info → pyedb-0.48.0.dist-info}/LICENSE +0 -0
  32. {pyedb-0.47.1.dist-info → pyedb-0.48.0.dist-info}/WHEEL +0 -0
pyedb/dotnet/edb.py CHANGED
@@ -1451,13 +1451,28 @@ class Edb(Database):
1451
1451
  def close_edb(self):
1452
1452
  """Close EDB and cleanup variables.
1453
1453
 
1454
+ . deprecated:: pyedb 0.47.0
1455
+ Use: func:`close` instead.
1456
+
1457
+ Returns
1458
+ -------
1459
+ bool
1460
+ ``True`` when successful, ``False`` when failed.
1461
+
1462
+ """
1463
+ warnings.warn("Use new property :func:`close` instead.", DeprecationWarning)
1464
+ return self.close()
1465
+
1466
+ def close(self):
1467
+ """Close EDB and cleanup variables.
1468
+
1454
1469
  Returns
1455
1470
  -------
1456
1471
  bool
1457
1472
  ``True`` when successful, ``False`` when failed.
1458
1473
 
1459
1474
  """
1460
- self.close()
1475
+ Database.close(self)
1461
1476
 
1462
1477
  if self.log_name and settings.enable_local_log_file:
1463
1478
  self._logger.remove_all_file_loggers()
@@ -1471,25 +1486,62 @@ class Edb(Database):
1471
1486
  def save_edb(self):
1472
1487
  """Save the EDB file.
1473
1488
 
1489
+ . deprecated:: pyedb 0.47.0
1490
+ Use: func:`save` instead.
1491
+
1492
+ Returns
1493
+ -------
1494
+ bool
1495
+ ``True`` when successful, ``False`` when failed.
1496
+
1497
+ """
1498
+ warnings.warn("Use new method :func:`save` instead.", DeprecationWarning)
1499
+ return self.save()
1500
+
1501
+ def save(self):
1502
+ """Save the EDB file.
1503
+
1474
1504
  Returns
1475
1505
  -------
1476
1506
  bool
1477
1507
  ``True`` when successful, ``False`` when failed.
1478
1508
 
1479
1509
  """
1480
- self.save()
1510
+
1511
+ Database.save(self)
1481
1512
  start_time = time.time()
1482
1513
  self._wait_for_file_release()
1483
1514
  elapsed_time = time.time() - start_time
1484
1515
  self.logger.info("EDB file save time: {0:.2f}ms".format(elapsed_time * 1000.0))
1485
1516
  return True
1486
1517
 
1487
- def save_edb_as(self, fname):
1518
+ def save_edb_as(self, path):
1519
+ """Save the EDB file as another file.
1520
+
1521
+ . deprecated:: pyedb 0.47.0
1522
+ Use: func:`save_as` instead.
1523
+
1524
+
1525
+ Parameters
1526
+ ----------
1527
+ path : str
1528
+ Name of the new file to save to.
1529
+
1530
+ Returns
1531
+ -------
1532
+ bool
1533
+ ``True`` when successful, ``False`` when failed.
1534
+
1535
+ """
1536
+ warnings.warn("Use new property :func:`save_as` instead.", DeprecationWarning)
1537
+ return self.save_as(path)
1538
+
1539
+ def save_as(self, path, version=""):
1488
1540
  """Save the EDB file as another file.
1489
1541
 
1490
1542
  Parameters
1491
1543
  ----------
1492
- fname : str
1544
+ path : str
1493
1545
  Name of the new file to save to.
1494
1546
 
1495
1547
  Returns
@@ -1499,7 +1551,7 @@ class Edb(Database):
1499
1551
 
1500
1552
  """
1501
1553
  origin_name = "pyedb_" + os.path.splitext(os.path.split(self.edbpath)[-1])[0]
1502
- self.save_as(fname)
1554
+ Database.save_as(self, path)
1503
1555
  start_time = time.time()
1504
1556
  self._wait_for_file_release()
1505
1557
  elapsed_time = time.time() - start_time
@@ -1509,8 +1561,8 @@ class Edb(Database):
1509
1561
  self._logger.remove_file_logger(os.path.splitext(os.path.split(self.log_name)[-1])[0])
1510
1562
 
1511
1563
  self.log_name = os.path.join(
1512
- os.path.dirname(fname),
1513
- "pyedb_" + os.path.splitext(os.path.split(fname)[-1])[0] + ".log",
1564
+ os.path.dirname(path),
1565
+ "pyedb_" + os.path.splitext(os.path.split(path)[-1])[0] + ".log",
1514
1566
  )
1515
1567
  if settings.enable_local_log_file:
1516
1568
  self._logger.add_file_logger(self.log_name, "Edb")
@@ -1800,7 +1852,7 @@ class Edb(Database):
1800
1852
  output_aedb_path=None,
1801
1853
  open_cutout_at_end=True,
1802
1854
  use_pyaedt_cutout=True,
1803
- number_of_threads=4,
1855
+ number_of_threads=1,
1804
1856
  use_pyaedt_extent_computing=True,
1805
1857
  extent_defeature=0,
1806
1858
  remove_single_pin_components=False,
@@ -4668,3 +4720,10 @@ class Edb(Database):
4668
4720
  ET.indent(tree, space="\t", level=0)
4669
4721
  tree.write(control_path)
4670
4722
  return True if os.path.exists(control_path) else False
4723
+
4724
+ def get_variable_value(self, variable_name):
4725
+ """Added to get closer architecture as for grpc."""
4726
+ if variable_name in self.variables:
4727
+ return self.variables[variable_name].value
4728
+ else:
4729
+ return False
@@ -276,20 +276,26 @@ class Components(object):
276
276
  self._others = {}
277
277
  for i in self._pedb.layout.groups:
278
278
  self._cmp[i.name] = i
279
- if i.type == "resistor":
280
- self._res[i.name] = i
281
- elif i.type == "capacitor":
282
- self._cap[i.name] = i
283
- elif i.type == "inductor":
284
- self._ind[i.name] = i
285
- elif i.type == "ic":
286
- self._ics[i.name] = i
287
- elif i.type == "io":
288
- self._ios[i.name] = i
289
- elif i.type == "other":
279
+ try:
280
+ if i.type == "resistor":
281
+ self._res[i.name] = i
282
+ elif i.type == "capacitor":
283
+ self._cap[i.name] = i
284
+ elif i.type == "inductor":
285
+ self._ind[i.name] = i
286
+ elif i.type == "ic":
287
+ self._ics[i.name] = i
288
+ elif i.type == "io":
289
+ self._ios[i.name] = i
290
+ elif i.type == "other":
291
+ self._others[i.name] = i
292
+ else:
293
+ self._logger.warning(
294
+ f"Unknown component type {i.name} found while refreshing components, will ignore"
295
+ )
296
+ except:
297
+ self._logger.warning(f"Assigning component {i.name} as default type other.")
290
298
  self._others[i.name] = i
291
- else:
292
- self._logger.warning(f"Unknown component type {i.name} found while refreshing components, will ignore")
293
299
  return True
294
300
 
295
301
  @property
@@ -527,7 +527,7 @@ class Hfss(object):
527
527
  "`pyedb.grpc.core.excitations.create_differential_wave_port` instead.",
528
528
  DeprecationWarning,
529
529
  )
530
- return self._pedb.excitations.create_differential_wave_port(
530
+ return self._pedb.source_excitation.create_differential_wave_port(
531
531
  positive_primitive_id,
532
532
  positive_points_on_edge,
533
533
  negative_primitive_id,
@@ -579,7 +579,7 @@ class Hfss(object):
579
579
  "`pyedb.grpc.core.excitations.create_bundle_wave_port` instead.",
580
580
  DeprecationWarning,
581
581
  )
582
- self._pedb.excitations.create_bundle_wave_port(
582
+ return self._pedb.source_excitation.create_bundle_wave_port(
583
583
  primitives_id, points_on_edge, port_name, horizontal_extent_factor, vertical_extent_factor, pec_launch_width
584
584
  )
585
585
 
@@ -720,7 +720,7 @@ class Hfss(object):
720
720
  "`pyedb.grpc.core.excitations.create_source_on_component` instead.",
721
721
  DeprecationWarning,
722
722
  )
723
- self._pedb.source_excitation.create_wave_port(
723
+ return self._pedb.source_excitation.create_wave_port(
724
724
  prim_id,
725
725
  point_on_edge,
726
726
  port_name,
@@ -1272,7 +1272,7 @@ class Modeler(object):
1272
1272
  stat_model.num_resistors = len(self._pedb.components.resistors)
1273
1273
  stat_model.num_inductors = len(self._pedb.components.inductors)
1274
1274
  bbox = self._pedb._hfss.get_layout_bounding_box(self._active_layout)
1275
- stat_model._layout_size = bbox[2] - bbox[0], bbox[3] - bbox[1]
1275
+ stat_model._layout_size = round(bbox[2] - bbox[0], 6), round(bbox[3] - bbox[1], 6)
1276
1276
  stat_model.num_discrete_components = (
1277
1277
  len(self._pedb.components.Others) + len(self._pedb.components.ICs) + len(self._pedb.components.IOs)
1278
1278
  )
@@ -1283,7 +1283,7 @@ class Modeler(object):
1283
1283
  stat_model.num_traces = len(self._pedb.modeler.paths)
1284
1284
  stat_model.num_polygons = len(self._pedb.modeler.polygons)
1285
1285
  stat_model.num_vias = len(self._pedb.padstacks.instances)
1286
- stat_model.stackup_thickness = self._pedb.stackup.get_layout_thickness()
1286
+ stat_model.stackup_thickness = round(self._pedb.stackup.get_layout_thickness(), 6)
1287
1287
  if evaluate_area:
1288
1288
  outline_surface = stat_model.layout_size[0] * stat_model.layout_size[1]
1289
1289
  if net_list:
@@ -1298,8 +1298,8 @@ class Modeler(object):
1298
1298
  surface += Path(self._pedb, prim).length * prim.cast().width.value
1299
1299
  if prim.primitive_type.name == "POLYGON":
1300
1300
  surface += prim.polygon_data.area()
1301
- stat_model.occupying_surface[layer] = surface
1302
- stat_model.occupying_ratio[layer] = surface / outline_surface
1301
+ stat_model.occupying_surface[layer] = round(surface, 6)
1302
+ stat_model.occupying_ratio[layer] = round(surface / outline_surface, 6)
1303
1303
  return stat_model
1304
1304
 
1305
1305
  def create_bondwire(
@@ -506,7 +506,9 @@ class Padstacks(object):
506
506
  "`pyedb.grpc.core.excitations.create_coax_port` instead.",
507
507
  DeprecationWarning,
508
508
  )
509
- self._pedb.excitations.create_coax_port(self, padstackinstance, use_dot_separator=use_dot_separator, name=name)
509
+ self._pedb.source_excitation.create_coax_port(
510
+ self, padstackinstance, use_dot_separator=use_dot_separator, name=name
511
+ )
510
512
 
511
513
  def get_pin_from_component_and_net(self, refdes=None, netname=None):
512
514
  """Retrieve pins given a component's reference designator and net name.
@@ -108,6 +108,10 @@ class GapPort(EdgeTerminal):
108
108
  self._edb_object.port_post_processing_prop.renormalizion_z0[1],
109
109
  )
110
110
 
111
+ @property
112
+ def terminal_type(self):
113
+ return self._edb_object.terminal_type
114
+
111
115
 
112
116
  class CircuitPort(GapPort):
113
117
  """Manages gap port properties.
@@ -62,7 +62,7 @@ class Path(GrpcPath, Primitive):
62
62
  """
63
63
  center_line_arcs = self._edb_object.cast().center_line.arc_data
64
64
  path_length = 0.0
65
- for arc in center_line_arcs:
65
+ for arc in center_line_arcs[: int(len(center_line_arcs) / 2)]:
66
66
  path_length += arc.length
67
67
  end_cap_style = self.get_end_cap_style()
68
68
  if end_cap_style:
@@ -181,7 +181,7 @@ class Path(GrpcPath, Primitive):
181
181
  # )
182
182
  # else:
183
183
  return self._pedb.hfss.create_edge_port_vertical(
184
- self.id,
184
+ self.edb_uid,
185
185
  pos,
186
186
  name,
187
187
  50,
@@ -253,7 +253,12 @@ class Primitive(GrpcPrimitive):
253
253
 
254
254
  """
255
255
  bbox = self.cast().polygon_data.bbox()
256
- return [bbox[0].x.value, bbox[0].y.value, bbox[1].x.value, bbox[1].y.value]
256
+ return [
257
+ round(bbox[0].x.value, 6),
258
+ round(bbox[0].y.value, 6),
259
+ round(bbox[1].x.value, 6),
260
+ round(bbox[1].y.value, 6),
261
+ ]
257
262
 
258
263
  def convert_to_polygon(self):
259
264
  """Convert path to polygon.
@@ -353,6 +353,14 @@ class SourceExcitation:
353
353
  >>> port_type=SourceType.CoaxPort, do_pingroup=False, refnet="GND")
354
354
 
355
355
  """
356
+ if isinstance(port_type, int):
357
+ # Adding DotNet backward compatibility with SourceType
358
+ type_mapping = {0: "coax_port", 1: "circuit_port"}
359
+ if port_type in type_mapping:
360
+ port_type = type_mapping[port_type]
361
+ else:
362
+ self._logger.error(f"unsupported port type with method.")
363
+ return False
356
364
  if isinstance(component, str):
357
365
  component = self._pedb.components.instances[component]
358
366
  if not isinstance(net_list, list):
@@ -395,7 +403,7 @@ class SourceExcitation:
395
403
  "outside the component when not found if argument extend_reference_pins_outside_component is True."
396
404
  )
397
405
  return False
398
- pad_params = self._pedb.padstack.get_pad_parameters(pin=cmp_pins[0], layername=pin_layers[0], pad_type=0)
406
+ pad_params = self._pedb.padstacks.get_pad_parameters(pin=cmp_pins[0], layername=pin_layers[0], pad_type=0)
399
407
  if not pad_params[0] == 7:
400
408
  if not solder_balls_size: # pragma no cover
401
409
  sball_diam = min([GrpcValue(val).value for val in pad_params[1]])
@@ -431,7 +439,7 @@ class SourceExcitation:
431
439
  shape=sball_shape,
432
440
  )
433
441
  for pin in cmp_pins:
434
- self._pedb.padstack.create_coax_port(padstackinstance=pin, name=port_name)
442
+ self._pedb.source_excitation.create_coax_port(padstackinstance=pin, name=port_name)
435
443
 
436
444
  elif port_type == "circuit_port": # pragma no cover
437
445
  ref_pins = [p for p in list(component.pins.values()) if p.net_name in reference_net]
@@ -794,7 +802,7 @@ class SourceExcitation:
794
802
  port_name = generate_unique_name(port_name, n=2)
795
803
  self._logger.info("An existing port already has this same name. Renaming to {}.".format(port_name))
796
804
  PadstackInstanceTerminal.create(
797
- layout=self._pedb._active_layout,
805
+ layout=self._pedb.active_layout,
798
806
  name=port_name,
799
807
  padstack_instance=padstackinstance,
800
808
  layer=terminal_layer,
@@ -831,7 +839,7 @@ class SourceExcitation:
831
839
  terminal_name = generate_unique_name("Terminal_")
832
840
  if isinstance(point_on_edge, tuple):
833
841
  point_on_edge = GrpcPointData(point_on_edge)
834
- prim = [i for i in self._pedb.modeler.primitives if i.id == prim_id]
842
+ prim = [i for i in self._pedb.modeler.primitives if i.edb_uid == prim_id]
835
843
  if not prim:
836
844
  self._pedb.logger.error(f"No primitive found for ID {prim_id}")
837
845
  return False
@@ -1580,10 +1588,10 @@ class SourceExcitation:
1580
1588
  port_name = generate_unique_name("diff")
1581
1589
 
1582
1590
  if isinstance(positive_primitive_id, Primitive):
1583
- positive_primitive_id = positive_primitive_id.id
1591
+ positive_primitive_id = positive_primitive_id.edb_uid
1584
1592
 
1585
1593
  if isinstance(negative_primitive_id, Primitive):
1586
- negative_primitive_id = negative_primitive_id.id
1594
+ negative_primitive_id = negative_primitive_id.edb_uid
1587
1595
 
1588
1596
  _, pos_term = self.create_wave_port(
1589
1597
  positive_primitive_id,
@@ -1652,7 +1660,7 @@ class SourceExcitation:
1652
1660
  port_name = generate_unique_name("Terminal_")
1653
1661
 
1654
1662
  if isinstance(prim_id, Primitive):
1655
- prim_id = prim_id.id
1663
+ prim_id = prim_id.edb_uid
1656
1664
  pos_edge_term = self._create_edge_terminal(prim_id, point_on_edge, port_name)
1657
1665
  pos_edge_term.impedance = GrpcValue(impedance)
1658
1666
  wave_port = WavePort(self._pedb, pos_edge_term)
@@ -2027,7 +2035,7 @@ class SourceExcitation:
2027
2035
  port_name = generate_unique_name("bundle_port")
2028
2036
 
2029
2037
  if isinstance(primitives_id[0], Primitive):
2030
- primitives_id = [i.id for i in primitives_id]
2038
+ primitives_id = [i.edb_uid for i in primitives_id]
2031
2039
 
2032
2040
  terminals = []
2033
2041
  _port_name = port_name
@@ -46,7 +46,7 @@ class BundleTerminal(GrpcBundleTerminal):
46
46
  """
47
47
 
48
48
  def __init__(self, pedb, edb_object):
49
- super().__init__(edb_object)
49
+ super().__init__(edb_object.msg)
50
50
  self._pedb = pedb
51
51
  self._edb_object = edb_object
52
52
 
pyedb/grpc/edb.py CHANGED
@@ -35,6 +35,7 @@ import sys
35
35
  import tempfile
36
36
  import time
37
37
  import traceback
38
+ from typing import Union
38
39
  import warnings
39
40
  from zipfile import ZipFile as zpf
40
41
 
@@ -57,7 +58,7 @@ from pyedb.generic.general_methods import (
57
58
  from pyedb.generic.process import SiwaveSolve
58
59
  from pyedb.generic.settings import settings
59
60
  from pyedb.grpc.database.components import Components
60
- from pyedb.grpc.database.control_file import ControlFile, convert_technology_file
61
+ from pyedb.grpc.database.control_file import ControlFile
61
62
  from pyedb.grpc.database.definition.materials import Materials
62
63
  from pyedb.grpc.database.hfss import Hfss
63
64
  from pyedb.grpc.database.layout.layout import Layout
@@ -110,7 +111,7 @@ class Edb(EdbInit):
110
111
  edbpath : str, optional
111
112
  Full path to the ``aedb`` folder. The variable can also contain
112
113
  the path to a layout to import. Allowed formats are BRD, MCM,
113
- XML (IPC2581), GDS, and DXF. The default is ``None``.
114
+ XML (IPC2581), GDS, ODB++(TGZ and ZIP) and DXF. The default is ``None``.
114
115
  For GDS import, the Ansys control file (also XML) should have the same
115
116
  name as the GDS file. Only the file extension differs.
116
117
  cellname : str, optional
@@ -120,14 +121,25 @@ class Edb(EdbInit):
120
121
  owned by HFSS 3D Layout. The default is ``False``.
121
122
  edbversion : str, int, float, optional
122
123
  Version of EDB to use. The default is ``None``.
123
- Examples of input values are ``252``, ``25.2``,``2025.2``,``"2025.2"``.
124
+ Examples of input values are ``232``, ``23.2``, ``2023.2``, ``"2023.2"``.
124
125
  isaedtowned : bool, optional
125
126
  Whether to launch EDB from HFSS 3D Layout. The
126
127
  default is ``False``.
127
128
  oproject : optional
128
129
  Reference to the AEDT project object.
130
+ student_version : bool, optional
131
+ Whether to open the AEDT student version. The default is ``False.``
132
+ control_file : str, optional
133
+ Path to the XML file. The default is ``None``, in which case an attempt is made to find
134
+ the XML file in the same directory as the board file. To succeed, the XML file and board file
135
+ must have the same name. Only the extension differs.
136
+ map_file : str, optional
137
+ Layer map .map file.
129
138
  technology_file : str, optional
130
- Technology file full path to be converted to XML before importing or XML. Supported by GDS format only.
139
+ Full path to technology file to be converted to xml before importing or xml.
140
+ Supported by GDS format only.
141
+ layer_filter:str,optional
142
+ Layer filter .txt file.
131
143
  restart_rpc_server : bool, optional
132
144
  ``True`` RPC server is terminated and restarted. This will close all open EDB. RPC server is running on single
133
145
  instance loading all EDB, enabling this option should be used with caution but can be a solution to release
@@ -188,15 +200,19 @@ class Edb(EdbInit):
188
200
 
189
201
  def __init__(
190
202
  self,
191
- edbpath=None,
192
- cellname=None,
193
- isreadonly=False,
194
- edbversion=None,
195
- isaedtowned=False,
203
+ edbpath: Union[str, Path] = None,
204
+ cellname: str = None,
205
+ isreadonly: bool = False,
206
+ edbversion: str = None,
207
+ isaedtowned: bool = False,
196
208
  oproject=None,
197
209
  student_version: bool = False,
198
- use_ppe=False,
199
- technology_file=None,
210
+ use_ppe: bool = False,
211
+ control_file: str = None,
212
+ map_file: str = None,
213
+ technology_file: str = None,
214
+ layer_filter: str = None,
215
+ remove_existing_aedt: bool = False,
200
216
  restart_rpc_server=False,
201
217
  ):
202
218
  edbversion = get_string_version(edbversion)
@@ -247,14 +263,18 @@ class Edb(EdbInit):
247
263
  zipped_file.extractall(edbpath[:-4])
248
264
  self.logger.info("ODB++ unzipped successfully.")
249
265
  zipped_file.close()
250
- control_file = None
251
- if technology_file:
252
- if os.path.splitext(technology_file)[1] == ".xml":
253
- control_file = technology_file
254
- else:
255
- control_file = convert_technology_file(technology_file, edbversion=edbversion)
256
266
  self.logger.info("Translating ODB++ to EDB...")
257
- self.import_layout_pcb(edbpath[:-4], working_dir, use_ppe=use_ppe, control_file=control_file)
267
+ if not self.import_layout_file(
268
+ edbpath[:-4],
269
+ working_dir,
270
+ use_ppe=use_ppe,
271
+ control_file=control_file,
272
+ tech_file=technology_file,
273
+ layer_filter=layer_filter,
274
+ map_file=map_file,
275
+ ):
276
+ raise AttributeError("Translation was unsuccessful")
277
+ return False
258
278
  if settings.enable_local_log_file and self.log_name:
259
279
  self.logger.add_file_logger(self.log_name, "Edb")
260
280
  self.logger.info("EDB %s was created correctly from %s file.", self.edbpath, edbpath)
@@ -262,14 +282,17 @@ class Edb(EdbInit):
262
282
  elif edbpath[-3:] in ["brd", "mcm", "gds", "xml", "dxf", "tgz"]:
263
283
  self.edbpath = edbpath[:-4] + ".aedb"
264
284
  working_dir = os.path.dirname(edbpath)
265
- control_file = None
266
- if technology_file:
267
- if os.path.splitext(technology_file)[1] == ".xml":
268
- control_file = technology_file
269
- else:
270
- control_file = convert_technology_file(technology_file, edbversion=edbversion)
271
- self.import_layout_pcb(edbpath, working_dir, use_ppe=use_ppe, control_file=control_file)
272
- self.logger.info("EDB %s was created correctly from %s file.", self.edbpath, edbpath[-2:])
285
+ if not self.import_layout_file(
286
+ edbpath,
287
+ working_dir,
288
+ use_ppe=use_ppe,
289
+ control_file=control_file,
290
+ tech_file=technology_file,
291
+ layer_filter=layer_filter,
292
+ map_file=map_file,
293
+ ):
294
+ raise AttributeError("Translation was unsuccessful")
295
+ return False
273
296
  elif edbpath.endswith("edb.def"):
274
297
  self.edbpath = os.path.dirname(edbpath)
275
298
  self.open_edb(restart_rpc_server=restart_rpc_server)
@@ -638,10 +661,69 @@ class Edb(EdbInit):
638
661
  def import_layout_pcb(
639
662
  self,
640
663
  input_file,
641
- working_dir,
664
+ working_dir="",
665
+ anstranslator_full_path="",
666
+ use_ppe=False,
667
+ control_file=None,
668
+ map_file=None,
669
+ tech_file=None,
670
+ layer_filter=None,
671
+ ):
672
+ """Import a board file and generate an ``edb.def`` file in the working directory.
673
+
674
+ .. deprecated:: 0.42.0
675
+ Use :func:`import_layout_file` method instead.
676
+
677
+ This function supports all AEDT formats, including DXF, GDS, SML (IPC2581), BRD, MCM, SIP, ZIP and TGZ.
678
+
679
+ Parameters
680
+ ----------
681
+ input_file : str
682
+ Full path to the board file.
683
+ working_dir : str, optional
684
+ Directory in which to create the ``aedb`` folder. The name given to the AEDB file
685
+ is the same as the name of the board file.
686
+ anstranslator_full_path : str, optional
687
+ Full path to the Ansys translator. The default is ``""``.
688
+ use_ppe : bool
689
+ Whether to use the PPE License. The default is ``False``.
690
+ control_file : str, optional
691
+ Path to the XML file. The default is ``None``, in which case an attempt is made to find
692
+ the XML file in the same directory as the board file. To succeed, the XML file and board file
693
+ must have the same name. Only the extension differs.
694
+ tech_file : str, optional
695
+ Technology file. The file can be *.ircx, *.vlc.tech, or *.itf
696
+ map_file : str, optional
697
+ Layer map .map file.
698
+ layer_filter:str,optional
699
+ Layer filter .txt file.
700
+
701
+ Returns
702
+ -------
703
+ Full path to the AEDB file : str
704
+ """
705
+ self.logger.warning("import_layout_pcb method is deprecated, use import_layout_file instead.")
706
+ return self.import_layout_file(
707
+ input_file,
708
+ working_dir,
709
+ anstranslator_full_path,
710
+ use_ppe,
711
+ control_file,
712
+ map_file,
713
+ tech_file,
714
+ layer_filter,
715
+ )
716
+
717
+ def import_layout_file(
718
+ self,
719
+ input_file,
720
+ working_dir="",
642
721
  anstranslator_full_path="",
643
722
  use_ppe=False,
644
723
  control_file=None,
724
+ map_file=None,
725
+ tech_file=None,
726
+ layer_filter=None,
645
727
  ):
646
728
  """Import a board file and generate an ``edb.def`` file in the working directory.
647
729
 
@@ -651,7 +733,7 @@ class Edb(EdbInit):
651
733
  ----------
652
734
  input_file : str
653
735
  Full path to the board file.
654
- working_dir : str
736
+ working_dir : str, optional
655
737
  Directory in which to create the ``aedb`` folder. The name given to the AEDB file
656
738
  is the same as the name of the board file.
657
739
  anstranslator_full_path : str, optional
@@ -662,10 +744,16 @@ class Edb(EdbInit):
662
744
  Path to the XML file. The default is ``None``, in which case an attempt is made to find
663
745
  the XML file in the same directory as the board file. To succeed, the XML file and board file
664
746
  must have the same name. Only the extension differs.
747
+ tech_file : str, optional
748
+ Technology file. The file can be *.ircx, *.vlc.tech, or *.itf
749
+ map_file : str, optional
750
+ Layer map .map file.
751
+ layer_filter:str,optional
752
+ Layer filter .txt file.
665
753
 
666
754
  Returns
667
755
  -------
668
- str: Full path to the AEDB file.
756
+ Full path to the AEDB file : str
669
757
 
670
758
  """
671
759
  self._components = None
@@ -693,13 +781,18 @@ class Edb(EdbInit):
693
781
  ]
694
782
  if not use_ppe:
695
783
  cmd_translator.append("-ppe=false")
696
- if control_file and input_file[-3:] not in ["brd", "mcm"]:
784
+ if control_file and input_file[-3:] not in ["brd", "mcm", "sip"]:
697
785
  if is_linux:
698
786
  cmd_translator.append("-c={}".format(control_file))
699
787
  else:
700
788
  cmd_translator.append('-c="{}"'.format(control_file))
701
- p = subprocess.Popen(cmd_translator)
702
- p.wait()
789
+ if map_file:
790
+ cmd_translator.append('-g="{}"'.format(map_file))
791
+ if tech_file:
792
+ cmd_translator.append('-t="{}"'.format(tech_file))
793
+ if layer_filter:
794
+ cmd_translator.append('-f="{}"'.format(layer_filter))
795
+ subprocess.run(cmd_translator)
703
796
  if not os.path.exists(os.path.join(working_dir, aedb_name)):
704
797
  self.logger.error("Translator failed to translate.")
705
798
  return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyedb
3
- Version: 0.47.1
3
+ Version: 0.48.0
4
4
  Summary: Higher-Level Pythonic Ansys Electronics Data Base
5
5
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
6
6
  Maintainer-email: PyEDB developers <simon.vandenbrouck@ansys.com>