Skip to content

Commit 125ec1d

Browse files
Merge branch 'main' into chore/setup-ruff
2 parents fe98f27 + e195a6b commit 125ec1d

33 files changed

+1196
-145
lines changed

.github/workflows/ci_cd.yml

Lines changed: 311 additions & 26 deletions
Large diffs are not rendered by default.

src/pyedb/configuration/cfg_operations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222

23-
from typing import Any, Dict, List, Optional
23+
from typing import Any, Dict, List, Optional, Union
2424

2525
from pydantic import BaseModel, Field
2626

@@ -37,7 +37,7 @@ class CfgCutout(BaseModel):
3737
signal_list: Optional[List[str]] = None
3838
reference_list: Optional[List[str]] = None
3939
extent_type: Optional[str] = "ConvexHull"
40-
expansion_size: Optional[float] = 0.002
40+
expansion_size: Optional[Union[float, str]] = 0.002
4141
number_of_threads: Optional[int] = 1
4242
custom_extent: Optional[Any] = None
4343
custom_extent_units: str = Field(default="meter")

src/pyedb/configuration/cfg_ports_sources.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def __init__(self, pedb, **kwargs):
278278
self._pedb = pedb
279279
self.name = kwargs["name"]
280280
self.type = kwargs["type"]
281-
self.impedance = kwargs.get("impedance", 50)
281+
self.impedance = kwargs.get("impedance", None)
282282
self.reference_designator = kwargs.get("reference_designator", None)
283283
self.distributed = kwargs.get("distributed", False)
284284
self._elem_num = 1

src/pyedb/dotnet/database/Variables.py

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,15 @@ def __getitem__(self, item): # pragma: no cover
183183
if variable in key_string:
184184
found_variable = True
185185
break
186-
assert found_variable, "Input string {} is not a key of the data dictionary.".format(variable)
186+
if not found_variable:
187+
raise KeyError(f"Input string {variable} is not a key of the data dictionary.")
187188
data_out._data[variable] = self._data[key_string]
188189
data_out._header.append(variable)
189190
return data_out
190191

191192
def __add__(self, other): # pragma: no cover
192-
assert self.number_of_columns == other.number_of_columns, "Inconsistent number of columns"
193+
if self.number_of_columns != other.number_of_columns:
194+
raise ValueError("Number of columns is inconsistent.")
193195
# Create a new object to return, avoiding changing the original inputs
194196
new_dataset = CSVDataset()
195197
# Add empty columns to new_dataset
@@ -224,7 +226,8 @@ def __iadd__(self, other): # pragma: no cover
224226
for column in other.data:
225227
self._data[column] = []
226228

227-
assert self.number_of_columns == other.number_of_columns, "Inconsistent number of columns"
229+
if self.number_of_columns != other.number_of_columns:
230+
raise ValueError("Number of columns is inconsistent.")
228231

229232
# Append the data from 'other'
230233
for column, row_data in other.data.items():
@@ -1348,9 +1351,10 @@ def __init__(
13481351
self._value = self._calculated_value
13491352
# If units have been specified, check for a conflict and otherwise use the specified unit system
13501353
if units:
1351-
assert not self._units, "The unit specification {} is inconsistent with the identified units {}.".format(
1352-
specified_units, self._units
1353-
)
1354+
if self._units and self._units != specified_units:
1355+
raise RuntimeError(
1356+
f"The unit specification {specified_units} is inconsistent with the identified units {self._units}."
1357+
)
13541358
self._units = specified_units
13551359

13561360
if not si_value and is_number(self._value):
@@ -1737,9 +1741,10 @@ def rescale_to(self, units): # pragma: no cover
17371741
17381742
"""
17391743
new_unit_system = unit_system(units)
1740-
assert new_unit_system == self.unit_system, (
1741-
"New unit system {0} is inconsistent with the current unit system {1}."
1742-
)
1744+
if new_unit_system != self.unit_system:
1745+
raise ValueError(
1746+
f"New unit system {new_unit_system} is inconsistent with the current unit system {self.unit_system}."
1747+
)
17431748
self._units = units
17441749
return self
17451750

@@ -1810,7 +1815,8 @@ def __mul__(self, other): # pragma: no cover
18101815
>>> assert result_3.unit_system == "Power"
18111816
18121817
"""
1813-
assert is_number(other) or isinstance(other, Variable), "Multiplier must be a scalar quantity or a variable."
1818+
if not is_number(other) and not isinstance(other, Variable):
1819+
raise ValueError("Multiplier must be a scalar quantity or a variable.")
18141820
if is_number(other):
18151821
result_value = self.numeric_value * other
18161822
result_units = self.units
@@ -1854,10 +1860,10 @@ def __add__(self, other): # pragma: no cover
18541860
>>> assert result.unit_system == "Current"
18551861
18561862
"""
1857-
assert isinstance(other, Variable), "You can only add a variable with another variable."
1858-
assert self.unit_system == other.unit_system, (
1859-
"Only ``Variable`` objects with the same unit system can be added."
1860-
)
1863+
if not isinstance(other, Variable):
1864+
raise ValueError("You can only add a variable with another variable.")
1865+
if self.unit_system != other.unit_system:
1866+
raise ValueError("Only Variable objects with the same unit system can be added.")
18611867
result_value = self.value + other.value
18621868
result_units = SI_UNITS[self.unit_system]
18631869
# If the units of the two operands are different, return SI-Units
@@ -1895,10 +1901,10 @@ def __sub__(self, other): # pragma: no cover
18951901
>>> assert result_2.unit_system == "Current"
18961902
18971903
"""
1898-
assert isinstance(other, Variable), "You can only subtract a variable from another variable."
1899-
assert self.unit_system == other.unit_system, (
1900-
"Only ``Variable`` objects with the same unit system can be subtracted."
1901-
)
1904+
if not isinstance(other, Variable):
1905+
raise ValueError("You can only subtract a variable from another variable.")
1906+
if self.unit_system != other.unit_system:
1907+
raise ValueError("Only Variable objects with the same unit system can be subtracted.")
19021908
result_value = self.value - other.value
19031909
result_units = SI_UNITS[self.unit_system]
19041910
# If the units of the two operands are different, return SI-Units
@@ -1940,7 +1946,8 @@ def __truediv__(self, other): # pragma: no cover
19401946
>>> assert result_1.unit_system == "Current"
19411947
19421948
"""
1943-
assert is_number(other) or isinstance(other, Variable), "Divisor must be a scalar quantity or a variable."
1949+
if not is_number(other) and not isinstance(other, Variable):
1950+
raise ValueError("Divisor must be a scalar quantity or a variable.")
19441951
if is_number(other):
19451952
result_value = self.numeric_value / other
19461953
result_units = self.units

src/pyedb/dotnet/database/padstack.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,3 +1945,90 @@ def expand_cluster(point_idx, neighbors):
19451945
clusters[int(label)].append(padstack_ids[i])
19461946

19471947
return dict(clusters)
1948+
1949+
def reduce_via_by_density(
1950+
self, padstacks: List[int], cell_size_x: float = 1e-3, cell_size_y: float = 1e-3, delete: bool = False
1951+
) -> tuple[List[int], List[List[List[float]]]]:
1952+
"""
1953+
Reduce the number of vias by density. Keep only one via which is closest to the center of the cell. The cells
1954+
are automatically populated based on the input vias.
1955+
1956+
Parameters
1957+
----------
1958+
padstacks: List[int]
1959+
List of padstack ids to be reduced.
1960+
1961+
cell_size_x : float
1962+
Width of each grid cell (default is 1e-3).
1963+
1964+
cell_size_y : float
1965+
Height of each grid cell (default is 1e-3).
1966+
1967+
delete: bool
1968+
If True, delete vias that are not kept (default is False).
1969+
1970+
Returns
1971+
-------
1972+
List[int]
1973+
IDs of vias kept after reduction.
1974+
1975+
List[List[float]]
1976+
coordinates for grid lines (for plotting).
1977+
1978+
"""
1979+
to_keep = set()
1980+
1981+
all_instances = self.instances
1982+
positions = np.array([all_instances[_id].position for _id in padstacks])
1983+
1984+
x_coords, y_coords = positions[:, 0], positions[:, 1]
1985+
x_min, x_max = np.min(x_coords), np.max(x_coords)
1986+
y_min, y_max = np.min(y_coords), np.max(y_coords)
1987+
1988+
padstacks_array = np.array(padstacks)
1989+
cell_map = {} # {(cell_x, cell_y): [(id1, [x1, y1]), (id2, [x2, y2), ...]}
1990+
grid = []
1991+
1992+
for idx, pos in enumerate(positions):
1993+
i = int((pos[0] - x_min) // cell_size_x)
1994+
j = int((pos[1] - y_min) // cell_size_y)
1995+
cell_key = (i, j)
1996+
cell_map.setdefault(cell_key, []).append((padstacks_array[idx], pos))
1997+
1998+
for (i, j), items in cell_map.items():
1999+
# cell center
2000+
cell_x_min = x_min + i * cell_size_x
2001+
cell_y_min = y_min + j * cell_size_y
2002+
cell_x_mid = cell_x_min + 0.5 * cell_size_x
2003+
cell_y_mid = cell_y_min + 0.5 * cell_size_y
2004+
2005+
grid.append(
2006+
[
2007+
[
2008+
cell_x_min,
2009+
cell_x_min + cell_size_x,
2010+
cell_x_min + cell_size_x,
2011+
cell_x_min,
2012+
cell_x_min,
2013+
],
2014+
[
2015+
cell_y_min,
2016+
cell_y_min,
2017+
cell_y_min + cell_size_y,
2018+
cell_y_min + cell_size_y,
2019+
cell_y_min,
2020+
],
2021+
]
2022+
)
2023+
2024+
# Find closest via to cell center
2025+
distances = [np.linalg.norm(pos - [cell_x_mid, cell_y_mid]) for _, pos in items]
2026+
closest_idx = np.argmin(distances)
2027+
to_keep.add(items[closest_idx][0])
2028+
2029+
if delete:
2030+
to_delete = set(padstacks) - to_keep
2031+
for _id in to_delete:
2032+
all_instances[_id].delete()
2033+
2034+
return list(to_keep), grid

src/pyedb/dotnet/edb.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4036,15 +4036,15 @@ def copy_zones(self, working_directory=None):
40364036
edb_zones = {}
40374037
if not self.setups:
40384038
self.siwave.add_siwave_syz_analysis()
4039-
self.save_edb()
4039+
self.save()
40404040
for zone_primitive in zone_primitives:
40414041
edb_zone_path = os.path.join(
40424042
working_directory,
40434043
"{}_{}".format(zone_primitive.GetId(), os.path.basename(self.edbpath)),
40444044
)
40454045
shutil.copytree(self.edbpath, edb_zone_path)
40464046
poly_data = zone_primitive.GetPolygonData()
4047-
if self.version[0] >= 10:
4047+
if self._db.GetVersion()[0] >= 10:
40484048
edb_zones[edb_zone_path] = (zone_primitive.GetZoneId(), poly_data)
40494049
elif len(zone_primitives) == len(zone_ids):
40504050
edb_zones[edb_zone_path] = (zone_ids[0], poly_data)

0 commit comments

Comments
 (0)