lots of fixes to get test_rep running
This commit is contained in:
parent
88b64bf525
commit
1b04fb7ed0
@ -1,103 +1,135 @@
|
||||
from pprint import pprint
|
||||
from pathlib import Path
|
||||
|
||||
import numpy
|
||||
from numpy import pi
|
||||
|
||||
import masque
|
||||
import masque.file.gdsii
|
||||
import masque.file.klamath
|
||||
import masque.file.dxf
|
||||
import masque.file.oasis
|
||||
from masque import shapes, Pattern, SubPattern
|
||||
from masque import Pattern, Ref, Arc, WrapLibrary
|
||||
from masque.repetition import Grid
|
||||
from masque.file import gdsii, dxf, oasis
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
def main():
|
||||
pat = masque.Pattern(name='ellip_grating')
|
||||
lib = WrapLibrary()
|
||||
|
||||
cell_name = 'ellip_grating'
|
||||
pat = masque.Pattern()
|
||||
for rmin in numpy.arange(10, 15, 0.5):
|
||||
pat.shapes.append(shapes.Arc(
|
||||
pat.shapes.append(Arc(
|
||||
radii=(rmin, rmin),
|
||||
width=0.1,
|
||||
angles=(0*-numpy.pi/4, numpy.pi/4),
|
||||
angles=(0 * -pi/4, pi/4),
|
||||
annotations={'1': ['blah']},
|
||||
))
|
||||
|
||||
pat.scale_by(1000)
|
||||
# pat.visualize()
|
||||
pat2 = pat.copy()
|
||||
pat2.name = 'grating2'
|
||||
|
||||
pat3 = Pattern('sref_test')
|
||||
pat3.subpatterns = [
|
||||
SubPattern(pat, offset=(1e5, 3e5), annotations={'4': ['Hello I am the base subpattern']}),
|
||||
SubPattern(pat, offset=(2e5, 3e5), rotation=pi/3),
|
||||
SubPattern(pat, offset=(3e5, 3e5), rotation=pi/2),
|
||||
SubPattern(pat, offset=(4e5, 3e5), rotation=pi),
|
||||
SubPattern(pat, offset=(5e5, 3e5), rotation=3*pi/2),
|
||||
SubPattern(pat, mirrored=(True, False), offset=(1e5, 4e5)),
|
||||
SubPattern(pat, mirrored=(True, False), offset=(2e5, 4e5), rotation=pi/3),
|
||||
SubPattern(pat, mirrored=(True, False), offset=(3e5, 4e5), rotation=pi/2),
|
||||
SubPattern(pat, mirrored=(True, False), offset=(4e5, 4e5), rotation=pi),
|
||||
SubPattern(pat, mirrored=(True, False), offset=(5e5, 4e5), rotation=3*pi/2),
|
||||
SubPattern(pat, mirrored=(False, True), offset=(1e5, 5e5)),
|
||||
SubPattern(pat, mirrored=(False, True), offset=(2e5, 5e5), rotation=pi/3),
|
||||
SubPattern(pat, mirrored=(False, True), offset=(3e5, 5e5), rotation=pi/2),
|
||||
SubPattern(pat, mirrored=(False, True), offset=(4e5, 5e5), rotation=pi),
|
||||
SubPattern(pat, mirrored=(False, True), offset=(5e5, 5e5), rotation=3*pi/2),
|
||||
SubPattern(pat, mirrored=(True, True), offset=(1e5, 6e5)),
|
||||
SubPattern(pat, mirrored=(True, True), offset=(2e5, 6e5), rotation=pi/3),
|
||||
SubPattern(pat, mirrored=(True, True), offset=(3e5, 6e5), rotation=pi/2),
|
||||
SubPattern(pat, mirrored=(True, True), offset=(4e5, 6e5), rotation=pi),
|
||||
SubPattern(pat, mirrored=(True, True), offset=(5e5, 6e5), rotation=3*pi/2),
|
||||
]
|
||||
|
||||
pprint(pat3)
|
||||
pprint(pat3.subpatterns)
|
||||
lib[cell_name] = pat
|
||||
print(f'\nAdded {cell_name}:')
|
||||
pprint(pat.shapes)
|
||||
|
||||
rep = Grid(a_vector=[1e4, 0],
|
||||
b_vector=[0, 1.5e4],
|
||||
a_count=3,
|
||||
b_count=2,)
|
||||
pat4 = Pattern('aref_test')
|
||||
pat4.subpatterns = [
|
||||
SubPattern(pat, repetition=rep, offset=(1e5, 3e5)),
|
||||
SubPattern(pat, repetition=rep, offset=(2e5, 3e5), rotation=pi/3),
|
||||
SubPattern(pat, repetition=rep, offset=(3e5, 3e5), rotation=pi/2),
|
||||
SubPattern(pat, repetition=rep, offset=(4e5, 3e5), rotation=pi),
|
||||
SubPattern(pat, repetition=rep, offset=(5e5, 3e5), rotation=3*pi/2),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, False), offset=(1e5, 4e5)),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, False), offset=(2e5, 4e5), rotation=pi/3),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, False), offset=(3e5, 4e5), rotation=pi/2),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, False), offset=(4e5, 4e5), rotation=pi),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, False), offset=(5e5, 4e5), rotation=3*pi/2),
|
||||
SubPattern(pat, repetition=rep, mirrored=(False, True), offset=(1e5, 5e5)),
|
||||
SubPattern(pat, repetition=rep, mirrored=(False, True), offset=(2e5, 5e5), rotation=pi/3),
|
||||
SubPattern(pat, repetition=rep, mirrored=(False, True), offset=(3e5, 5e5), rotation=pi/2),
|
||||
SubPattern(pat, repetition=rep, mirrored=(False, True), offset=(4e5, 5e5), rotation=pi),
|
||||
SubPattern(pat, repetition=rep, mirrored=(False, True), offset=(5e5, 5e5), rotation=3*pi/2),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, True), offset=(1e5, 6e5)),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, True), offset=(2e5, 6e5), rotation=pi/3),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, True), offset=(3e5, 6e5), rotation=pi/2),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, True), offset=(4e5, 6e5), rotation=pi),
|
||||
SubPattern(pat, repetition=rep, mirrored=(True, True), offset=(5e5, 6e5), rotation=3*pi/2),
|
||||
new_name = lib.get_name(cell_name)
|
||||
lib[new_name] = pat.copy()
|
||||
print(f'\nAdded a copy of {cell_name} as {new_name}')
|
||||
|
||||
pat3 = Pattern()
|
||||
pat3.refs = [
|
||||
Ref(cell_name, offset=(1e5, 3e5), annotations={'4': ['Hello I am the base Ref']}),
|
||||
Ref(cell_name, offset=(2e5, 3e5), rotation=pi/3),
|
||||
Ref(cell_name, offset=(3e5, 3e5), rotation=pi/2),
|
||||
Ref(cell_name, offset=(4e5, 3e5), rotation=pi),
|
||||
Ref(cell_name, offset=(5e5, 3e5), rotation=3*pi/2),
|
||||
Ref(cell_name, mirrored=(True, False), offset=(1e5, 4e5)),
|
||||
Ref(cell_name, mirrored=(True, False), offset=(2e5, 4e5), rotation=pi/3),
|
||||
Ref(cell_name, mirrored=(True, False), offset=(3e5, 4e5), rotation=pi/2),
|
||||
Ref(cell_name, mirrored=(True, False), offset=(4e5, 4e5), rotation=pi),
|
||||
Ref(cell_name, mirrored=(True, False), offset=(5e5, 4e5), rotation=3*pi/2),
|
||||
Ref(cell_name, mirrored=(False, True), offset=(1e5, 5e5)),
|
||||
Ref(cell_name, mirrored=(False, True), offset=(2e5, 5e5), rotation=pi/3),
|
||||
Ref(cell_name, mirrored=(False, True), offset=(3e5, 5e5), rotation=pi/2),
|
||||
Ref(cell_name, mirrored=(False, True), offset=(4e5, 5e5), rotation=pi),
|
||||
Ref(cell_name, mirrored=(False, True), offset=(5e5, 5e5), rotation=3*pi/2),
|
||||
Ref(cell_name, mirrored=(True, True), offset=(1e5, 6e5)),
|
||||
Ref(cell_name, mirrored=(True, True), offset=(2e5, 6e5), rotation=pi/3),
|
||||
Ref(cell_name, mirrored=(True, True), offset=(3e5, 6e5), rotation=pi/2),
|
||||
Ref(cell_name, mirrored=(True, True), offset=(4e5, 6e5), rotation=pi),
|
||||
Ref(cell_name, mirrored=(True, True), offset=(5e5, 6e5), rotation=3*pi/2),
|
||||
]
|
||||
|
||||
folder = 'layouts/'
|
||||
masque.file.klamath.writefile((pat, pat2, pat3, pat4), folder + 'rep.gds.gz', 1e-9, 1e-3)
|
||||
lib['sref_test'] = pat3
|
||||
print('\nAdded sref_test:')
|
||||
pprint(pat3)
|
||||
pprint(pat3.refs)
|
||||
|
||||
cells = list(masque.file.klamath.readfile(folder + 'rep.gds.gz')[0].values())
|
||||
masque.file.klamath.writefile(cells, folder + 'rerep.gds.gz', 1e-9, 1e-3)
|
||||
rep = Grid(
|
||||
a_vector=[1e4, 0],
|
||||
b_vector=[0, 1.5e4],
|
||||
a_count=3,
|
||||
b_count=2,
|
||||
)
|
||||
pat4 = Pattern()
|
||||
pat4.refs = [
|
||||
Ref(cell_name, repetition=rep, offset=(1e5, 3e5)),
|
||||
Ref(cell_name, repetition=rep, offset=(2e5, 3e5), rotation=pi/3),
|
||||
Ref(cell_name, repetition=rep, offset=(3e5, 3e5), rotation=pi/2),
|
||||
Ref(cell_name, repetition=rep, offset=(4e5, 3e5), rotation=pi),
|
||||
Ref(cell_name, repetition=rep, offset=(5e5, 3e5), rotation=3*pi/2),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, False), offset=(1e5, 4e5)),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, False), offset=(2e5, 4e5), rotation=pi/3),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, False), offset=(3e5, 4e5), rotation=pi/2),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, False), offset=(4e5, 4e5), rotation=pi),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, False), offset=(5e5, 4e5), rotation=3*pi/2),
|
||||
Ref(cell_name, repetition=rep, mirrored=(False, True), offset=(1e5, 5e5)),
|
||||
Ref(cell_name, repetition=rep, mirrored=(False, True), offset=(2e5, 5e5), rotation=pi/3),
|
||||
Ref(cell_name, repetition=rep, mirrored=(False, True), offset=(3e5, 5e5), rotation=pi/2),
|
||||
Ref(cell_name, repetition=rep, mirrored=(False, True), offset=(4e5, 5e5), rotation=pi),
|
||||
Ref(cell_name, repetition=rep, mirrored=(False, True), offset=(5e5, 5e5), rotation=3*pi/2),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, True), offset=(1e5, 6e5)),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, True), offset=(2e5, 6e5), rotation=pi/3),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, True), offset=(3e5, 6e5), rotation=pi/2),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, True), offset=(4e5, 6e5), rotation=pi),
|
||||
Ref(cell_name, repetition=rep, mirrored=(True, True), offset=(5e5, 6e5), rotation=3*pi/2),
|
||||
]
|
||||
|
||||
masque.file.dxf.writefile(pat4, folder + 'rep.dxf.gz')
|
||||
dxf, info = masque.file.dxf.readfile(folder + 'rep.dxf.gz')
|
||||
masque.file.dxf.writefile(dxf, folder + 'rerep.dxf.gz')
|
||||
lib['aref_test'] = pat4
|
||||
print('\nAdded aref_test')
|
||||
|
||||
folder = Path('./layouts/')
|
||||
print(f'...writing files to {folder}...')
|
||||
|
||||
gds1 = folder / 'rep.gds.gz'
|
||||
gds2 = folder / 'rerep.gds.gz'
|
||||
print(f'Initial write to {gds1}')
|
||||
gdsii.writefile(lib, gds1, 1e-9, 1e-3)
|
||||
|
||||
print(f'Read back and rewrite to {gds2}')
|
||||
readback_lib, _info = gdsii.readfile(gds1)
|
||||
gdsii.writefile(readback_lib, gds2, 1e-9, 1e-3)
|
||||
|
||||
dxf1 = folder / 'rep.dxf.gz'
|
||||
dxf2 = folder / 'rerep.dxf.gz'
|
||||
print(f'Write aref_test to {dxf1}')
|
||||
dxf.writefile(lib, 'aref_test', dxf1)
|
||||
|
||||
print(f'Read back and rewrite to {dxf2}')
|
||||
dxf_lib, _info = dxf.readfile(dxf1)
|
||||
print(WrapLibrary(dxf_lib))
|
||||
dxf.writefile(dxf_lib, 'Model', dxf2)
|
||||
|
||||
layer_map = {'base': (0,0), 'mylabel': (1,2)}
|
||||
masque.file.oasis.writefile((pat, pat2, pat3, pat4), folder + 'rep.oas.gz', 1000, layer_map=layer_map)
|
||||
oas, info = masque.file.oasis.readfile(folder + 'rep.oas.gz')
|
||||
masque.file.oasis.writefile(list(oas.values()), folder + 'rerep.oas.gz', 1000, layer_map=layer_map)
|
||||
print(info)
|
||||
oas1 = folder / 'rep.oas'
|
||||
oas2 = folder / 'rerep.oas'
|
||||
print(f'Write lib to {oas1}')
|
||||
oasis.writefile(lib, oas1, 1000, layer_map=layer_map)
|
||||
|
||||
print(f'Read back and rewrite to {oas2}')
|
||||
oas_lib, oas_info = oasis.readfile(oas1)
|
||||
oasis.writefile(oas_lib, oas2, 1000, layer_map=layer_map)
|
||||
|
||||
print('OASIS info:')
|
||||
pprint(oas_info)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -35,7 +35,9 @@ from .pattern import Pattern
|
||||
from .utils import layer_t, annotations_t
|
||||
from .library import Library, MutableLibrary, WrapROLibrary, WrapLibrary, LazyLibrary, AbstractView
|
||||
from .ports import Port, PortList
|
||||
from .builder import Builder, Abstract, Tool
|
||||
from .abstract import Abstract
|
||||
from .builder import Builder, Tool
|
||||
|
||||
|
||||
__author__ = 'Jan Petykiewicz'
|
||||
|
||||
|
@ -3,13 +3,12 @@ from typing import MutableMapping, TYPE_CHECKING
|
||||
import copy
|
||||
import logging
|
||||
|
||||
from ..pattern import Pattern
|
||||
from ..library import MutableLibrary
|
||||
from ..ports import PortList, Port
|
||||
from .tools import Tool
|
||||
from .pattern import Pattern
|
||||
from .ports import PortList, Port
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .builder import Builder
|
||||
from .builder import Builder, Tool
|
||||
from .library import MutableLibrary
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -34,8 +33,8 @@ class Abstract(PortList):
|
||||
|
||||
def build(
|
||||
self,
|
||||
library: MutableLibrary,
|
||||
tools: Union[None, Tool, MutableMapping[Optional[str], Tool]] = None,
|
||||
library: 'MutableLibrary',
|
||||
tools: Union[None, 'Tool', MutableMapping[Optional[str], 'Tool']] = None,
|
||||
) -> 'Builder':
|
||||
"""
|
||||
Begin building a new device around an instance of the current device
|
@ -1,4 +1,3 @@
|
||||
from .builder import Builder
|
||||
from .abstract import Abstract
|
||||
from .utils import ell
|
||||
from .tools import Tool
|
||||
|
@ -12,9 +12,9 @@ from ..ref import Ref
|
||||
from ..library import MutableLibrary
|
||||
from ..error import PortError, BuildError
|
||||
from ..ports import PortList, Port
|
||||
from ..abstract import Abstract
|
||||
from .tools import Tool
|
||||
from .utils import ell
|
||||
from .abstract import Abstract
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -14,27 +14,29 @@ import pathlib
|
||||
import gzip
|
||||
|
||||
import numpy
|
||||
import ezdxf # type: ignore
|
||||
import ezdxf
|
||||
|
||||
from .. import Pattern, Ref, PatternError, Label, Shape
|
||||
from ..shapes import Polygon, Path
|
||||
from .. import Pattern, Ref, PatternError, Label
|
||||
from ..library import Library, WrapROLibrary
|
||||
from ..shapes import Shape, Polygon, Path
|
||||
from ..repetition import Grid
|
||||
from ..utils import rotation_matrix_2d, layer_t
|
||||
from .utils import is_gzipped
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
logger.warning('DXF support is experimental and only slightly tested!')
|
||||
logger.warning('DXF support is experimental!')
|
||||
|
||||
|
||||
DEFAULT_LAYER = 'DEFAULT'
|
||||
|
||||
|
||||
def write(
|
||||
library: Mapping[str, Pattern], # TODO could allow library=None for flat DXF
|
||||
top_name: str,
|
||||
library: Mapping[str, Pattern],
|
||||
stream: io.TextIOBase,
|
||||
stream: TextIO,
|
||||
*,
|
||||
dxf_version='AC1024',
|
||||
) -> None:
|
||||
@ -65,17 +67,23 @@ def write(
|
||||
array with rotated instances must be manhattan _after_ having a compensating rotation applied.
|
||||
|
||||
Args:
|
||||
top_name: Name of the top-level pattern to write.
|
||||
library: A {name: Pattern} mapping of patterns. Only `top_name` and patterns referenced
|
||||
by it are written.
|
||||
top_name: Name of the top-level pattern to write.
|
||||
stream: Stream object to write to.
|
||||
disambiguate_func: Function which takes a list of patterns and alters them
|
||||
to make their names valid and unique. Default is `disambiguate_pattern_names`.
|
||||
WARNING: No additional error checking is performed on the results.
|
||||
"""
|
||||
#TODO consider supporting DXF arcs?
|
||||
if not isinstance(library, Library):
|
||||
if isinstance(library, dict):
|
||||
library = WrapROLibrary(library)
|
||||
else:
|
||||
library = WrapROLibrary(dict(library))
|
||||
|
||||
pattern = library[top_name]
|
||||
subtree = library.subtree(top_name)
|
||||
|
||||
# Create library
|
||||
lib = ezdxf.new(dxf_version, setup=True)
|
||||
@ -85,8 +93,11 @@ def write(
|
||||
_mrefs_to_drefs(msp, pattern.refs)
|
||||
|
||||
# Now create a block for each referenced pattern, and add in any shapes
|
||||
for name, pat in library.items():
|
||||
for name, pat in subtree.items():
|
||||
assert pat is not None
|
||||
if name == top_name:
|
||||
continue
|
||||
|
||||
block = lib.blocks.new(name=name)
|
||||
|
||||
_shapes_to_elements(block, pat.shapes)
|
||||
@ -97,8 +108,8 @@ def write(
|
||||
|
||||
|
||||
def writefile(
|
||||
top_name: str,
|
||||
library: Mapping[str, Pattern],
|
||||
top_name: str,
|
||||
filename: Union[str, pathlib.Path],
|
||||
*args,
|
||||
**kwargs,
|
||||
@ -109,9 +120,9 @@ def writefile(
|
||||
Will automatically compress the file if it has a .gz suffix.
|
||||
|
||||
Args:
|
||||
top_name: Name of the top-level pattern to write.
|
||||
library: A {name: Pattern} mapping of patterns. Only `top_name` and patterns referenced
|
||||
by it are written.
|
||||
top_name: Name of the top-level pattern to write.
|
||||
filename: Filename to save to.
|
||||
*args: passed to `dxf.write`
|
||||
**kwargs: passed to `dxf.write`
|
||||
@ -181,19 +192,19 @@ def read(
|
||||
lib = ezdxf.read(stream)
|
||||
msp = lib.modelspace()
|
||||
|
||||
npat = _read_block(msp, clean_vertices)
|
||||
npat = _read_block(msp)
|
||||
patterns_dict = dict(
|
||||
[npat] + [_read_block(bb, clean_vertices) for bb in lib.blocks if bb.name != '*Model_Space']
|
||||
[npat] + [_read_block(bb) for bb in lib.blocks if bb.name != '*Model_Space']
|
||||
)
|
||||
|
||||
library_info = {
|
||||
'layers': [ll.dxfattribs() for ll in lib.layers]
|
||||
}
|
||||
library_info = dict(
|
||||
layers=[ll.dxfattribs() for ll in lib.layers],
|
||||
)
|
||||
|
||||
return patterns_dict, library_info
|
||||
|
||||
|
||||
def _read_block(block, clean_vertices: bool) -> Tuple[str, Pattern]:
|
||||
def _read_block(block) -> Tuple[str, Pattern]:
|
||||
name = block.name
|
||||
pat = Pattern()
|
||||
for element in block:
|
||||
@ -225,18 +236,13 @@ def _read_block(block, clean_vertices: bool) -> Tuple[str, Pattern]:
|
||||
else:
|
||||
shape = Path(layer=layer, width=width, vertices=points[:, :2])
|
||||
|
||||
if clean_vertices:
|
||||
try:
|
||||
shape.clean_vertices()
|
||||
except PatternError:
|
||||
continue
|
||||
|
||||
pat.shapes.append(shape)
|
||||
|
||||
elif eltype in ('TEXT',):
|
||||
args = {'offset': numpy.array(element.get_pos()[1])[:2],
|
||||
'layer': element.dxfattribs().get('layer', DEFAULT_LAYER),
|
||||
}
|
||||
args = dict(
|
||||
offset=numpy.array(element.get_pos()[1])[:2],
|
||||
layer=element.dxfattribs().get('layer', DEFAULT_LAYER),
|
||||
)
|
||||
string = element.dxfattribs().get('text', '')
|
||||
# height = element.dxfattribs().get('height', 0)
|
||||
# if height != 0:
|
||||
@ -257,20 +263,21 @@ def _read_block(block, clean_vertices: bool) -> Tuple[str, Pattern]:
|
||||
|
||||
offset = numpy.array(attr.get('insert', (0, 0, 0)))[:2]
|
||||
|
||||
args = {
|
||||
'target': (attr.get('name', None),),
|
||||
'offset': offset,
|
||||
'scale': scale,
|
||||
'mirrored': mirrored,
|
||||
'rotation': rotation,
|
||||
'pattern': None,
|
||||
}
|
||||
args = dict(
|
||||
target=attr.get('name', None),
|
||||
offset=offset,
|
||||
scale=scale,
|
||||
mirrored=mirrored,
|
||||
rotation=rotation,
|
||||
)
|
||||
|
||||
if 'column_count' in attr:
|
||||
args['repetition'] = Grid(a_vector=(attr['column_spacing'], 0),
|
||||
args['repetition'] = Grid(
|
||||
a_vector=(attr['column_spacing'], 0),
|
||||
b_vector=(0, attr['row_spacing']),
|
||||
a_count=attr['column_count'],
|
||||
b_count=attr['row_count'])
|
||||
b_count=attr['row_count'],
|
||||
)
|
||||
pat.ref(**args)
|
||||
else:
|
||||
logger.warning(f'Ignoring DXF element {element.dxftype()} (not implemented).')
|
||||
@ -286,12 +293,12 @@ def _mrefs_to_drefs(
|
||||
continue
|
||||
encoded_name = ref.target
|
||||
|
||||
rotation = (ref.rotation * 180 / numpy.pi) % 360
|
||||
attribs = {
|
||||
'xscale': ref.scale * (-1 if ref.mirrored[1] else 1),
|
||||
'yscale': ref.scale * (-1 if ref.mirrored[0] else 1),
|
||||
'rotation': rotation,
|
||||
}
|
||||
rotation = numpy.rad2deg(ref.rotation) % 360
|
||||
attribs = dict(
|
||||
xscale=ref.scale * (-1 if ref.mirrored[1] else 1),
|
||||
yscale=ref.scale * (-1 if ref.mirrored[0] else 1),
|
||||
rotation=rotation,
|
||||
)
|
||||
|
||||
rep = ref.repetition
|
||||
if rep is None:
|
||||
@ -338,7 +345,7 @@ def _shapes_to_elements(
|
||||
' Please call library.wrap_repeated_shapes() before writing to file.'
|
||||
)
|
||||
|
||||
attribs = {'layer': _mlayer2dxf(shape.layer)}
|
||||
attribs = dict(layer=_mlayer2dxf(shape.layer))
|
||||
for polygon in shape.to_polygons():
|
||||
xy_open = polygon.vertices + polygon.offset
|
||||
xy_closed = numpy.vstack((xy_open, xy_open[0, :]))
|
||||
@ -350,7 +357,7 @@ def _labels_to_texts(
|
||||
labels: List[Label],
|
||||
) -> None:
|
||||
for label in labels:
|
||||
attribs = {'layer': _mlayer2dxf(label.layer)}
|
||||
attribs = dict(layer=_mlayer2dxf(label.layer))
|
||||
xy = label.offset
|
||||
block.add_text(label.string, dxfattribs=attribs).set_pos(xy, align='BOTTOM_LEFT')
|
||||
|
||||
|
@ -30,7 +30,7 @@ import string
|
||||
from pprint import pformat
|
||||
|
||||
import numpy
|
||||
from numpy.typing import NDArray, ArrayLike
|
||||
from numpy.typing import ArrayLike, NDArray
|
||||
import klamath
|
||||
from klamath import records
|
||||
|
||||
@ -54,7 +54,7 @@ path_cap_map = {
|
||||
|
||||
|
||||
def rint_cast(val: ArrayLike) -> NDArray[numpy.int32]:
|
||||
return numpy.rint(val, dtype=numpy.int32, casting='unsafe')
|
||||
return numpy.rint(val).astype(numpy.int32)
|
||||
|
||||
|
||||
def write(
|
||||
|
@ -39,7 +39,7 @@ from ..utils import layer_t, normalize_mirror, annotations_t
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
logger.warning('OASIS support is experimental and mostly untested!')
|
||||
logger.warning('OASIS support is experimental!')
|
||||
|
||||
|
||||
path_cap_map = {
|
||||
@ -51,7 +51,7 @@ path_cap_map = {
|
||||
#TODO implement more shape types?
|
||||
|
||||
def rint_cast(val: ArrayLike) -> NDArray[numpy.int64]:
|
||||
return numpy.rint(val, dtype=numpy.int64, casting='unsafe')
|
||||
return numpy.rint(val).astype(numpy.int64)
|
||||
|
||||
|
||||
def build(
|
||||
|
@ -22,7 +22,7 @@ from .error import LibraryError, PatternError
|
||||
from .utils import rotation_matrix_2d, normalize_mirror
|
||||
from .shapes import Shape, Polygon
|
||||
from .label import Label
|
||||
from .builder.abstract import Abstract
|
||||
from .abstract import Abstract
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .pattern import Pattern
|
||||
@ -37,7 +37,7 @@ ML = TypeVar('ML', bound='MutableLibrary')
|
||||
LL = TypeVar('LL', bound='LazyLibrary')
|
||||
|
||||
|
||||
class Library(Mapping[str, Pattern], metaclass=ABCMeta):
|
||||
class Library(Mapping[str, 'Pattern'], metaclass=ABCMeta):
|
||||
# inherited abstract functions
|
||||
#def __getitem__(self, key: str) -> 'Pattern':
|
||||
#def __iter__(self) -> Iterator[str]:
|
||||
@ -61,7 +61,7 @@ class Library(Mapping[str, Pattern], metaclass=ABCMeta):
|
||||
return Abstract(name=name, ports=self[name].ports)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return '<Library with keys ' + repr(list(self.keys())) + '>'
|
||||
return '<Library with keys\n' + pformat(list(self.keys())) + '>'
|
||||
|
||||
def dangling_references(
|
||||
self,
|
||||
@ -142,7 +142,11 @@ class Library(Mapping[str, Pattern], metaclass=ABCMeta):
|
||||
Returns:
|
||||
A `WrapROLibrary` containing only `tops` and the patterns they reference.
|
||||
"""
|
||||
if isinstance(tops, str):
|
||||
tops = (tops,)
|
||||
|
||||
keep: Set[str] = self.referenced_patterns(tops) - set((None,)) # type: ignore
|
||||
keep |= set(tops)
|
||||
|
||||
filtered = {kk: vv for kk, vv in self.items() if kk in keep}
|
||||
new = WrapROLibrary(filtered)
|
||||
@ -405,7 +409,7 @@ class Library(Mapping[str, Pattern], metaclass=ABCMeta):
|
||||
VVV = TypeVar('VVV')
|
||||
|
||||
|
||||
class MutableLibrary(Generic[VVV], Library, metaclass=ABCMeta):
|
||||
class MutableLibrary(Library, Generic[VVV], metaclass=ABCMeta):
|
||||
# inherited abstract functions
|
||||
#def __getitem__(self, key: str) -> 'Pattern':
|
||||
#def __iter__(self) -> Iterator[str]:
|
||||
@ -627,7 +631,11 @@ class MutableLibrary(Generic[VVV], Library, metaclass=ABCMeta):
|
||||
Returns:
|
||||
A `Library` containing only `tops` and the patterns they reference.
|
||||
"""
|
||||
if isinstance(tops, str):
|
||||
tops = (tops,)
|
||||
|
||||
keep: Set[str] = self.referenced_patterns(tops) - set((None,)) # type: ignore
|
||||
keep |= set(tops)
|
||||
|
||||
new = type(self)()
|
||||
for key in keep:
|
||||
@ -654,7 +662,7 @@ class WrapROLibrary(Library):
|
||||
return len(self.mapping)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'<WrapROLibrary ({type(self.mapping)}) with keys ' + repr(list(self.keys())) + '>'
|
||||
return f'<WrapROLibrary ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
|
||||
|
||||
|
||||
class WrapLibrary(MutableLibrary):
|
||||
@ -662,8 +670,11 @@ class WrapLibrary(MutableLibrary):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mapping: MutableMapping[str, 'Pattern'],
|
||||
mapping: Optional[MutableMapping[str, 'Pattern']] = None,
|
||||
) -> None:
|
||||
if mapping is None:
|
||||
self.mapping = {}
|
||||
else:
|
||||
self.mapping = mapping
|
||||
|
||||
def __getitem__(self, key: str) -> 'Pattern':
|
||||
@ -688,7 +699,7 @@ class WrapLibrary(MutableLibrary):
|
||||
self[key] = other[key]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'<WrapLibrary ({type(self.mapping)}) with keys ' + repr(list(self.keys())) + '>'
|
||||
return f'<WrapLibrary ({type(self.mapping)}) with keys\n' + pformat(list(self.keys())) + '>'
|
||||
|
||||
|
||||
class LazyLibrary(MutableLibrary):
|
||||
@ -745,7 +756,7 @@ class LazyLibrary(MutableLibrary):
|
||||
self._set(key, other[key])
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return '<LazyLibrary with keys ' + repr(list(self.keys())) + '>'
|
||||
return '<LazyLibrary with keys\n' + pformat(list(self.keys())) + '>'
|
||||
|
||||
def precache(self: LL) -> LL:
|
||||
"""
|
||||
|
@ -88,7 +88,9 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable, metaclass=AutoSlots):
|
||||
self.refs = list(refs)
|
||||
|
||||
if ports is not None:
|
||||
ports = dict(copy.deepcopy(ports))
|
||||
self.ports = dict(copy.deepcopy(ports))
|
||||
else:
|
||||
self.ports = {}
|
||||
|
||||
self.annotations = annotations if annotations is not None else {}
|
||||
|
||||
|
@ -178,8 +178,8 @@ class Ref(
|
||||
def get_bounds(
|
||||
self,
|
||||
*,
|
||||
pattern: Optional[Pattern] = None,
|
||||
library: Optional[Mapping[str, Pattern]] = None,
|
||||
pattern: Optional['Pattern'] = None,
|
||||
library: Optional[Mapping[str, 'Pattern']] = None,
|
||||
) -> Optional[NDArray[numpy.float64]]:
|
||||
"""
|
||||
Return a `numpy.ndarray` containing `[[x_min, y_min], [x_max, y_max]]`, corresponding to the
|
||||
|
Loading…
Reference in New Issue
Block a user