Compare commits
No commits in common. "1ae3ffb9a28ee4b35af72bce18c985328224c662" and "2cf187fdb81da46440c791e1b4e2b61c5e619daa" have entirely different histories.
1ae3ffb9a2
...
2cf187fdb8
@ -597,19 +597,19 @@ def load_libraryfile(
|
|||||||
path = pathlib.Path(filename)
|
path = pathlib.Path(filename)
|
||||||
stream: IO[bytes]
|
stream: IO[bytes]
|
||||||
if is_gzipped(path):
|
if is_gzipped(path):
|
||||||
if use_mmap:
|
if mmap:
|
||||||
logger.info('Asked to mmap a gzipped file, reading into memory instead...')
|
logger.info('Asked to mmap a gzipped file, reading into memory instead...')
|
||||||
gz_stream = gzip.open(path, mode='rb') # noqa: SIM115
|
gz_stream = gzip.open(path, mode='rb')
|
||||||
stream = io.BytesIO(gz_stream.read()) # type: ignore
|
stream = io.BytesIO(gz_stream.read()) # type: ignore
|
||||||
else:
|
else:
|
||||||
gz_stream = gzip.open(path, mode='rb') # noqa: SIM115
|
gz_stream = gzip.open(path, mode='rb')
|
||||||
stream = io.BufferedReader(gz_stream) # type: ignore
|
stream = io.BufferedReader(gz_stream) # type: ignore
|
||||||
else: # noqa: PLR5501
|
else: # noqa: PLR5501
|
||||||
if use_mmap:
|
if mmap:
|
||||||
base_stream = path.open(mode='rb', buffering=0) # noqa: SIM115
|
base_stream = open(path, mode='rb', buffering=0)
|
||||||
stream = mmap.mmap(base_stream.fileno(), 0, access=mmap.ACCESS_READ) # type: ignore
|
stream = mmap.mmap(base_stream.fileno(), 0, access=mmap.ACCESS_READ) # type: ignore
|
||||||
else:
|
else:
|
||||||
stream = path.open(mode='rb') # noqa: SIM115
|
stream = open(path, mode='rb')
|
||||||
return load_library(stream, full_load=full_load, postprocess=postprocess)
|
return load_library(stream, full_load=full_load, postprocess=postprocess)
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ def clean_pattern_vertices(pat: Pattern) -> Pattern:
|
|||||||
|
|
||||||
|
|
||||||
def is_gzipped(path: pathlib.Path) -> bool:
|
def is_gzipped(path: pathlib.Path) -> bool:
|
||||||
with path.open('rb') as stream:
|
with open(path, 'rb') as stream:
|
||||||
magic_bytes = stream.read(2)
|
magic_bytes = stream.read(2)
|
||||||
return magic_bytes == b'\x1f\x8b'
|
return magic_bytes == b'\x1f\x8b'
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
|||||||
if not annotations_eq(self.annotations, other.annotations):
|
if not annotations_eq(self.annotations, other.annotations):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not ports_eq(self.ports, other.ports): # noqa: SIM103
|
if not ports_eq(self.ports, other.ports):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -595,7 +595,8 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
|||||||
|
|
||||||
if (cbounds[1] < cbounds[0]).any():
|
if (cbounds[1] < cbounds[0]).any():
|
||||||
return None
|
return None
|
||||||
return cbounds
|
else:
|
||||||
|
return cbounds
|
||||||
|
|
||||||
def get_bounds_nonempty(
|
def get_bounds_nonempty(
|
||||||
self,
|
self,
|
||||||
@ -616,7 +617,7 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
|||||||
Returns:
|
Returns:
|
||||||
`[[x_min, y_min], [x_max, y_max]]`
|
`[[x_min, y_min], [x_max, y_max]]`
|
||||||
"""
|
"""
|
||||||
bounds = self.get_bounds(library, recurse=recurse)
|
bounds = self.get_bounds(library)
|
||||||
assert bounds is not None
|
assert bounds is not None
|
||||||
return bounds
|
return bounds
|
||||||
|
|
||||||
@ -953,7 +954,7 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
|||||||
Returns:
|
Returns:
|
||||||
self
|
self
|
||||||
"""
|
"""
|
||||||
flattened: dict[str | None, Pattern | None] = {}
|
flattened: dict[str | None, 'Pattern | None'] = {}
|
||||||
|
|
||||||
def flatten_single(name: str | None) -> None:
|
def flatten_single(name: str | None) -> None:
|
||||||
if name is None:
|
if name is None:
|
||||||
|
@ -289,7 +289,7 @@ class Grid(Repetition):
|
|||||||
return True
|
return True
|
||||||
if self.b_vector is None or other.b_vector is None:
|
if self.b_vector is None or other.b_vector is None:
|
||||||
return False
|
return False
|
||||||
if any(self.b_vector[ii] != other.b_vector[ii] for ii in range(2)): # noqa: SIM103
|
if any(self.b_vector[ii] != other.b_vector[ii] for ii in range(2)):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ class Arc(Shape):
|
|||||||
return thetas
|
return thetas
|
||||||
|
|
||||||
wh = self.width / 2.0
|
wh = self.width / 2.0
|
||||||
if wh in (r0, r1):
|
if wh == r0 or wh == r1:
|
||||||
thetas_inner = numpy.zeros(1) # Don't generate multiple vertices if we're at the origin
|
thetas_inner = numpy.zeros(1) # Don't generate multiple vertices if we're at the origin
|
||||||
else:
|
else:
|
||||||
thetas_inner = get_thetas(inner=True)
|
thetas_inner = get_thetas(inner=True)
|
||||||
@ -308,7 +308,7 @@ class Arc(Shape):
|
|||||||
return [poly]
|
return [poly]
|
||||||
|
|
||||||
def get_bounds_single(self) -> NDArray[numpy.float64]:
|
def get_bounds_single(self) -> NDArray[numpy.float64]:
|
||||||
"""
|
'''
|
||||||
Equation for rotated ellipse is
|
Equation for rotated ellipse is
|
||||||
`x = x0 + a * cos(t) * cos(rot) - b * sin(t) * sin(phi)`
|
`x = x0 + a * cos(t) * cos(rot) - b * sin(t) * sin(phi)`
|
||||||
`y = y0 + a * cos(t) * sin(rot) + b * sin(t) * cos(rot)`
|
`y = y0 + a * cos(t) * sin(rot) + b * sin(t) * cos(rot)`
|
||||||
@ -319,7 +319,7 @@ class Arc(Shape):
|
|||||||
where -+ is for x, y cases, so that's where the extrema are.
|
where -+ is for x, y cases, so that's where the extrema are.
|
||||||
|
|
||||||
If the extrema are innaccessible due to arc constraints, check the arc endpoints instead.
|
If the extrema are innaccessible due to arc constraints, check the arc endpoints instead.
|
||||||
"""
|
'''
|
||||||
a_ranges = self._angles_to_parameters()
|
a_ranges = self._angles_to_parameters()
|
||||||
|
|
||||||
mins = []
|
mins = []
|
||||||
@ -424,13 +424,13 @@ class Arc(Shape):
|
|||||||
))
|
))
|
||||||
|
|
||||||
def get_cap_edges(self) -> NDArray[numpy.float64]:
|
def get_cap_edges(self) -> NDArray[numpy.float64]:
|
||||||
"""
|
'''
|
||||||
Returns:
|
Returns:
|
||||||
```
|
```
|
||||||
[[[x0, y0], [x1, y1]], array of 4 points, specifying the two cuts which
|
[[[x0, y0], [x1, y1]], array of 4 points, specifying the two cuts which
|
||||||
[[x2, y2], [x3, y3]]], would create this arc from its corresponding ellipse.
|
[[x2, y2], [x3, y3]]], would create this arc from its corresponding ellipse.
|
||||||
```
|
```
|
||||||
"""
|
'''
|
||||||
a_ranges = self._angles_to_parameters()
|
a_ranges = self._angles_to_parameters()
|
||||||
|
|
||||||
mins = []
|
mins = []
|
||||||
@ -454,11 +454,11 @@ class Arc(Shape):
|
|||||||
return numpy.array([mins, maxs]) + self.offset
|
return numpy.array([mins, maxs]) + self.offset
|
||||||
|
|
||||||
def _angles_to_parameters(self) -> NDArray[numpy.float64]:
|
def _angles_to_parameters(self) -> NDArray[numpy.float64]:
|
||||||
"""
|
'''
|
||||||
Returns:
|
Returns:
|
||||||
"Eccentric anomaly" parameter ranges for the inner and outer edges, in the form
|
"Eccentric anomaly" parameter ranges for the inner and outer edges, in the form
|
||||||
`[[a_min_inner, a_max_inner], [a_min_outer, a_max_outer]]`
|
`[[a_min_inner, a_max_inner], [a_min_outer, a_max_outer]]`
|
||||||
"""
|
'''
|
||||||
a = []
|
a = []
|
||||||
for sgn in (-1, +1):
|
for sgn in (-1, +1):
|
||||||
wh = sgn * self.width / 2
|
wh = sgn * self.width / 2
|
||||||
|
@ -431,22 +431,22 @@ class Path(Shape):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def remove_duplicate_vertices(self) -> 'Path':
|
def remove_duplicate_vertices(self) -> 'Path':
|
||||||
"""
|
'''
|
||||||
Removes all consecutive duplicate (repeated) vertices.
|
Removes all consecutive duplicate (repeated) vertices.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
self
|
self
|
||||||
"""
|
'''
|
||||||
self.vertices = remove_duplicate_vertices(self.vertices, closed_path=False)
|
self.vertices = remove_duplicate_vertices(self.vertices, closed_path=False)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def remove_colinear_vertices(self) -> 'Path':
|
def remove_colinear_vertices(self) -> 'Path':
|
||||||
"""
|
'''
|
||||||
Removes consecutive co-linear vertices.
|
Removes consecutive co-linear vertices.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
self
|
self
|
||||||
"""
|
'''
|
||||||
self.vertices = remove_colinear_vertices(self.vertices, closed_path=False)
|
self.vertices = remove_colinear_vertices(self.vertices, closed_path=False)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -415,22 +415,22 @@ class Polygon(Shape):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def remove_duplicate_vertices(self) -> 'Polygon':
|
def remove_duplicate_vertices(self) -> 'Polygon':
|
||||||
"""
|
'''
|
||||||
Removes all consecutive duplicate (repeated) vertices.
|
Removes all consecutive duplicate (repeated) vertices.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
self
|
self
|
||||||
"""
|
'''
|
||||||
self.vertices = remove_duplicate_vertices(self.vertices, closed_path=True)
|
self.vertices = remove_duplicate_vertices(self.vertices, closed_path=True)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def remove_colinear_vertices(self) -> 'Polygon':
|
def remove_colinear_vertices(self) -> 'Polygon':
|
||||||
"""
|
'''
|
||||||
Removes consecutive co-linear vertices.
|
Removes consecutive co-linear vertices.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
self
|
self
|
||||||
"""
|
'''
|
||||||
self.vertices = remove_colinear_vertices(self.vertices, closed_path=True)
|
self.vertices = remove_colinear_vertices(self.vertices, closed_path=True)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from typing import Self
|
from typing import Self
|
||||||
|
from abc import ABCMeta
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
|
||||||
class Copyable:
|
class Copyable(metaclass=ABCMeta):
|
||||||
"""
|
"""
|
||||||
Trait class which adds .copy() and .deepcopy()
|
Trait class which adds .copy() and .deepcopy()
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user