pyedb 0.56.0__py3-none-any.whl → 0.58.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.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_data.py +3 -0
- pyedb/configuration/cfg_pin_groups.py +2 -0
- pyedb/configuration/cfg_terminals.py +232 -0
- pyedb/configuration/configuration.py +146 -3
- pyedb/dotnet/clr_module.py +1 -2
- pyedb/dotnet/database/Variables.py +30 -22
- pyedb/dotnet/database/cell/hierarchy/component.py +2 -8
- pyedb/dotnet/database/cell/layout.py +5 -1
- pyedb/dotnet/database/cell/primitive/primitive.py +2 -2
- pyedb/dotnet/database/cell/terminal/bundle_terminal.py +12 -0
- pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
- pyedb/dotnet/database/cell/terminal/terminal.py +38 -0
- pyedb/dotnet/database/components.py +15 -19
- pyedb/dotnet/database/dotnet/database.py +1 -0
- pyedb/dotnet/database/edb_data/control_file.py +19 -8
- pyedb/dotnet/database/edb_data/nets_data.py +3 -3
- pyedb/dotnet/database/edb_data/padstacks_data.py +39 -14
- pyedb/dotnet/database/edb_data/ports.py +0 -25
- pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
- pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +18 -19
- pyedb/dotnet/database/edb_data/simulation_configuration.py +3 -3
- pyedb/dotnet/database/edb_data/sources.py +21 -2
- pyedb/dotnet/database/general.py +1 -6
- pyedb/dotnet/database/hfss.py +9 -8
- pyedb/dotnet/database/layout_validation.py +14 -3
- pyedb/dotnet/database/materials.py +1 -3
- pyedb/dotnet/database/modeler.py +7 -3
- pyedb/dotnet/database/nets.py +27 -19
- pyedb/dotnet/database/padstack.py +4 -2
- pyedb/dotnet/database/sim_setup_data/io/siwave.py +54 -1
- pyedb/dotnet/database/siwave.py +4 -3
- pyedb/dotnet/database/stackup.py +55 -58
- pyedb/dotnet/database/utilities/heatsink.py +0 -1
- pyedb/dotnet/database/utilities/hfss_simulation_setup.py +81 -0
- pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
- pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
- pyedb/dotnet/database/utilities/siwave_simulation_setup.py +264 -13
- pyedb/dotnet/edb.py +65 -47
- pyedb/exceptions.py +1 -2
- pyedb/extensions/create_cell_array.py +67 -49
- pyedb/generic/data_handlers.py +13 -23
- pyedb/generic/design_types.py +9 -35
- pyedb/generic/filesystem.py +4 -2
- pyedb/generic/general_methods.py +28 -41
- pyedb/generic/plot.py +8 -23
- pyedb/generic/process.py +78 -10
- pyedb/grpc/database/_typing.py +0 -0
- pyedb/grpc/database/components.py +14 -13
- pyedb/grpc/database/control_file.py +27 -40
- pyedb/grpc/database/definition/materials.py +1 -1
- pyedb/grpc/database/definition/package_def.py +6 -3
- pyedb/grpc/database/definition/padstack_def.py +14 -12
- pyedb/grpc/database/hfss.py +1 -4
- pyedb/grpc/database/hierarchy/component.py +5 -13
- pyedb/grpc/database/hierarchy/pingroup.py +16 -3
- pyedb/grpc/database/layers/layer.py +1 -2
- pyedb/grpc/database/layers/stackup_layer.py +42 -19
- pyedb/grpc/database/layout/layout.py +43 -27
- pyedb/grpc/database/layout/voltage_regulator.py +6 -1
- pyedb/grpc/database/layout_validation.py +5 -2
- pyedb/grpc/database/modeler.py +254 -252
- pyedb/grpc/database/net/differential_pair.py +9 -2
- pyedb/grpc/database/net/extended_net.py +24 -9
- pyedb/grpc/database/net/net.py +14 -5
- pyedb/grpc/database/net/net_class.py +24 -7
- pyedb/grpc/database/nets.py +11 -43
- pyedb/grpc/database/padstacks.py +67 -119
- pyedb/grpc/database/primitive/bondwire.py +3 -67
- pyedb/grpc/database/primitive/circle.py +42 -3
- pyedb/grpc/database/primitive/padstack_instance.py +58 -31
- pyedb/grpc/database/primitive/path.py +160 -11
- pyedb/grpc/database/primitive/polygon.py +73 -7
- pyedb/grpc/database/primitive/primitive.py +2 -2
- pyedb/grpc/database/primitive/rectangle.py +105 -4
- pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
- pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
- pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +79 -0
- pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +1 -0
- pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
- pyedb/grpc/database/siwave.py +6 -13
- pyedb/grpc/database/source_excitations.py +46 -63
- pyedb/grpc/database/stackup.py +55 -60
- pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
- pyedb/grpc/database/terminal/padstack_instance_terminal.py +9 -11
- pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
- pyedb/grpc/database/terminal/point_terminal.py +30 -0
- pyedb/grpc/database/terminal/terminal.py +35 -10
- pyedb/grpc/database/utility/heat_sink.py +0 -1
- pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
- pyedb/grpc/database/utility/xml_control_file.py +19 -8
- pyedb/grpc/edb.py +63 -32
- pyedb/grpc/edb_init.py +1 -0
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
- pyedb/ipc2581/ecad/cad_data/step.py +1 -1
- pyedb/ipc2581/ipc2581.py +8 -7
- pyedb/libraries/common.py +3 -4
- pyedb/libraries/rf_libraries/base_functions.py +7 -16
- pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
- pyedb/misc/aedtlib_personalib_install.py +2 -2
- pyedb/misc/downloads.py +19 -3
- pyedb/misc/misc.py +5 -2
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +3 -2
- pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +0 -1
- pyedb/misc/utilities.py +0 -1
- pyedb/modeler/geometry_operators.py +3 -2
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/METADATA +6 -7
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/RECORD +110 -108
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/WHEEL +0 -0
- {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/licenses/LICENSE +0 -0
pyedb/grpc/edb.py
CHANGED
|
@@ -60,7 +60,7 @@ from itertools import combinations
|
|
|
60
60
|
import os
|
|
61
61
|
import re
|
|
62
62
|
import shutil
|
|
63
|
-
import subprocess
|
|
63
|
+
import subprocess # nosec B404
|
|
64
64
|
import sys
|
|
65
65
|
import tempfile
|
|
66
66
|
import time
|
|
@@ -658,8 +658,7 @@ class Edb(EdbInit):
|
|
|
658
658
|
bool
|
|
659
659
|
True if successful, False otherwise.
|
|
660
660
|
"""
|
|
661
|
-
from ansys.edb.core.layout.cell import Cell as GrpcCell
|
|
662
|
-
from ansys.edb.core.layout.cell import CellType as GrpcCellType
|
|
661
|
+
from ansys.edb.core.layout.cell import Cell as GrpcCell, CellType as GrpcCellType
|
|
663
662
|
|
|
664
663
|
self.standalone = self.standalone
|
|
665
664
|
n_try = 10
|
|
@@ -762,6 +761,11 @@ class Edb(EdbInit):
|
|
|
762
761
|
|
|
763
762
|
This function supports all AEDT formats, including DXF, GDS, SML (IPC2581), BRD, MCM, SIP, ZIP and TGZ.
|
|
764
763
|
|
|
764
|
+
.. warning::
|
|
765
|
+
Do not execute this function with untrusted function argument, environment
|
|
766
|
+
variables or pyedb global settings.
|
|
767
|
+
See the :ref:`security guide<ref_security_consideration>` for details.
|
|
768
|
+
|
|
765
769
|
Parameters
|
|
766
770
|
----------
|
|
767
771
|
input_file : str
|
|
@@ -804,16 +808,16 @@ class Edb(EdbInit):
|
|
|
804
808
|
self._nets = None
|
|
805
809
|
aedb_name = os.path.splitext(os.path.basename(input_file))[0] + ".aedb"
|
|
806
810
|
if anstranslator_full_path and os.path.exists(anstranslator_full_path):
|
|
807
|
-
|
|
811
|
+
executable_path = anstranslator_full_path
|
|
808
812
|
else:
|
|
809
|
-
|
|
813
|
+
executable_path = os.path.join(self.base_path, "anstranslator")
|
|
810
814
|
if is_windows:
|
|
811
|
-
|
|
815
|
+
executable_path += ".exe"
|
|
812
816
|
|
|
813
817
|
if not working_dir:
|
|
814
818
|
working_dir = os.path.dirname(input_file)
|
|
815
819
|
cmd_translator = [
|
|
816
|
-
|
|
820
|
+
executable_path,
|
|
817
821
|
input_file,
|
|
818
822
|
os.path.join(working_dir, aedb_name),
|
|
819
823
|
"-l={}".format(os.path.join(working_dir, "Translator.log")),
|
|
@@ -831,7 +835,10 @@ class Edb(EdbInit):
|
|
|
831
835
|
cmd_translator.append('-t="{}"'.format(tech_file))
|
|
832
836
|
if layer_filter:
|
|
833
837
|
cmd_translator.append('-f="{}"'.format(layer_filter))
|
|
834
|
-
|
|
838
|
+
try:
|
|
839
|
+
subprocess.run(cmd_translator, check=True) # nosec
|
|
840
|
+
except subprocess.CalledProcessError as e: # nosec
|
|
841
|
+
raise RuntimeError("An error occurred while translating board file to ``edb.def`` file") from e
|
|
835
842
|
if not os.path.exists(os.path.join(working_dir, aedb_name)):
|
|
836
843
|
self.logger.error("Translator failed to translate.")
|
|
837
844
|
return False
|
|
@@ -1191,7 +1198,7 @@ class Edb(EdbInit):
|
|
|
1191
1198
|
continue
|
|
1192
1199
|
except:
|
|
1193
1200
|
self.logger.warning(
|
|
1194
|
-
f"Failed to find connected objects on layout_obj
|
|
1201
|
+
f"Failed to find connected objects on layout_obj {layout_object_instance.layout_obj.id}, skipping."
|
|
1195
1202
|
)
|
|
1196
1203
|
pass
|
|
1197
1204
|
return temp
|
|
@@ -1341,6 +1348,11 @@ class Edb(EdbInit):
|
|
|
1341
1348
|
):
|
|
1342
1349
|
"""Import GDS file.
|
|
1343
1350
|
|
|
1351
|
+
.. warning::
|
|
1352
|
+
Do not execute this function with untrusted function argument, environment
|
|
1353
|
+
variables or pyedb global settings.
|
|
1354
|
+
See the :ref:`security guide<ref_security_consideration>` for details.
|
|
1355
|
+
|
|
1344
1356
|
Parameters
|
|
1345
1357
|
----------
|
|
1346
1358
|
inputGDS : str
|
|
@@ -1399,14 +1411,17 @@ class Edb(EdbInit):
|
|
|
1399
1411
|
command = [
|
|
1400
1412
|
anstranslator_full_path,
|
|
1401
1413
|
inputGDS,
|
|
1402
|
-
f'-o="{control_file_temp}"
|
|
1414
|
+
f'-o="{control_file_temp}"-t="{tech_file}"',
|
|
1403
1415
|
f'-g="{map_file}"',
|
|
1404
1416
|
f'-f="{layer_filter}"',
|
|
1405
1417
|
]
|
|
1406
1418
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1419
|
+
try:
|
|
1420
|
+
result = subprocess.run(command, capture_output=True, text=True, check=True) # nosec
|
|
1421
|
+
print(result.stdout)
|
|
1422
|
+
print(command)
|
|
1423
|
+
except subprocess.CalledProcessError as e: # nosec
|
|
1424
|
+
raise RuntimeError("An error occurred while converting file") from e
|
|
1410
1425
|
temp_inputGDS = inputGDS.split(".gds")[0]
|
|
1411
1426
|
self.edbpath = temp_inputGDS + ".aedb"
|
|
1412
1427
|
return self.open()
|
|
@@ -1568,8 +1583,11 @@ class Edb(EdbInit):
|
|
|
1568
1583
|
voids_poly.append(void_polydata)
|
|
1569
1584
|
if voids_poly:
|
|
1570
1585
|
obj_data = obj_data[0].subtract(list(obj_data), voids_poly)
|
|
1571
|
-
except:
|
|
1572
|
-
|
|
1586
|
+
except Exception as e:
|
|
1587
|
+
self.logger.error(
|
|
1588
|
+
f"A(n) {type(e).__name__} error occurred in method _create_conformal of "
|
|
1589
|
+
f"class Edb at iteration {k} for data {i}: {str(e)}"
|
|
1590
|
+
)
|
|
1573
1591
|
finally:
|
|
1574
1592
|
unite_polys.extend(list(obj_data))
|
|
1575
1593
|
_poly_unite = GrpcPolygonData.unite(unite_polys)
|
|
@@ -1734,7 +1752,7 @@ class Edb(EdbInit):
|
|
|
1734
1752
|
>>> # Create a basic cutout:
|
|
1735
1753
|
>>> edb.cutout(signal_list=["Net1"], reference_list=["GND"])
|
|
1736
1754
|
>>> # Create cutout with custom polygon:
|
|
1737
|
-
>>> custom_poly = [[0,0], [10e-3,0], [10e-3,10e-3], [0,10e-3]]
|
|
1755
|
+
>>> custom_poly = [[0, 0], [10e-3, 0], [10e-3, 10e-3], [0, 10e-3]]
|
|
1738
1756
|
>>> edb.cutout(custom_extent=custom_poly)
|
|
1739
1757
|
"""
|
|
1740
1758
|
if expansion_factor > 0:
|
|
@@ -1940,8 +1958,8 @@ class Edb(EdbInit):
|
|
|
1940
1958
|
if os.path.exists(source) and not os.path.exists(target):
|
|
1941
1959
|
try:
|
|
1942
1960
|
shutil.copy(source, target)
|
|
1943
|
-
except:
|
|
1944
|
-
|
|
1961
|
+
except Exception as e:
|
|
1962
|
+
self.logger.error(f"Failed to copy {source} to {target} - {type(e).__name__}: {str(e)}")
|
|
1945
1963
|
elif open_cutout_at_end:
|
|
1946
1964
|
self._active_cell = _cutout
|
|
1947
1965
|
self._init_objects()
|
|
@@ -2419,8 +2437,8 @@ class Edb(EdbInit):
|
|
|
2419
2437
|
try:
|
|
2420
2438
|
shutil.copy(source, target)
|
|
2421
2439
|
self.logger.warning("aedb def file manually created.")
|
|
2422
|
-
except:
|
|
2423
|
-
|
|
2440
|
+
except Exception as e:
|
|
2441
|
+
self.logger.error(f"Failed to copy {source} to {target} - {type(e).__name__}: {str(e)}")
|
|
2424
2442
|
return [[Value(pt.x), Value(pt.y)] for pt in polygon_data.without_arcs().points]
|
|
2425
2443
|
|
|
2426
2444
|
@staticmethod
|
|
@@ -2599,8 +2617,10 @@ class Edb(EdbInit):
|
|
|
2599
2617
|
process = SiwaveSolve(self)
|
|
2600
2618
|
try:
|
|
2601
2619
|
self.close()
|
|
2602
|
-
except:
|
|
2603
|
-
|
|
2620
|
+
except Exception as e:
|
|
2621
|
+
self.logger.warning(
|
|
2622
|
+
f"A(n) {type(e).__name__} error occurred while attempting to close the database {self}: {str(e)}"
|
|
2623
|
+
)
|
|
2604
2624
|
process.solve()
|
|
2605
2625
|
return self.edbpath[:-5] + ".siw"
|
|
2606
2626
|
|
|
@@ -2650,8 +2670,10 @@ class Edb(EdbInit):
|
|
|
2650
2670
|
process = SiwaveSolve(self)
|
|
2651
2671
|
try:
|
|
2652
2672
|
self.close()
|
|
2653
|
-
except:
|
|
2654
|
-
|
|
2673
|
+
except Exception as e:
|
|
2674
|
+
self.logger.warning(
|
|
2675
|
+
f"A(n) {type(e).__name__} error occurred while attempting to close the database {self}: {str(e)}"
|
|
2676
|
+
)
|
|
2655
2677
|
return process.export_dc_report(
|
|
2656
2678
|
siwave_project,
|
|
2657
2679
|
solution_name,
|
|
@@ -3009,7 +3031,7 @@ class Edb(EdbInit):
|
|
|
3009
3031
|
Use :func:`pyedb.grpc.core.hfss.add_setup` instead.
|
|
3010
3032
|
"""
|
|
3011
3033
|
warnings.warn(
|
|
3012
|
-
"`create_hfss_setup` is deprecated and is now located here
|
|
3034
|
+
"`create_hfss_setup` is deprecated and is now located here `pyedb.grpc.core.hfss.add_setup` instead.",
|
|
3013
3035
|
DeprecationWarning,
|
|
3014
3036
|
)
|
|
3015
3037
|
return self._hfss.add_setup(
|
|
@@ -3757,8 +3779,7 @@ class Edb(EdbInit):
|
|
|
3757
3779
|
]
|
|
3758
3780
|
if not polys:
|
|
3759
3781
|
self.logger.error(
|
|
3760
|
-
f"No polygon found with voids on layer {reference_layer} during model creation for "
|
|
3761
|
-
f"arbitrary wave ports"
|
|
3782
|
+
f"No polygon found with voids on layer {reference_layer} during model creation for arbitrary wave ports"
|
|
3762
3783
|
)
|
|
3763
3784
|
return False
|
|
3764
3785
|
void_padstacks = []
|
|
@@ -3771,7 +3792,7 @@ class Edb(EdbInit):
|
|
|
3771
3792
|
|
|
3772
3793
|
if not void_padstacks:
|
|
3773
3794
|
self.logger.error(
|
|
3774
|
-
"No padstack instances found inside evaluated voids during model creation for arbitrary
|
|
3795
|
+
"No padstack instances found inside evaluated voids during model creation for arbitrary waveports"
|
|
3775
3796
|
)
|
|
3776
3797
|
return False
|
|
3777
3798
|
cloned_edb = Edb(edbpath=output_edb, edbversion=self.edbversion, restart_rpc_server=True)
|
|
@@ -3903,6 +3924,11 @@ class Edb(EdbInit):
|
|
|
3903
3924
|
def compare(self, input_file, results=""):
|
|
3904
3925
|
"""Compares current open database with another one.
|
|
3905
3926
|
|
|
3927
|
+
.. warning::
|
|
3928
|
+
Do not execute this function with untrusted function argument, environment
|
|
3929
|
+
variables or pyedb global settings.
|
|
3930
|
+
See the :ref:`security guide<ref_security_consideration>` for details.
|
|
3931
|
+
|
|
3906
3932
|
Parameters
|
|
3907
3933
|
----------
|
|
3908
3934
|
input_file : str
|
|
@@ -3919,13 +3945,18 @@ class Edb(EdbInit):
|
|
|
3919
3945
|
if not results:
|
|
3920
3946
|
results = self.edbpath[:-5] + "_compare_results"
|
|
3921
3947
|
os.mkdir(results)
|
|
3922
|
-
|
|
3948
|
+
executable_path = os.path.join(self.base_path, "EDBDiff.exe")
|
|
3923
3949
|
if is_linux:
|
|
3924
3950
|
mono_path = os.path.join(self.base_path, "common/mono/Linux64/bin/mono")
|
|
3925
|
-
|
|
3951
|
+
command = [mono_path, executable_path, input_file, self.edbpath, results]
|
|
3926
3952
|
else:
|
|
3927
|
-
|
|
3928
|
-
|
|
3953
|
+
command = [executable_path, input_file, self.edbpath, results]
|
|
3954
|
+
try:
|
|
3955
|
+
subprocess.run(command, check=True) # nosec
|
|
3956
|
+
except subprocess.CalledProcessError as e: # nosec
|
|
3957
|
+
raise RuntimeError(
|
|
3958
|
+
"EDBDiff.exe execution failed. Please check if the executable is present in the base path."
|
|
3959
|
+
)
|
|
3929
3960
|
|
|
3930
3961
|
if not os.path.exists(os.path.join(results, "EDBDiff.csv")):
|
|
3931
3962
|
self.logger.error("Comparison execution failed")
|
pyedb/grpc/edb_init.py
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
import math
|
|
24
24
|
|
|
25
25
|
from pyedb.generic.general_methods import ET
|
|
26
|
+
from pyedb.generic.settings import settings
|
|
26
27
|
from pyedb.ipc2581.ecad.cad_data.feature import Feature, FeatureType
|
|
27
28
|
|
|
28
29
|
|
|
@@ -99,8 +100,11 @@ class LayerFeature(object):
|
|
|
99
100
|
)
|
|
100
101
|
)
|
|
101
102
|
self.features.append(feature)
|
|
102
|
-
except:
|
|
103
|
-
|
|
103
|
+
except Exception as e:
|
|
104
|
+
settings.logger.warning(
|
|
105
|
+
f"A(n) {type(e).__name__} error occurred while attempting to append IPC2581 "
|
|
106
|
+
f"feature {feature} to features of object {self}: {str(e)}"
|
|
107
|
+
)
|
|
104
108
|
|
|
105
109
|
def add_drill_feature(self, via, diameter=0.0): # pragma no cover
|
|
106
110
|
feature = Feature(self._ipc, self._pedb)
|
|
@@ -262,7 +262,7 @@ class Step(object):
|
|
|
262
262
|
start_layer, stop_layer = padstack_instance.get_layer_range()
|
|
263
263
|
for layer_name in self.layer_ranges(start_layer, stop_layer):
|
|
264
264
|
if layer_name not in layers:
|
|
265
|
-
layer_feature = LayerFeature(self._ipc)
|
|
265
|
+
layer_feature = LayerFeature(self._ipc, self._pedb)
|
|
266
266
|
layer_feature.layer_name = layer_name
|
|
267
267
|
# layer_feature.color = self._ipc._pedb.stackup[layer_name].color
|
|
268
268
|
layer_feature.color = layer_colors[layer_name]
|
pyedb/ipc2581/ipc2581.py
CHANGED
|
@@ -89,9 +89,9 @@ class Ipc2581(object):
|
|
|
89
89
|
self.from_meter_to_units(pad.parameters_values[0], self.units)
|
|
90
90
|
)
|
|
91
91
|
if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
|
|
92
|
-
self.content.standard_geometries_dict.standard_circ_dict[
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
self.content.standard_geometries_dict.standard_circ_dict[primitive_ref] = (
|
|
93
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units)
|
|
94
|
+
)
|
|
95
95
|
elif pad.geometry_type == 2:
|
|
96
96
|
primitive_ref = "RECT_{}_{}".format(
|
|
97
97
|
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
@@ -135,9 +135,9 @@ class Ipc2581(object):
|
|
|
135
135
|
self.from_meter_to_units(antipad.parameters_values[0], self.units)
|
|
136
136
|
)
|
|
137
137
|
if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
|
|
138
|
-
self.content.standard_geometries_dict.standard_circ_dict[
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
self.content.standard_geometries_dict.standard_circ_dict[primitive_ref] = (
|
|
139
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units)
|
|
140
|
+
)
|
|
141
141
|
elif antipad.geometry_type == 2:
|
|
142
142
|
primitive_ref = "RECT_{}_{}".format(
|
|
143
143
|
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
@@ -336,7 +336,8 @@ class Ipc2581(object):
|
|
|
336
336
|
padstack_defs = {i: k for i, k in self._pedb.padstacks.definitions.items()}
|
|
337
337
|
polys = {i: j for i, j in self._pedb.modeler.primitives_by_layer.items()}
|
|
338
338
|
for layer_name, layer in layers.items():
|
|
339
|
-
|
|
339
|
+
if layer_name in polys:
|
|
340
|
+
self.ecad.cad_data.cad_data_step.add_layer_feature(layer, polys[layer_name])
|
|
340
341
|
self.ecad.cad_data.cad_data_step.add_padstack_instances(padstack_instances, padstack_defs)
|
|
341
342
|
|
|
342
343
|
def add_drills(self):
|
pyedb/libraries/common.py
CHANGED
|
@@ -45,8 +45,7 @@ class Substrate:
|
|
|
45
45
|
|
|
46
46
|
Examples
|
|
47
47
|
--------
|
|
48
|
-
>>> sub = Substrate(h=1.6e-3, er=4.4, tan_d=0.02,
|
|
49
|
-
... name="FR4", size=(10e-3, 15e-3))
|
|
48
|
+
>>> sub = Substrate(h=1.6e-3, er=4.4, tan_d=0.02, name="FR4", size=(10e-3, 15e-3))
|
|
50
49
|
>>> sub.h
|
|
51
50
|
0.0016
|
|
52
51
|
"""
|
|
@@ -84,7 +83,7 @@ class Material:
|
|
|
84
83
|
>>> m = Material(edb, "MyMaterial")
|
|
85
84
|
>>> m.name
|
|
86
85
|
'MyMaterial'
|
|
87
|
-
>>> edb.materials["MyMaterial"]
|
|
86
|
+
>>> edb.materials["MyMaterial"] # now exists in the database
|
|
88
87
|
<Material object at ...>
|
|
89
88
|
"""
|
|
90
89
|
|
|
@@ -125,7 +124,7 @@ class Conductor(Material):
|
|
|
125
124
|
>>> cu = Conductor(edb, "Copper", conductivity=5.8e7)
|
|
126
125
|
>>> cu.conductivity
|
|
127
126
|
58000000.0
|
|
128
|
-
>>> cu.conductivity = 3.5e7
|
|
127
|
+
>>> cu.conductivity = 3.5e7 # update on-the-fly
|
|
129
128
|
>>> edb.materials["Copper"].conductivity
|
|
130
129
|
35000000.0
|
|
131
130
|
"""
|
|
@@ -50,8 +50,7 @@ class HatchGround:
|
|
|
50
50
|
|
|
51
51
|
Examples
|
|
52
52
|
--------
|
|
53
|
-
>>> hatch = HatchGround(pitch=0.5e-3, width=0.2e-3,
|
|
54
|
-
... fill_target=70, board_size=5e-3)
|
|
53
|
+
>>> hatch = HatchGround(pitch=0.5e-3, width=0.2e-3, fill_target=70, board_size=5e-3)
|
|
55
54
|
>>> edb = Edb("demo.aedb")
|
|
56
55
|
>>> hatch._edb = edb
|
|
57
56
|
>>> hatch.create()
|
|
@@ -164,8 +163,7 @@ class Meander:
|
|
|
164
163
|
|
|
165
164
|
Examples
|
|
166
165
|
--------
|
|
167
|
-
>>> m = Meander(pitch=0.2e-3, trace_width=0.15e-3,
|
|
168
|
-
... amplitude=2e-3, num_turns=4)
|
|
166
|
+
>>> m = Meander(pitch=0.2e-3, trace_width=0.15e-3, amplitude=2e-3, num_turns=4)
|
|
169
167
|
>>> edb = Edb("meander.aedb")
|
|
170
168
|
>>> m._pedb = edb
|
|
171
169
|
>>> m.create()
|
|
@@ -293,7 +291,7 @@ class MIMCapacitor:
|
|
|
293
291
|
>>> edb = Edb("mim.aedb")
|
|
294
292
|
>>> cap._pedb = edb
|
|
295
293
|
>>> cap.create()
|
|
296
|
-
>>> f"{cap.capacitance_f*1e12:.2f} pF"
|
|
294
|
+
>>> f"{cap.capacitance_f * 1e12:.2f} pF"
|
|
297
295
|
'1.45 pF'
|
|
298
296
|
"""
|
|
299
297
|
|
|
@@ -383,8 +381,7 @@ class SpiralInductor:
|
|
|
383
381
|
|
|
384
382
|
Examples
|
|
385
383
|
--------
|
|
386
|
-
>>> sp = SpiralInductor(turns=3.5, trace_width=25e-6,
|
|
387
|
-
... inner_diameter=80e-6)
|
|
384
|
+
>>> sp = SpiralInductor(turns=3.5, trace_width=25e-6, inner_diameter=80e-6)
|
|
388
385
|
>>> edb = Edb("spiral.aedb")
|
|
389
386
|
>>> sp._pedb = edb
|
|
390
387
|
>>> sp.create()
|
|
@@ -769,7 +766,7 @@ class RatRace:
|
|
|
769
766
|
>>> edb = Edb("ratrace.aedb")
|
|
770
767
|
>>> rr._pedb = edb
|
|
771
768
|
>>> rr.create()
|
|
772
|
-
>>> f"{rr.circumference*1e3:.2f} mm"
|
|
769
|
+
>>> f"{rr.circumference * 1e3:.2f} mm"
|
|
773
770
|
'45.00 mm'
|
|
774
771
|
"""
|
|
775
772
|
|
|
@@ -958,9 +955,7 @@ class InterdigitalCapacitor:
|
|
|
958
955
|
|
|
959
956
|
Examples
|
|
960
957
|
--------
|
|
961
|
-
>>> idc = InterdigitalCapacitor(fingers=10,
|
|
962
|
-
... finger_length="0.5mm",
|
|
963
|
-
... gap="0.03mm")
|
|
958
|
+
>>> idc = InterdigitalCapacitor(fingers=10, finger_length="0.5mm", gap="0.03mm")
|
|
964
959
|
>>> edb = Edb("idc.aedb")
|
|
965
960
|
>>> idc._pedb = edb
|
|
966
961
|
>>> idc.create()
|
|
@@ -1104,11 +1099,7 @@ class DifferentialTLine:
|
|
|
1104
1099
|
|
|
1105
1100
|
Examples
|
|
1106
1101
|
--------
|
|
1107
|
-
>>> diff = DifferentialTLine(Edb("diff.aedb"),
|
|
1108
|
-
... length=5e-3,
|
|
1109
|
-
... width=0.15e-3,
|
|
1110
|
-
... spacing=0.1e-3,
|
|
1111
|
-
... angle=math.pi/4)
|
|
1102
|
+
>>> diff = DifferentialTLine(Edb("diff.aedb"), length=5e-3, width=0.15e-3, spacing=0.1e-3, angle=math.pi / 4)
|
|
1112
1103
|
>>> traces = diff.create()
|
|
1113
1104
|
>>> f"{diff.diff_impedance:.1f} Ω"
|
|
1114
1105
|
'95.6 Ω'
|
|
@@ -66,13 +66,7 @@ class RectangularPatch:
|
|
|
66
66
|
Build a 5.8 GHz patch on a 0.787 mm Rogers RO4350B substrate:
|
|
67
67
|
|
|
68
68
|
>>> edb = pyedb.Edb()
|
|
69
|
-
>>> patch = RectangularPatch(
|
|
70
|
-
... edb_cell=edb,
|
|
71
|
-
... freq="5.8GHz",
|
|
72
|
-
... inset="4.2mm",
|
|
73
|
-
... layer="TOP",
|
|
74
|
-
... bottom_layer="GND"
|
|
75
|
-
... )
|
|
69
|
+
>>> patch = RectangularPatch(edb_cell=edb, freq="5.8GHz", inset="4.2mm", layer="TOP", bottom_layer="GND")
|
|
76
70
|
>>> patch.substrate.er = 3.66
|
|
77
71
|
>>> patch.substrate.tand = 0.0037
|
|
78
72
|
>>> patch.substrate.h = 0.000787
|
|
@@ -248,13 +242,7 @@ class CircularPatch:
|
|
|
248
242
|
Build a 5.8 GHz circular patch on a 0.787 mm Rogers RO4350B substrate:
|
|
249
243
|
|
|
250
244
|
>>> edb = pyedb.Edb()
|
|
251
|
-
>>> patch = CircularPatch(
|
|
252
|
-
... edb_cell=edb,
|
|
253
|
-
... freq="5.8GHz",
|
|
254
|
-
... probe_offset="6.4mm",
|
|
255
|
-
... layer="TOP",
|
|
256
|
-
... bottom_layer="GND"
|
|
257
|
-
... )
|
|
245
|
+
>>> patch = CircularPatch(edb_cell=edb, freq="5.8GHz", probe_offset="6.4mm", layer="TOP", bottom_layer="GND")
|
|
258
246
|
>>> patch.substrate.er = 3.66
|
|
259
247
|
>>> patch.substrate.tand = 0.0037
|
|
260
248
|
>>> patch.substrate.h = 0.000787
|
|
@@ -425,13 +413,7 @@ class TriangularPatch:
|
|
|
425
413
|
Build a 5.8 GHz triangular patch on a 0.787 mm Rogers RO4350B substrate:
|
|
426
414
|
|
|
427
415
|
>>> edb = pyedb.Edb()
|
|
428
|
-
>>> patch = TriangularPatch(
|
|
429
|
-
... edb_cell=edb,
|
|
430
|
-
... freq="5.8GHz",
|
|
431
|
-
... probe_offset="5.6mm",
|
|
432
|
-
... layer="TOP",
|
|
433
|
-
... bottom_layer="GND"
|
|
434
|
-
... )
|
|
416
|
+
>>> patch = TriangularPatch(edb_cell=edb, freq="5.8GHz", probe_offset="5.6mm", layer="TOP", bottom_layer="GND")
|
|
435
417
|
>>> patch.substrate.er = 3.66
|
|
436
418
|
>>> patch.substrate.tand = 0.0037
|
|
437
419
|
>>> patch.substrate.h = 0.000787
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
import defusedxml.ElementTree as ET
|
|
24
|
+
from defusedxml.minidom import parseString
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
def write_pretty_xml(root, file_path):
|
pyedb/misc/downloads.py
CHANGED
|
@@ -21,8 +21,10 @@
|
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
23
|
"""Download example datasets from https://github.com/pyansys/example-data"""
|
|
24
|
+
|
|
24
25
|
import os
|
|
25
26
|
import shutil
|
|
27
|
+
import subprocess # nosec B404
|
|
26
28
|
import tempfile
|
|
27
29
|
import urllib.request
|
|
28
30
|
import zipfile
|
|
@@ -47,7 +49,18 @@ def _get_file_url(directory, filename=None):
|
|
|
47
49
|
|
|
48
50
|
|
|
49
51
|
def _retrieve_file(url, filename, directory, destination=None, local_paths=[]): # pragma: no cover
|
|
50
|
-
"""Download a file from a url
|
|
52
|
+
"""Download a file from a url
|
|
53
|
+
|
|
54
|
+
.. warning::
|
|
55
|
+
Do not execute this function with untrusted function argument, environment
|
|
56
|
+
variables or pyedb global settings.
|
|
57
|
+
See the :ref:`security guide<ref_security_consideration>` for details.
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
# Check that provided url is pointing to pyaedt-example repo
|
|
61
|
+
if not url.startswith(EXAMPLE_REPO):
|
|
62
|
+
raise ValueError(f"Attempting to download file(s) from url {url} not pointing the to example-data repo.")
|
|
63
|
+
|
|
51
64
|
# First check if file has already been downloaded
|
|
52
65
|
if not destination:
|
|
53
66
|
destination = EXAMPLES_PATH
|
|
@@ -63,8 +76,11 @@ def _retrieve_file(url, filename, directory, destination=None, local_paths=[]):
|
|
|
63
76
|
os.makedirs(destination_dir)
|
|
64
77
|
# Perform download
|
|
65
78
|
if is_linux:
|
|
66
|
-
command = "wget
|
|
67
|
-
|
|
79
|
+
command = ["wget", url, "-O", local_path]
|
|
80
|
+
try:
|
|
81
|
+
subprocess.run(command, check=True) # nosec
|
|
82
|
+
except subprocess.CalledProcessError as e: # nosec
|
|
83
|
+
raise RuntimeError("An error occurred while downloading wget") from e
|
|
68
84
|
else:
|
|
69
85
|
_, resp = urlretrieve(url, local_path)
|
|
70
86
|
local_paths.append(local_path)
|
pyedb/misc/misc.py
CHANGED
|
@@ -21,9 +21,12 @@
|
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
23
|
"""Miscellaneous Methods for PyEDB."""
|
|
24
|
+
|
|
24
25
|
import os
|
|
25
26
|
import warnings
|
|
26
27
|
|
|
28
|
+
from pyedb.generic.settings import settings
|
|
29
|
+
|
|
27
30
|
|
|
28
31
|
def list_installed_ansysem():
|
|
29
32
|
"""Return a list of installed AEDT versions on ``ANSYSEM_ROOT``."""
|
|
@@ -68,8 +71,8 @@ def installed_versions():
|
|
|
68
71
|
else:
|
|
69
72
|
v_key = "20{0}.{1}".format(version, release)
|
|
70
73
|
return_dict[v_key] = os.environ[version_env_var]
|
|
71
|
-
except: # pragma: no cover
|
|
72
|
-
|
|
74
|
+
except Exception: # pragma: no cover
|
|
75
|
+
settings.logger.debug(f"Failed to parse version and release from {current_version_id}")
|
|
73
76
|
return return_dict
|
|
74
77
|
|
|
75
78
|
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
from copy import deepcopy as copy
|
|
24
24
|
import json
|
|
25
25
|
|
|
26
|
+
from defusedxml.ElementTree import parse as defused_parse
|
|
26
27
|
import numpy as np
|
|
27
28
|
|
|
28
29
|
from pyedb.generic.general_methods import ET
|
|
@@ -66,7 +67,7 @@ class EMCRuleCheckerSettings:
|
|
|
66
67
|
tree = ET.ElementTree(root)
|
|
67
68
|
try:
|
|
68
69
|
ET.indent(tree, space="\t", level=0)
|
|
69
|
-
except: # pragma no cover
|
|
70
|
+
except AttributeError: # pragma no cover
|
|
70
71
|
pass
|
|
71
72
|
return tree
|
|
72
73
|
|
|
@@ -78,7 +79,7 @@ class EMCRuleCheckerSettings:
|
|
|
78
79
|
fpath: str
|
|
79
80
|
Path to file.
|
|
80
81
|
"""
|
|
81
|
-
tree =
|
|
82
|
+
tree = defused_parse(fpath)
|
|
82
83
|
root = tree.getroot()
|
|
83
84
|
|
|
84
85
|
self.tag_library = TagLibrary(root.find("TagLibrary"))
|
pyedb/misc/utilities.py
CHANGED
|
@@ -62,12 +62,12 @@ class GeometryOperators(object):
|
|
|
62
62
|
Parse `'"2mm"'`.
|
|
63
63
|
|
|
64
64
|
>>> from pyedb.modeler.geometry_operators import GeometryOperators as go
|
|
65
|
-
>>> go.parse_dim_arg(
|
|
65
|
+
>>> go.parse_dim_arg("2mm")
|
|
66
66
|
>>> 0.002
|
|
67
67
|
|
|
68
68
|
Use the optional argument ``scale_to_unit`` to specify the destination unit.
|
|
69
69
|
|
|
70
|
-
>>> go.parse_dim_arg(
|
|
70
|
+
>>> go.parse_dim_arg("2mm", scale_to_unit="mm")
|
|
71
71
|
>>> 2.0
|
|
72
72
|
|
|
73
73
|
"""
|
|
@@ -1588,6 +1588,7 @@ class GeometryOperators(object):
|
|
|
1588
1588
|
``True`` if the segments are intersecting.
|
|
1589
1589
|
``False`` otherwise.
|
|
1590
1590
|
"""
|
|
1591
|
+
|
|
1591
1592
|
# fmt: off
|
|
1592
1593
|
def on_segment(p, q, r):
|
|
1593
1594
|
# Given three collinear points p, q, r, the function checks if point q lies on line-segment 'pr'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyedb
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.58.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>
|
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: cffi>=1.16.0,<1
|
|
19
|
+
Requires-Dist: cffi>=1.16.0,<2.1; platform_system=='Linux'
|
|
20
20
|
Requires-Dist: pywin32 >= 303;platform_system=='Windows'
|
|
21
21
|
Requires-Dist: ansys-pythonnet >= 3.1.0rc4
|
|
22
22
|
Requires-Dist: dotnetcore2 ==3.1.23;platform_system=='Linux'
|
|
@@ -29,6 +29,8 @@ Requires-Dist: shapely
|
|
|
29
29
|
Requires-Dist: scikit-rf
|
|
30
30
|
Requires-Dist: ansys-edb-core>=0.2.0
|
|
31
31
|
Requires-Dist: psutil
|
|
32
|
+
Requires-Dist: defusedxml>=0.7,<8.0
|
|
33
|
+
Requires-Dist: matplotlib>=3.5.0,<3.11
|
|
32
34
|
Requires-Dist: ansys-sphinx-theme>=1.0.0,<1.5 ; extra == "doc"
|
|
33
35
|
Requires-Dist: imageio>=2.30.0,<2.38 ; extra == "doc"
|
|
34
36
|
Requires-Dist: ipython>=8.13.0,<8.32 ; extra == "doc"
|
|
@@ -41,18 +43,16 @@ Requires-Dist: numpydoc>=1.5.0,<1.9 ; extra == "doc"
|
|
|
41
43
|
Requires-Dist: pypandoc>=1.10.0,<1.16 ; extra == "doc"
|
|
42
44
|
Requires-Dist: recommonmark ; extra == "doc"
|
|
43
45
|
Requires-Dist: Sphinx>=7.1.0,<8.2 ; extra == "doc"
|
|
44
|
-
Requires-Dist: sphinx-autobuild==
|
|
46
|
+
Requires-Dist: sphinx-autobuild==2024.10.3 ; extra == "doc" and ( python_version == '3.8')
|
|
45
47
|
Requires-Dist: sphinx-autobuild==2024.10.3 ; extra == "doc" and ( python_version > '3.8')
|
|
46
48
|
Requires-Dist: sphinx-copybutton>=0.5.0,<0.6 ; extra == "doc"
|
|
47
49
|
Requires-Dist: sphinx-gallery>=0.14.0,<0.20 ; extra == "doc"
|
|
48
50
|
Requires-Dist: sphinx_design>=0.4.0,<0.7 ; extra == "doc"
|
|
49
51
|
Requires-Dist: shapely ; extra == "doc"
|
|
50
|
-
Requires-Dist: matplotlib>=3.5.0,<3.11 ; extra == "full"
|
|
51
|
-
Requires-Dist: shapely ; extra == "full"
|
|
52
52
|
Requires-Dist: matplotlib>=3.5.0,<3.11 ; extra == "tests"
|
|
53
53
|
Requires-Dist: mock>=5.1.0,<5.3 ; extra == "tests"
|
|
54
54
|
Requires-Dist: pytest>=7.4.0,<8.5 ; extra == "tests"
|
|
55
|
-
Requires-Dist: pytest-cov>=4.0.0,<
|
|
55
|
+
Requires-Dist: pytest-cov>=4.0.0,<7.1 ; extra == "tests"
|
|
56
56
|
Requires-Dist: pytest-xdist>=3.5.0,<3.7 ; extra == "tests"
|
|
57
57
|
Requires-Dist: scikit-rf ; extra == "tests"
|
|
58
58
|
Requires-Dist: shapely ; extra == "tests"
|
|
@@ -62,7 +62,6 @@ Project-URL: Documentation, https://edb.docs.pyansys.com
|
|
|
62
62
|
Project-URL: Releases, https://github.com/ansys/pyedb/releases
|
|
63
63
|
Project-URL: Source, https://github.com/ansys/pyedb
|
|
64
64
|
Provides-Extra: doc
|
|
65
|
-
Provides-Extra: full
|
|
66
65
|
Provides-Extra: tests
|
|
67
66
|
|
|
68
67
|
<!-- -->
|