whitespace

nolock
jan 2 years ago
parent 75adceda8b
commit e0fad680a1

@ -267,10 +267,12 @@ def _read_block(block, clean_vertices: bool) -> Pattern:
} }
if 'column_count' in attr: if 'column_count' in attr:
args['repetition'] = Grid(a_vector=(attr['column_spacing'], 0), args['repetition'] = Grid(
b_vector=(0, attr['row_spacing']), a_vector=(attr['column_spacing'], 0),
a_count=attr['column_count'], b_vector=(0, attr['row_spacing']),
b_count=attr['row_count']) a_count=attr['column_count'],
b_count=attr['row_count'],
)
pat.subpatterns.append(SubPattern(**args)) pat.subpatterns.append(SubPattern(**args))
else: else:
logger.warning(f'Ignoring DXF element {element.dxftype()} (not implemented).') logger.warning(f'Ignoring DXF element {element.dxftype()} (not implemented).')

@ -114,9 +114,11 @@ def write(
patterns = [p.wrap_repeated_shapes() for p in patterns] patterns = [p.wrap_repeated_shapes() for p in patterns]
# Create library # Create library
header = klamath.library.FileHeader(name=library_name.encode('ASCII'), header = klamath.library.FileHeader(
user_units_per_db_unit=logical_units_per_unit, name=library_name.encode('ASCII'),
meters_per_db_unit=meters_per_unit) user_units_per_db_unit=logical_units_per_unit,
meters_per_db_unit=meters_per_unit,
)
header.write(stream) header.write(stream)
# Get a dict of id(pattern) -> pattern # Get a dict of id(pattern) -> pattern
@ -241,10 +243,11 @@ def _read_header(stream: BinaryIO) -> Dict[str, Any]:
""" """
header = klamath.library.FileHeader.read(stream) header = klamath.library.FileHeader.read(stream)
library_info = {'name': header.name.decode('ASCII'), library_info = {
'meters_per_unit': header.meters_per_db_unit, 'name': header.name.decode('ASCII'),
'logical_units_per_unit': header.user_units_per_db_unit, 'meters_per_unit': header.meters_per_db_unit,
} 'logical_units_per_unit': header.user_units_per_db_unit,
}
return library_info return library_info
@ -276,10 +279,12 @@ def read_elements(
path = _gpath_to_mpath(element, raw_mode) path = _gpath_to_mpath(element, raw_mode)
pat.shapes.append(path) pat.shapes.append(path)
elif isinstance(element, klamath.elements.Text): elif isinstance(element, klamath.elements.Text):
label = Label(offset=element.xy.astype(float), label = Label(
layer=element.layer, offset=element.xy.astype(float),
string=element.string.decode('ASCII'), layer=element.layer,
annotations=_properties_to_annotations(element.properties)) string=element.string.decode('ASCII'),
annotations=_properties_to_annotations(element.properties),
)
pat.labels.append(label) pat.labels.append(label)
elif isinstance(element, klamath.elements.Reference): elif isinstance(element, klamath.elements.Reference):
pat.subpatterns.append(_ref_to_subpat(element)) pat.subpatterns.append(_ref_to_subpat(element))
@ -314,16 +319,22 @@ def _ref_to_subpat(ref: klamath.library.Reference) -> SubPattern:
a_count, b_count = ref.colrow a_count, b_count = ref.colrow
a_vector = (xy[1] - offset) / a_count a_vector = (xy[1] - offset) / a_count
b_vector = (xy[2] - offset) / b_count b_vector = (xy[2] - offset) / b_count
repetition = Grid(a_vector=a_vector, b_vector=b_vector, repetition = Grid(
a_count=a_count, b_count=b_count) a_vector=a_vector,
b_vector=b_vector,
a_count=a_count,
b_count=b_count,
)
subpat = SubPattern(pattern=None, subpat = SubPattern(
offset=offset, pattern=None,
rotation=numpy.deg2rad(ref.angle_deg), offset=offset,
scale=ref.mag, rotation=numpy.deg2rad(ref.angle_deg),
mirrored=(ref.invert_y, False), scale=ref.mag,
annotations=_properties_to_annotations(ref.properties), mirrored=(ref.invert_y, False),
repetition=repetition) annotations=_properties_to_annotations(ref.properties),
repetition=repetition,
)
subpat.identifier = (ref.struct_name.decode('ASCII'),) subpat.identifier = (ref.struct_name.decode('ASCII'),)
return subpat return subpat
@ -334,26 +345,28 @@ def _gpath_to_mpath(gpath: klamath.library.Path, raw_mode: bool) -> Path:
else: else:
raise PatternError(f'Unrecognized path type: {gpath.path_type}') raise PatternError(f'Unrecognized path type: {gpath.path_type}')
mpath = Path(vertices=gpath.xy.astype(float), mpath = Path(
layer=gpath.layer, vertices=gpath.xy.astype(float),
width=gpath.width, layer=gpath.layer,
cap=cap, width=gpath.width,
offset=numpy.zeros(2), cap=cap,
annotations=_properties_to_annotations(gpath.properties), offset=numpy.zeros(2),
raw=raw_mode, annotations=_properties_to_annotations(gpath.properties),
) raw=raw_mode,
)
if cap == Path.Cap.SquareCustom: if cap == Path.Cap.SquareCustom:
mpath.cap_extensions = gpath.extension mpath.cap_extensions = gpath.extension
return mpath return mpath
def _boundary_to_polygon(boundary: klamath.library.Boundary, raw_mode: bool) -> Polygon: def _boundary_to_polygon(boundary: klamath.library.Boundary, raw_mode: bool) -> Polygon:
return Polygon(vertices=boundary.xy[:-1].astype(float), return Polygon(
layer=boundary.layer, vertices=boundary.xy[:-1].astype(float),
offset=numpy.zeros(2), layer=boundary.layer,
annotations=_properties_to_annotations(boundary.properties), offset=numpy.zeros(2),
raw=raw_mode, annotations=_properties_to_annotations(boundary.properties),
) raw=raw_mode,
)
def _subpatterns_to_refs(subpatterns: List[SubPattern]) -> List[klamath.library.Reference]: def _subpatterns_to_refs(subpatterns: List[SubPattern]) -> List[klamath.library.Reference]:
@ -377,31 +390,37 @@ def _subpatterns_to_refs(subpatterns: List[SubPattern]) -> List[klamath.library.
rep.a_vector * rep.a_count, rep.a_vector * rep.a_count,
b_vector * b_count, b_vector * b_count,
] ]
aref = klamath.library.Reference(struct_name=encoded_name, aref = klamath.library.Reference(
xy=numpy.round(xy).astype(int), struct_name=encoded_name,
colrow=(numpy.round(rep.a_count), numpy.round(rep.b_count)), xy=numpy.round(xy).astype(int),
angle_deg=angle_deg, colrow=(numpy.round(rep.a_count), numpy.round(rep.b_count)),
invert_y=mirror_across_x, angle_deg=angle_deg,
mag=subpat.scale, invert_y=mirror_across_x,
properties=properties) mag=subpat.scale,
properties=properties,
)
refs.append(aref) refs.append(aref)
elif rep is None: elif rep is None:
ref = klamath.library.Reference(struct_name=encoded_name, ref = klamath.library.Reference(
xy=numpy.round([subpat.offset]).astype(int), struct_name=encoded_name,
colrow=None, xy=numpy.round([subpat.offset]).astype(int),
angle_deg=angle_deg, colrow=None,
invert_y=mirror_across_x, angle_deg=angle_deg,
mag=subpat.scale, invert_y=mirror_across_x,
properties=properties) mag=subpat.scale,
properties=properties,
)
refs.append(ref) refs.append(ref)
else: else:
new_srefs = [klamath.library.Reference(struct_name=encoded_name, new_srefs = [klamath.library.Reference(
xy=numpy.round([subpat.offset + dd]).astype(int), struct_name=encoded_name,
colrow=None, xy=numpy.round([subpat.offset + dd]).astype(int),
angle_deg=angle_deg, colrow=None,
invert_y=mirror_across_x, angle_deg=angle_deg,
mag=subpat.scale, invert_y=mirror_across_x,
properties=properties) mag=subpat.scale,
properties=properties,
)
for dd in rep.displacements] for dd in rep.displacements]
refs += new_srefs refs += new_srefs
return refs return refs
@ -453,30 +472,36 @@ def _shapes_to_elements(
else: else:
extension = (0, 0) extension = (0, 0)
path = klamath.elements.Path(layer=(layer, data_type), path = klamath.elements.Path(
xy=xy, layer=(layer, data_type),
path_type=path_type, xy=xy,
width=width, path_type=path_type,
extension=extension, width=width,
properties=properties) extension=extension,
properties=properties,
)
elements.append(path) elements.append(path)
elif isinstance(shape, Polygon): elif isinstance(shape, Polygon):
polygon = shape polygon = shape
xy_closed = numpy.empty((polygon.vertices.shape[0] + 1, 2), dtype=numpy.int32) xy_closed = numpy.empty((polygon.vertices.shape[0] + 1, 2), dtype=numpy.int32)
numpy.rint(polygon.vertices + polygon.offset, out=xy_closed[:-1], casting='unsafe') numpy.rint(polygon.vertices + polygon.offset, out=xy_closed[:-1], casting='unsafe')
xy_closed[-1] = xy_closed[0] xy_closed[-1] = xy_closed[0]
boundary = klamath.elements.Boundary(layer=(layer, data_type), boundary = klamath.elements.Boundary(
xy=xy_closed, layer=(layer, data_type),
properties=properties) xy=xy_closed,
properties=properties,
)
elements.append(boundary) elements.append(boundary)
else: else:
for polygon in shape.to_polygons(): for polygon in shape.to_polygons():
xy_closed = numpy.empty((polygon.vertices.shape[0] + 1, 2), dtype=numpy.int32) xy_closed = numpy.empty((polygon.vertices.shape[0] + 1, 2), dtype=numpy.int32)
numpy.rint(polygon.vertices + polygon.offset, out=xy_closed[:-1], casting='unsafe') numpy.rint(polygon.vertices + polygon.offset, out=xy_closed[:-1], casting='unsafe')
xy_closed[-1] = xy_closed[0] xy_closed[-1] = xy_closed[0]
boundary = klamath.elements.Boundary(layer=(layer, data_type), boundary = klamath.elements.Boundary(
xy=xy_closed, layer=(layer, data_type),
properties=properties) xy=xy_closed,
properties=properties,
)
elements.append(boundary) elements.append(boundary)
return elements return elements
@ -487,16 +512,18 @@ def _labels_to_texts(labels: List[Label]) -> List[klamath.elements.Text]:
properties = _annotations_to_properties(label.annotations, 128) properties = _annotations_to_properties(label.annotations, 128)
layer, text_type = _mlayer2gds(label.layer) layer, text_type = _mlayer2gds(label.layer)
xy = numpy.round([label.offset]).astype(int) xy = numpy.round([label.offset]).astype(int)
text = klamath.elements.Text(layer=(layer, text_type), text = klamath.elements.Text(
xy=xy, layer=(layer, text_type),
string=label.string.encode('ASCII'), xy=xy,
properties=properties, string=label.string.encode('ASCII'),
presentation=0, # TODO maybe set some of these? properties=properties,
angle_deg=0, presentation=0, # TODO maybe set some of these?
invert_y=False, angle_deg=0,
width=0, invert_y=False,
path_type=0, width=0,
mag=1) path_type=0,
mag=1,
)
texts.append(text) texts.append(text)
return texts return texts

@ -285,11 +285,13 @@ def read(
if isinstance(element, fatrec.Polygon): if isinstance(element, fatrec.Polygon):
vertices = numpy.cumsum(numpy.vstack(((0, 0), element.get_point_list())), axis=0) vertices = numpy.cumsum(numpy.vstack(((0, 0), element.get_point_list())), axis=0)
annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings) annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings)
poly = Polygon(vertices=vertices, poly = Polygon(
layer=element.get_layer_tuple(), vertices=vertices,
offset=element.get_xy(), layer=element.get_layer_tuple(),
annotations=annotations, offset=element.get_xy(),
repetition=repetition) annotations=annotations,
repetition=repetition,
)
pat.shapes.append(poly) pat.shapes.append(poly)
@ -308,14 +310,16 @@ def read(
element.get_extension_end()[1])) element.get_extension_end()[1]))
annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings) annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings)
path = Path(vertices=vertices, path = Path(
layer=element.get_layer_tuple(), vertices=vertices,
offset=element.get_xy(), layer=element.get_layer_tuple(),
repetition=repetition, offset=element.get_xy(),
annotations=annotations, repetition=repetition,
width=element.get_half_width() * 2, annotations=annotations,
cap=cap, width=element.get_half_width() * 2,
**path_args) cap=cap,
**path_args,
)
pat.shapes.append(path) pat.shapes.append(path)
@ -323,12 +327,13 @@ def read(
width = element.get_width() width = element.get_width()
height = element.get_height() height = element.get_height()
annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings) annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings)
rect = Polygon(layer=element.get_layer_tuple(), rect = Polygon(
offset=element.get_xy(), layer=element.get_layer_tuple(),
repetition=repetition, offset=element.get_xy(),
vertices=numpy.array(((0, 0), (1, 0), (1, 1), (0, 1))) * (width, height), repetition=repetition,
annotations=annotations, vertices=numpy.array(((0, 0), (1, 0), (1, 1), (0, 1))) * (width, height),
) annotations=annotations,
)
pat.shapes.append(rect) pat.shapes.append(rect)
elif isinstance(element, fatrec.Trapezoid): elif isinstance(element, fatrec.Trapezoid):
@ -357,12 +362,13 @@ def read(
vertices[2, 0] -= b vertices[2, 0] -= b
annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings) annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings)
trapz = Polygon(layer=element.get_layer_tuple(), trapz = Polygon(
offset=element.get_xy(), layer=element.get_layer_tuple(),
repetition=repetition, offset=element.get_xy(),
vertices=vertices, repetition=repetition,
annotations=annotations, vertices=vertices,
) annotations=annotations,
)
pat.shapes.append(trapz) pat.shapes.append(trapz)
elif isinstance(element, fatrec.CTrapezoid): elif isinstance(element, fatrec.CTrapezoid):
@ -412,21 +418,24 @@ def read(
vertices[0, 1] += width vertices[0, 1] += width
annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings) annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings)
ctrapz = Polygon(layer=element.get_layer_tuple(), ctrapz = Polygon(
offset=element.get_xy(), layer=element.get_layer_tuple(),
repetition=repetition, offset=element.get_xy(),
vertices=vertices, repetition=repetition,
annotations=annotations, vertices=vertices,
) annotations=annotations,
)
pat.shapes.append(ctrapz) pat.shapes.append(ctrapz)
elif isinstance(element, fatrec.Circle): elif isinstance(element, fatrec.Circle):
annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings) annotations = properties_to_annotations(element.properties, lib.propnames, lib.propstrings)
circle = Circle(layer=element.get_layer_tuple(), circle = Circle(
offset=element.get_xy(), layer=element.get_layer_tuple(),
repetition=repetition, offset=element.get_xy(),
annotations=annotations, repetition=repetition,
radius=float(element.get_radius())) annotations=annotations,
radius=float(element.get_radius()),
)
pat.shapes.append(circle) pat.shapes.append(circle)
elif isinstance(element, fatrec.Text): elif isinstance(element, fatrec.Text):
@ -436,11 +445,13 @@ def read(
string = lib.textstrings[str_or_ref].string string = lib.textstrings[str_or_ref].string
else: else:
string = str_or_ref.string string = str_or_ref.string
label = Label(layer=element.get_layer_tuple(), label = Label(
offset=element.get_xy(), layer=element.get_layer_tuple(),
repetition=repetition, offset=element.get_xy(),
annotations=annotations, repetition=repetition,
string=string) annotations=annotations,
string=string,
)
pat.labels.append(label) pat.labels.append(label)
else: else:
@ -499,14 +510,16 @@ def _placement_to_subpat(placement: fatrec.Placement, lib: fatamorgana.OasisLayo
rotation = 0 rotation = 0
else: else:
rotation = numpy.deg2rad(float(placement.angle)) rotation = numpy.deg2rad(float(placement.angle))
subpat = SubPattern(offset=xy, subpat = SubPattern(
pattern=None, offset=xy,
mirrored=(placement.flip, False), pattern=None,
rotation=rotation, mirrored=(placement.flip, False),
scale=float(mag), rotation=rotation,
identifier=(name,), scale=float(mag),
repetition=repetition_fata2masq(placement.repetition), identifier=(name,),
annotations=annotations) repetition=repetition_fata2masq(placement.repetition),
annotations=annotations,
)
return subpat return subpat
@ -532,7 +545,8 @@ def _subpatterns_to_placements(
properties=annotations_to_properties(subpat.annotations), properties=annotations_to_properties(subpat.annotations),
x=offset[0], x=offset[0],
y=offset[1], y=offset[1],
repetition=frep) repetition=frep,
)
refs.append(ref) refs.append(ref)
return refs return refs
@ -551,13 +565,15 @@ def _shapes_to_elements(
if isinstance(shape, Circle): if isinstance(shape, Circle):
offset = numpy.round(shape.offset + rep_offset).astype(int) offset = numpy.round(shape.offset + rep_offset).astype(int)
radius = numpy.round(shape.radius).astype(int) radius = numpy.round(shape.radius).astype(int)
circle = fatrec.Circle(layer=layer, circle = fatrec.Circle(
datatype=datatype, layer=layer,
radius=radius, datatype=datatype,
x=offset[0], radius=radius,
y=offset[1], x=offset[0],
properties=properties, y=offset[1],
repetition=repetition) properties=properties,
repetition=repetition,
)
elements.append(circle) elements.append(circle)
elif isinstance(shape, Path): elif isinstance(shape, Path):
xy = numpy.round(shape.offset + shape.vertices[0] + rep_offset).astype(int) xy = numpy.round(shape.offset + shape.vertices[0] + rep_offset).astype(int)
@ -566,29 +582,32 @@ def _shapes_to_elements(
path_type = next(k for k, v in path_cap_map.items() if v == shape.cap) # reverse lookup path_type = next(k for k, v in path_cap_map.items() if v == shape.cap) # reverse lookup
extension_start = (path_type, shape.cap_extensions[0] if shape.cap_extensions is not None else None) extension_start = (path_type, shape.cap_extensions[0] if shape.cap_extensions is not None else None)
extension_end = (path_type, shape.cap_extensions[1] if shape.cap_extensions is not None else None) extension_end = (path_type, shape.cap_extensions[1] if shape.cap_extensions is not None else None)
path = fatrec.Path(layer=layer, path = fatrec.Path(
datatype=datatype, layer=layer,
point_list=deltas, datatype=datatype,
half_width=half_width, point_list=deltas,
x=xy[0], half_width=half_width,
y=xy[1], x=xy[0],
extension_start=extension_start, # TODO implement multiple cap types? y=xy[1],
extension_end=extension_end, extension_start=extension_start, # TODO implement multiple cap types?
properties=properties, extension_end=extension_end,
repetition=repetition, properties=properties,
) repetition=repetition,
)
elements.append(path) elements.append(path)
else: else:
for polygon in shape.to_polygons(): for polygon in shape.to_polygons():
xy = numpy.round(polygon.offset + polygon.vertices[0] + rep_offset).astype(int) xy = numpy.round(polygon.offset + polygon.vertices[0] + rep_offset).astype(int)
points = numpy.round(numpy.diff(polygon.vertices, axis=0)).astype(int) points = numpy.round(numpy.diff(polygon.vertices, axis=0)).astype(int)
elements.append(fatrec.Polygon(layer=layer, elements.append(fatrec.Polygon(
datatype=datatype, layer=layer,
x=xy[0], datatype=datatype,
y=xy[1], x=xy[0],
point_list=points, y=xy[1],
properties=properties, point_list=points,
repetition=repetition)) properties=properties,
repetition=repetition,
))
return elements return elements
@ -602,13 +621,15 @@ def _labels_to_texts(
repetition, rep_offset = repetition_masq2fata(label.repetition) repetition, rep_offset = repetition_masq2fata(label.repetition)
xy = numpy.round(label.offset + rep_offset).astype(int) xy = numpy.round(label.offset + rep_offset).astype(int)
properties = annotations_to_properties(label.annotations) properties = annotations_to_properties(label.annotations)
texts.append(fatrec.Text(layer=layer, texts.append(fatrec.Text(
datatype=datatype, layer=layer,
x=xy[0], datatype=datatype,
y=xy[1], x=xy[0],
string=label.string, y=xy[1],
properties=properties, string=label.string,
repetition=repetition)) properties=properties,
repetition=repetition,
))
return texts return texts
@ -648,10 +669,12 @@ def repetition_fata2masq(
) -> Optional[Repetition]: ) -> Optional[Repetition]:
mrep: Optional[Repetition] mrep: Optional[Repetition]
if isinstance(rep, fatamorgana.GridRepetition): if isinstance(rep, fatamorgana.GridRepetition):
mrep = Grid(a_vector=rep.a_vector, mrep = Grid(
b_vector=rep.b_vector, a_vector=rep.a_vector,
a_count=rep.a_count, b_vector=rep.b_vector,
b_count=rep.b_count) a_count=rep.a_count,
b_count=rep.b_count,
)
elif isinstance(rep, fatamorgana.ArbitraryRepetition): elif isinstance(rep, fatamorgana.ArbitraryRepetition):
displacements = numpy.cumsum(numpy.column_stack((rep.x_displacements, displacements = numpy.cumsum(numpy.column_stack((rep.x_displacements,
rep.y_displacements)), axis=0) rep.y_displacements)), axis=0)

@ -114,10 +114,12 @@ def build(
patterns = [p.wrap_repeated_shapes() for p in patterns] patterns = [p.wrap_repeated_shapes() for p in patterns]
# Create library # Create library
lib = gdsii.library.Library(version=600, lib = gdsii.library.Library(
name=library_name.encode('ASCII'), version=600,
logical_unit=logical_units_per_unit, name=library_name.encode('ASCII'),
physical_unit=meters_per_unit) logical_unit=logical_units_per_unit,
physical_unit=meters_per_unit,
)
# Get a dict of id(pattern) -> pattern # Get a dict of id(pattern) -> pattern
patterns_by_id = {id(pattern): pattern for pattern in patterns} patterns_by_id = {id(pattern): pattern for pattern in patterns}
@ -240,10 +242,11 @@ def read(
lib = gdsii.library.Library.load(stream) lib = gdsii.library.Library.load(stream)
library_info = {'name': lib.name.decode('ASCII'), library_info = {
'meters_per_unit': lib.physical_unit, 'name': lib.name.decode('ASCII'),
'logical_units_per_unit': lib.logical_unit, 'meters_per_unit': lib.physical_unit,
} 'logical_units_per_unit': lib.logical_unit,
}
raw_mode = True # Whether to construct shapes in raw mode (less error checking) raw_mode = True # Whether to construct shapes in raw mode (less error checking)
@ -261,9 +264,11 @@ def read(
pat.shapes.append(path) pat.shapes.append(path)
elif isinstance(element, gdsii.elements.Text): elif isinstance(element, gdsii.elements.Text):
label = Label(offset=element.xy.astype(float), label = Label(
layer=(element.layer, element.text_type), offset=element.xy.astype(float),
string=element.string.decode('ASCII')) layer=(element.layer, element.text_type),
string=element.string.decode('ASCII'),
)
pat.labels.append(label) pat.labels.append(label)
elif isinstance(element, (gdsii.elements.SRef, gdsii.elements.ARef)): elif isinstance(element, (gdsii.elements.SRef, gdsii.elements.ARef)):
@ -337,16 +342,22 @@ def _ref_to_subpat(
b_count = element.rows b_count = element.rows
a_vector = (element.xy[1] - offset) / a_count a_vector = (element.xy[1] - offset) / a_count
b_vector = (element.xy[2] - offset) / b_count b_vector = (element.xy[2] - offset) / b_count
repetition = Grid(a_vector=a_vector, b_vector=b_vector, repetition = Grid(
a_count=a_count, b_count=b_count) a_vector=a_vector,
b_vector=b_vector,
a_count=a_count,
b_count=b_count,
)
subpat = SubPattern(pattern=None, subpat = SubPattern(
offset=offset, pattern=None,
rotation=rotation, offset=offset,
scale=scale, rotation=rotation,
mirrored=(mirror_across_x, False), scale=scale,
annotations=_properties_to_annotations(element.properties), mirrored=(mirror_across_x, False),
repetition=repetition) annotations=_properties_to_annotations(element.properties),
repetition=repetition,
)
subpat.identifier = (element.struct_name,) subpat.identifier = (element.struct_name,)
return subpat return subpat
@ -357,14 +368,15 @@ def _gpath_to_mpath(element: gdsii.elements.Path, raw_mode: bool) -> Path:
else: else:
raise PatternError(f'Unrecognized path type: {element.path_type}') raise PatternError(f'Unrecognized path type: {element.path_type}')
args = {'vertices': element.xy.astype(float), args = {
'layer': (element.layer, element.data_type), 'vertices': element.xy.astype(float),
'width': element.width if element.width is not None else 0.0, 'layer': (element.layer, element.data_type),
'cap': cap, 'width': element.width if element.width is not None else 0.0,
'offset': numpy.zeros(2), 'cap': cap,
'annotations': _properties_to_annotations(element.properties), 'offset': numpy.zeros(2),
'raw': raw_mode, 'annotations': _properties_to_annotations(element.properties),
} 'raw': raw_mode,
}
if cap == Path.Cap.SquareCustom: if cap == Path.Cap.SquareCustom:
args['cap_extensions'] = numpy.zeros(2) args['cap_extensions'] = numpy.zeros(2)
@ -377,12 +389,13 @@ def _gpath_to_mpath(element: gdsii.elements.Path, raw_mode: bool) -> Path:
def _boundary_to_polygon(element: gdsii.elements.Boundary, raw_mode: bool) -> Polygon: def _boundary_to_polygon(element: gdsii.elements.Boundary, raw_mode: bool) -> Polygon:
args = {'vertices': element.xy[:-1].astype(float), args = {
'layer': (element.layer, element.data_type), 'vertices': element.xy[:-1].astype(float),
'offset': numpy.zeros(2), 'layer': (element.layer, element.data_type),
'annotations': _properties_to_annotations(element.properties), 'offset': numpy.zeros(2),
'raw': raw_mode, 'annotations': _properties_to_annotations(element.properties),
} 'raw': raw_mode,
}
return Polygon(**args) return Polygon(**args)
@ -409,18 +422,24 @@ def _subpatterns_to_refs(
rep.a_vector * rep.a_count, rep.a_vector * rep.a_count,
b_vector * b_count, b_vector * b_count,
] ]
ref = gdsii.elements.ARef(struct_name=encoded_name, ref = gdsii.elements.ARef(
xy=numpy.round(xy).astype(int), struct_name=encoded_name,
cols=numpy.round(rep.a_count).astype(int), xy=numpy.round(xy).astype(int),
rows=numpy.round(rep.b_count).astype(int)) cols=numpy.round(rep.a_count).astype(int),
rows=numpy.round(rep.b_count).astype(int),
)
new_refs = [ref] new_refs = [ref]
elif rep is None: elif rep is None:
ref = gdsii.elements.SRef(struct_name=encoded_name, ref = gdsii.elements.SRef(
xy=numpy.round([subpat.offset]).astype(int)) struct_name=encoded_name,
xy=numpy.round([subpat.offset]).astype(int),
)
new_refs = [ref] new_refs = [ref]
else: else:
new_refs = [gdsii.elements.SRef(struct_name=encoded_name, new_refs = [gdsii.elements.SRef(
xy=numpy.round([subpat.offset + dd]).astype(int)) struct_name=encoded_name,
xy=numpy.round([subpat.offset + dd]).astype(int),
)
for dd in rep.displacements] for dd in rep.displacements]
for ref in new_refs: for ref in new_refs:
@ -473,9 +492,11 @@ def _shapes_to_elements(
xy = numpy.round(shape.vertices + shape.offset).astype(int) xy = numpy.round(shape.vertices + shape.offset).astype(int)
width = numpy.round(shape.width).astype(int) width = numpy.round(shape.width).astype(int)
path_type = next(k for k, v in path_cap_map.items() if v == shape.cap) # reverse lookup path_type = next(k for k, v in path_cap_map.items() if v == shape.cap) # reverse lookup
path = gdsii.elements.Path(layer=layer, path = gdsii.elements.Path(
data_type=data_type, layer=layer,
xy=xy) data_type=data_type,
xy=xy,
)
path.path_type = path_type path.path_type = path_type
path.width = width path.width = width
path.properties = properties path.properties = properties
@ -484,9 +505,11 @@ def _shapes_to_elements(
for polygon in shape.to_polygons(): for polygon in shape.to_polygons():
xy_open = numpy.round(polygon.vertices + polygon.offset).astype(int) xy_open = numpy.round(polygon.vertices + polygon.offset).astype(int)
xy_closed = numpy.vstack((xy_open, xy_open[0, :])) xy_closed = numpy.vstack((xy_open, xy_open[0, :]))
boundary = gdsii.elements.Boundary(layer=layer, boundary = gdsii.elements.Boundary(
data_type=data_type, layer=layer,
xy=xy_closed) data_type=data_type,
xy=xy_closed,
)
boundary.properties = properties boundary.properties = properties
elements.append(boundary) elements.append(boundary)
return elements return elements
@ -498,10 +521,12 @@ def _labels_to_texts(labels: List[Label]) -> List[gdsii.elements.Text]:
properties = _annotations_to_properties(label.annotations, 128) properties = _annotations_to_properties(label.annotations, 128)
layer, text_type = _mlayer2gds(label.layer) layer, text_type = _mlayer2gds(label.layer)
xy = numpy.round([label.offset]).astype(int) xy = numpy.round([label.offset]).astype(int)
text = gdsii.elements.Text(layer=layer, text = gdsii.elements.Text(
text_type=text_type, layer=layer,
xy=xy, text_type=text_type,
string=label.string.encode('ASCII')) xy=xy,
string=label.string.encode('ASCII'),
)
text.properties = properties text.properties = properties
texts.append(text) texts.append(text)
return texts return texts

@ -34,10 +34,11 @@ class SubPattern(PositionableImpl, DoseableImpl, RotatableImpl, ScalableImpl, Mi
SubPattern provides basic support for nesting Pattern objects within each other, by adding SubPattern provides basic support for nesting Pattern objects within each other, by adding
offset, rotation, scaling, and associated methods. offset, rotation, scaling, and associated methods.
""" """
__slots__ = ('_pattern', __slots__ = (
'_mirrored', '_pattern',
'identifier', '_mirrored',
) 'identifier',
)
_pattern: Optional['Pattern'] _pattern: Optional['Pattern']
""" The `Pattern` being instanced """ """ The `Pattern` being instanced """

Loading…
Cancel
Save