def test_elem_cell(): c1 = spira.Cell(name='CellA') assert c1.name == 'CellA' assert len(c1.ports) == 0 assert len(c1.elementals) == 0 c1.ports += spira.Port(name='P1') assert len(c1.ports) == 1 c1.elementals += spira.Polygon(shape=[[[0, 0], [1, 0], [1, 1], [0, 1]]]) assert len(c1.elementals) == 1 c1.center = (0, 0) np.testing.assert_array_equal(c1.center, [0, 0]) c1.move(midpoint=c1.center, destination=(5, 0)) np.testing.assert_array_equal(c1.center, [5, 0]) class CellB(spira.Cell): def create_elementals(self, elems): elems += spira.Polygon(shape=[[[0, 0], [3, 0], [3, 1], [0, 1]]], gds_layer=spira.Layer(number=77)) return elems c2 = CellB() assert c2.name == 'CellB-0' assert len(c1.elementals) == 1 assert isinstance(c2.elementals[0], spira.Polygon)
def cut(ply, position, axis): import spira.all as spira plys = spira.ElementList() gp = ply.commit_to_gdspy() pl = gdspy.slice(objects=[gp], position=position, axis=axis) for p in pl: if len(p.polygons) > 0: plys += spira.Polygon(shape=p.polygons[0]) return plys
def parse(self): gdsii_lib = gdspy.GdsLibrary(name='SPiRA-cell') gdsii_lib.read_gds(self.file_name) top_level_gdspy_cells = gdsii_lib.top_level() if self.cell_name is not None: if self.cell_name not in gdsii_lib.cell_dict: error_message = "[SPiRA] import_gds() The requested gdspy_cell (named {}) is not present in file {}" raise ValueError(error_message.format(self.cell_name, self.file_name)) topgdspy_cell = gdsii_lib.cell_dict[self.cell_name] elif self.cell_name is None and len(top_level_gdspy_cells) == 1: topgdspy_cell = top_level_gdspy_cells[0] elif self.cell_name is None and len(top_level_gdspy_cells) > 1: # TODO: Add this to logger. print('Multiple toplevel gdspy_cells found:') for gdspy_cell in top_level_gdspy_cells: print(gdspy_cell) raise ValueError('[SPiRA] import_gds() There are multiple' + 'top-level gdspy_cells, you must specify self.cell_name' + 'to select of one of them') c2dmap = {} for gdspy_cell in gdsii_lib.cell_dict.values(): D = spira.Cell(name=gdspy_cell.name) for e in gdspy_cell.polygons: for i, p in enumerate(e.polygons): n = e.layers[i] d = e.datatypes[i] # print(n, d) layer = spira.Layer(number=int(n), datatype=int(d)) L = self.map_layer(layer) # print(L) # D += spira.Polygon(shape=p, layer=L) ply = spira.Polygon(shape=p, layer=L) # print(ply) D += ply # print(e.datatypes) # key = (e.layer) # # FIXME: Maybe check the datatype and add layer mapping. # for n, p in zip(e.layers, e.polygons): # layer = spira.Layer(number=int(n), datatype=int(0)) # L = self.map_layer(layer) # D += spira.Polygon(shape=p, layer=L) c2dmap.update({gdspy_cell: D}) for gdspy_cell in gdsii_lib.cell_dict.values(): self._create_references(gdspy_cell, c2dmap) # self._create_labels(gdspy_cell, c2dmap) return c2dmap[topgdspy_cell]
def import_gds(filename, cellname=None, flatten=False, pcell=True): """ """ gdsii_lib = gdspy.GdsLibrary(name='SPiRA-Cell') gdsii_lib.read_gds(filename) top_level_cells = gdsii_lib.top_level() if cellname is not None: if cellname not in gdsii_lib.cell_dict: raise ValueError("[SPiRA] import_gds() The requested cell " + "(named {}) is not present in file {}".format( cellname, filename)) topcell = gdsii_lib.cell_dict[cellname] elif cellname is None and len(top_level_cells) == 1: topcell = top_level_cells[0] elif cellname is None and len(top_level_cells) > 1: # TODO: Add this to logger. print('Multiple toplevel cells found:') for cell in top_level_cells: print(cell) raise ValueError('[SPiRA] import_gds() There are multiple' + 'top-level cells, you must specify cellname' + 'to select of one of them') cell_list = [] c2dmap = {} for cell in gdsii_lib.cell_dict.values(): D = spira.Cell(name=cell.name) for e in cell.polygons: # FIXME: Maybe check the datatype and add layer mapping. for n, p in zip(e.layers, e.polygons): layer = spira.Layer(number=int(n), datatype=0) D += spira.Polygon(shape=p, layer=layer) c2dmap.update({cell: D}) cell_list.append(cell) for cell in cell_list: wrap_references(cell, c2dmap) # wrap_labels(cell, c2dmap) top_spira_cell = c2dmap[topcell] if flatten == True: C = spira.Cell(name='import_gds') else: C = top_spira_cell if pcell is True: D = parameterize_cell(C) else: D = C return D
def _connect_boundary_edges(self, edges, overlap_edges): """ Connect the edges that falls on a shape boudnary, since there is no overlapping polygon in this case.""" if len(edges) > 0: e = spira.Polygon(alias='Dummy', shape=[], layer=RDD.PLAYER.METAL) overlap_edges[e] = [] for i, edge in enumerate(edges): if edge.layer.purpose == RDD.PURPOSE.PORT.OUTSIDE_EDGE_DISABLED: edge.pid = '{}'.format(e.shape.hash_string) edge.layer.purpose = RDD.PURPOSE.PORT.OUTSIDE_EDGE_ENABLED overlap_edges[e].append(edge)
def create_arrow(self): layer = PLayer(self.port.process, RDD.PURPOSE.PORT.DIRECTION) # w = self.port.length * 3 w = 0.01 # l = 2 # l = self.port.length * 3 l = 0.2 arrow_shape = shapes.ArrowShape(width=w, length=l, head=l * 0.2) p = spira.Polygon(shape=arrow_shape, layer=layer, enable_edges=False) T = transformation_from_vector(self.port) p.transform(T) return p
def create_elements(self, elems): points = [(10.0, 0.0), (15.0, 10.0), (0.0, 10.0), (0.0, 5.0), (-15.0, 5.0), (-5.0, 0.0), (-10.0, -10.0), (-5.0, -15.0), (10.0, -15.0), (5.0, -10.0), (5.0, -5.0)] s = spira.Shape(points=points) S1 = spira.Cell(name='shape', elements=spira.Polygon(shape=s, layer=spira.Layer(1))) # #translate a copy of the shape # t = s.move_copy((0.0, 20.0)) # S2 = Structure("shape_trans", Boundary(Layer(0), t)) # #rotate the shape (angle in degree) # t = s.rotate_copy((0.0, 0.0), 50) # S3 = Structure("shape_rot", Boundary(Layer(0), t)) # #scale the shape # t = s.magnify_copy((0.0, 0.0), 1.2) # S4 = Structure("shape_scale", Boundary(Layer(0), t)) # #stretch the shape horizontally and squeeze vertically # t = Stretch(stretch_center = (0.0, 0.0), stretch_factor = (1.5, 0.5))(s) # S5 = Structure("shape_stretch", Boundary(Layer(0), t)) # #fit the shape in a box # south_west = (-7.0, -7.0) # north_east = (7.0, 7.0) # t = ShapeFit(s, south_west, north_east) # S6 = Structure("shape_fit", Boundary(Layer(0), t)) # #create a shape which traces the contour with a certain line width # t = ShapePath(original_shape = s, path_width = 0.5) # S7 = Structure("ShapePath1", Boundary(Layer(0), t)) # t = ShapePathRounded(original_shape = s, path_width = 0.5) # S8 = Structure("ShapePath2", Boundary(Layer(0), t)) # #expand the shape with a certain distance # t = ShapeGrow(s, 1.0) # S9 = Structure("shape_grow", Boundary(Layer(1), t) + Boundary(Layer(0), s)) # #round the shape with a given radius # t = ShapeRound(original_shape = s, radius = 2.0) # S10 = Structure("shape_round", Boundary(Layer(1), t) + Boundary(Layer(0), s)) elems += [ spira.SRef(S1, (0.0, 200.0)), ] return elems
def create_elements(self, elems): group = spira.Group() group += spira.Rectangle(p1=(0, 0), p2=(10, 10), layer=spira.Layer(1)) group += spira.Rectangle(p1=(0, 15), p2=(10, 30), layer=spira.Layer(1)) group.transform(self.group_transform) elems += group bbox_shape = group.bbox_info.bounding_box(margin=1) elems += spira.Polygon(shape=bbox_shape, layer=spira.Layer(2)) return elems
def test_elem_polygon(): p1 = [[[0, 0], [3, 0], [3, 1], [0, 1]]] p2 = [[[4, 0], [7, 0], [7, 1], [4, 1]]] p3 = [[[8, 0], [11, 0], [11, 1], [8, 1]]] # Create polygon using class parameters. ply1 = spira.Polygon(p1) assert issubclass(type(ply1.shape), shapes.Shape) assert ply1.gds_layer.number == 0 assert ply1.gds_layer.datatype == 0 # Create polygon using new layer number. ply2 = spira.Polygon(shape=p2, gds_layer=spira.Layer(number=77)) assert issubclass(type(ply2.shape), shapes.Shape) assert ply2.gds_layer.number == 77 assert ply2.gds_layer.datatype == 0 # Create polygon using new shape, number and datatype. ply3 = spira.Polygon(shape=shapes.Shape(points=p3), gds_layer=spira.Layer(number=51, datatype=1)) assert issubclass(type(ply3.shape), shapes.Shape) assert ply3.gds_layer.number == 51 assert ply3.gds_layer.datatype == 1
def create_elements(self, elems): group = spira.Group() # group += spira.Rectangle(p1=(0,0), p2=(10,10), layer=spira.Layer(1)) # group += spira.Rectangle(p1=(0,15), p2=(10,30), layer=spira.Layer(1)) group += spira.Rectangle(p1=(0,0), p2=(10,10), layer=spira.RDD.PLAYER.M1.METAL) group += spira.Rectangle(p1=(0,15), p2=(10,30), layer=spira.RDD.PLAYER.M1.METAL) group.transform(spira.Rotation(-45)) elems += group bbox_shape = group.bbox_info.bounding_box(margin=1) # elems += spira.Polygon(shape=bbox_shape, layer=spira.Layer(2)) elems += spira.Polygon(shape=bbox_shape, layer=spira.RDD.PLAYER.M2.METAL) return elems
import spira.all as spira from spira.yevon.geometry import shapes # Boolean operations on the shapes # -------------------------------- s1 = shapes.CircleShape(box_size=(2, 2)) s2 = shapes.CircleShape(box_size=(2, 2), center=(1, 0)) p1 = spira.Polygon(shape=s1, layer=spira.Layer(1)) p2 = spira.Polygon(shape=s2, layer=spira.Layer(1)) elems = [p1, p2] for bs in s1 & s2: elems.append(spira.Polygon(shape=bs, layer=spira.Layer(2))) for bs in s1 - s2: elems.append(spira.Polygon(shape=bs, layer=spira.Layer(3))) for bs in s2 - s1: elems.append(spira.Polygon(shape=bs, layer=spira.Layer(4))) for bs in s1 | s2: elems.append(spira.Polygon(shape=bs, layer=spira.Layer(5))) # Boolean operations on the polygons # ---------------------------------- b_and = p1 & p2 for b in b_and: b.layer = spira.Layer(2) b_sub1 = p1 - p2 for b in b_sub1:
def create_elements(self, elems): shape = shapes.BoxShape(width=self.width, height=self.height) elems += spira.Polygon(shape=shape, layer=self.layer) return elems
def create_elementals(self, elems): points = [[0, 0], [2, 2], [2, 6], [-6, 6], [-6, -6], [-4, -4], [-4, 4], [0, 4]] elems += spira.Polygon(shape=points, layer=RDD.PLAYER.M2.METAL) elems += spira.Rectangle(p1=(-10, 2), p2=(-5, 4), layer=RDD.PLAYER.M2.METAL) return elems
def create_elements(self, elems): elems += spira.Polygon(shape=self.shape, layer=RDD.PLAYER.M1.METAL) return elems
def create_elementals(self, elems): elems += spira.Polygon(shape=[[[0, 0], [3, 0], [3, 1], [0, 1]]], gds_layer=spira.Layer(number=77)) return elems
def create_elements(self, elems): pts = [[0, 0], [2, 2], [2, 6], [-6, 6], [-6, -6], [-4, -4], [-4, 4], [0, 4]] shape = spira.Shape(points=pts) elems += spira.Polygon(shape=shape, layer=spira.Layer(1)) return elems
def create_elements(self, elems): poly = spira.Polygon(shape=self.route_shape, layer=self.layer, enable_edges=False) elems += poly return elems
# rect = spira.Polygon(shape=rect_shape, layer=spira.Layer(number=16)) # rect.center = (15,0) # cell += rect # box = spira.Polygon(shape=box_shape, layer=spira.Layer(number=17)) # box.center = (20,0) # cell += box # FIXME # basic = spira.Polygon(shape=basic_tri_shape, layer=spira.Layer(number=18)) # basic.center = (25,0) # cell += basic # FIXME # tri = spira.Polygon(shape=tri_shape, layer=spira.Layer(number=19)) # tri.center = (30,0) # cell += tri # FIXME # arrow = spira.Polygon(shape=arrow_shape, layer=spira.Layer(number=15)) # arrow.center = (10,0) # cell += arrow # NOTE: Advanced shapes ytron_shape = YtronShape() ytron = spira.Polygon(shape=ytron_shape, layer=spira.Layer(number=20)) ytron.center = (35, 0) cell += ytron cell.gdsii_output()
def create_elements(self, elems): w, l = self.width, self.length shape = spira.Shape(points=[[0, 0], [l, 0], [l, w], [0, w]]) elems += spira.Polygon(shape=shape, layer=spira.RDD.PLAYER.R1.METAL) return elems