def __init__(self, origin, trans_in=None): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.angle_connections = [] #list with angle of connecting elements self.connection_ptrs = [] # pointers to connected structures represented by their class instances ## MUST BE IMLPEMENTED END ## self.origin = origin self.metal_region = Region() self.empty_region = Region() self.metal_regions = {} self.empty_regions = {} self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = False self.empty_region.merged_semantics = False self.DCplxTrans_init = None self.ICplxTrans_init = None if( trans_in is not None ): # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if( isinstance( trans_in, DCplxTrans ) ): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans( trans_in ) elif( isinstance( trans_in, CplxTrans ) ): self.DCplxTrans_init = DCplxTrans().from_itrans( trans_in ) self.ICplxTrans_init = ICplxTrans().from_trans( trans_in ) elif( isinstance( trans_in, DTrans ) ): self.DCplxTrans_init = DCplxTrans( trans_in, 1 ) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans( trans_in ), 1 ) elif( isinstance( trans_in, Trans ) ): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans( trans_in ), 1 ) self.ICplxTrans_init = ICplxTrans( trans_in, 1 ) self._init_regions_trans()
def transform_layer(self, layer_i, trans, trans_ports=False): """ Performs transofmation of the layer desired. Parameters ---------- layer_i : int layer index, >0 trans : Union[DcplxTrans, DTrans] transformation to perform trans_ports : bool If `True` also performs transform of `self.sonnet_ports` as they are vectors. Returns ------- None """ r_cell = Region(self.cell.begin_shapes_rec(layer_i)) r_cell.transform(trans) temp_i = self.cell.layout().layer(pya.LayerInfo(PROGRAM.LAYER1_NUM, 0)) self.cell.shapes(temp_i).insert(r_cell) self.cell.layout().clear_layer(layer_i) self.cell.layout().move_layer(temp_i, layer_i) self.cell.layout().delete_layer(temp_i) if trans_ports: self.sonnet_ports = list( DSimplePolygon( self.sonnet_ports).transform(trans).each_point())
def init_regions(self): self.metal_regions["photo"] = Region() self.empty_regions["photo"] = Region() self.connections = [DPoint(0, 0), self.dr] self.start = DPoint(0, 0) self.end = self.start + self.dr alpha = atan2(self.dr.y, self.dr.x) self.angle_connections = [alpha, alpha] alpha_trans = ICplxTrans().from_dtrans( DCplxTrans(1, alpha * 180 / pi, False, self.start)) self.metal_regions['photo'].insert( pya.Box(Point().from_dpoint(DPoint(0, -self.width / 2)), Point().from_dpoint(DPoint(self.dr.abs(), self.width / 2)))) self.empty_regions['photo'].insert( pya.Box( Point().from_dpoint(DPoint(0, self.width / 2)), Point().from_dpoint( DPoint(self.dr.abs(), self.width / 2 + self.gap)))) self.empty_regions['photo'].insert( pya.Box( Point().from_dpoint(DPoint(0, -self.width / 2 - self.gap)), Point().from_dpoint(DPoint(self.dr.abs(), -self.width / 2)))) self.metal_regions['photo'].transform(alpha_trans) self.empty_regions['photo'].transform(alpha_trans) self.metal_region = self.metal_regions['photo'] self.empty_region = self.empty_regions['photo']
def init_regions(self): # photolitography regions self.metal_regions["photo"] = Region() self.empty_regions["el"] = Region() # electron-beam litography regions self.metal_regions["el"] = Region() self.empty_regions["photo"] = Region() self.metal_regions["photo"].insert(pya.Box().from_dbox(self.SQ1)) self.metal_regions["el"].insert(pya.Box().from_dbox(self.B1)) self.metal_regions["el"].insert(pya.Box().from_dbox(self.B2)) self.metal_regions["el"].insert(pya.Box().from_dbox(self.B3)) self.metal_regions["el"].insert(pya.Box().from_dbox(self.B4)) self.metal_regions["photo"].insert(pya.Box().from_dbox(self.SQ2)) self.metal_regions["el"].insert(SimplePolygon().from_dpoly( self.poly_1)) self.metal_regions["el"].insert(SimplePolygon().from_dpoly( self.poly_2)) self.metal_regions["el"].insert(SimplePolygon().from_dpoly( self.poly_3)) self.metal_regions[ "el"] = self.metal_regions["el"] + self._reg_tmp_to_metal self.metal_regions["el"].insert(SimplePolygon().from_dpoly( self.poly_5))
def __init__(self, origin, trans_in=None, inverse=False): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.connection_edges = [ ] # indexes of edges that are intended to connect to other polygons # indexes in "self.connection_edges" where Sonnet ports # should be placed self.sonnet_port_connections = [] self.angle_connections = [] # list with angle of connecting elements ## MUST BE IMLPEMENTED END ## self.connection_ptrs = [ ] # pointers to connected structures represented by their class instances self.origin = origin self.inverse = inverse # TODO: after Region.insert() and/or? metal_region + other_region # there is width problem that initial region has dimensions # Region().bbox() = ((-1,-1,1,1)) or something like that # Hence, if you wish to take Region.bbox() of the resulting region # You will get incorrect value due to initial region having # something "blank" at the creation moment. This may be solved # by either shrinking resulting region to shapes it contains, # or by refusing of usage of empty `Region()`s self.metal_region = Region() self.empty_region = Region() self.metal_regions = OrderedDict() self.empty_regions = OrderedDict() self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = True self.empty_region.merged_semantics = True self.DCplxTrans_init = None self.ICplxTrans_init = None if (trans_in is not None): # TODO: update with Klayouts new rules. # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if (isinstance(trans_in, DCplxTrans)): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans(trans_in) elif (isinstance(trans_in, CplxTrans)): self.DCplxTrans_init = DCplxTrans().from_itrans(trans_in) self.ICplxTrans_init = ICplxTrans().from_trans(trans_in) elif (isinstance(trans_in, DTrans)): self.DCplxTrans_init = DCplxTrans(trans_in, 1) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans(trans_in), 1) elif (isinstance(trans_in, Trans)): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans(trans_in), 1) self.ICplxTrans_init = ICplxTrans(trans_in, 1) elif (isinstance(trans_in, ICplxTrans)): # not tested 14.08.2021 self.DCplxTrans_init = DCplxTrans(trans_in) self.ICplxTrans_init = trans_in self._geometry_parameters = OrderedDict() self._init_regions_trans()
def __init__(self, cell_name="testScript"): """ Inherit this class for working on a chip design and override draw() method where other drawing methods should be called from call show() to draw everything str cell_name - name of a cell, e.g. 'testScript' Parameters ---------- cell_name : str name of cell design will be written into, e.g. 'testScript' """ # getting main references of the application self.app = pya.Application.instance() self.mw = self.app.main_window() self.lv = self.mw.current_view() self.cv = None self.cell = None # basic regions for sample self.region_ph = Region() self.region_el = Region() # this insures that lv and cv are valid objects if (self.lv == None): self.cv = self.mw.create_layout(1) self.lv = self.mw.current_view() else: self.cv = self.lv.active_cellview() # find or create the desired by programmer cell and layer self.layout = self.cv.layout() self.layout.dbu = 0.001 if (self.layout.has_cell(cell_name)): self.cell = self.layout.cell(cell_name) else: self.cell = self.layout.create_cell(cell_name) # basic layers for sample info = pya.LayerInfo(1, 0) info2 = pya.LayerInfo(2, 0) self.layer_ph = self.layout.layer(info) # photoresist layer self.layer_el = self.layout.layer(info2) # e-beam lithography layer # clear this cell and layer self.cell.clear() # setting layout view self.lv.select_cell(self.cell.cell_index(), 0) self.lv.add_missing_layers() # additinal variables for convinience self.origin = DPoint(0, 0) # design parameters that were passed to the last # self.draw(...) call are stored here as ordered dict self.design_pars = OrderedDict() self.sonnet_ports: list[DPoint] = []
def split_polygons(obj, max_pts=200, print_tree=False): """ Recursively splitting polygons in region or in polygons list until every resulted polygon has less than `max_pts` points. Parameters ---------- obj : Union[Region, List[Polygon]] Structure to operate on max_pts : int maximum points in each polygon Returns ------- Union[pya.Region, list[pya.Polygon]] Resulting structure that has the same type as input structure. """ # global split_shift_str if isinstance(obj, pya.Region): result_reg = Region() reg_to_split = obj # if print_tree: # print(split_shift_str + "got reg") for poly in reg_to_split: result_reg.insert(split_polygons([poly.dup()], max_pts, print_tree)) return result_reg elif isinstance(obj, list): if isinstance(obj[0], pya.Polygon): # if this is list of polygons polygons_list = obj # if print_tree: # print(split_shift_str + f"got array of {len(polygons_list)} polygons") resulting_polygons_list = [] for i, poly in enumerate(polygons_list): if poly.num_points() < max_pts: # if print_tree: # print(split_shift_str + f"polygon #{k} is ok") # recursion base (if all polygons satisfy this condition) resulting_polygons_list.append(poly) else: # if print_tree: # print(split_shift_str + f"polygon #{k} needs dividing") # split_shift_str += "\t" resulting_polygons_list.extend( split_polygons(poly.split(), max_pts, print_tree)) # if print_tree: # split_shift_str = split_shift_str[:-1] return resulting_polygons_list else: raise ValueError( "`split_polygons` function: List is supplied as argument, but this is not " "list of `pya.Polygon` objects") else: raise ValueError( "`split_polygons` function: Unknown argument received as `obj`" "only `pya.Region` or `list[pya.Polygons]` are supported")
def init_regions(self): origin = DPoint(0, 0) hor_box = DBox(origin - DPoint(self.l/2, self.t/2), DPoint(self.l/2, self.t/2)) vert_box = DBox(origin - DPoint(self.t/2, self.l/2), DPoint(self.t/2, self.l/2)) cross = (Region(hor_box) + Region(vert_box)).merge() #if self.inverse: # self.empty_region.insert(cross) #else: self.metal_region.insert(cross)
def extend_photo_overetching(self): tmp_reg = Region() ep = pya.EdgeProcessor() for poly in self.region_ph.each(): tmp_reg.insert( ep.simple_merge_p2p([ poly.sized(FABRICATION.OVERETCHING, FABRICATION.OVERETCHING, 2) ], False, False, 1)) self.region_ph = tmp_reg
def init_regions( self ): origin = DPoint(0,0) Rin = self.r - self.t Rout = self.r dpts_arr_Rout = [DPoint(Rout * cos(2 * pi * i / self.n_pts), Rout * sin(2 * pi * i / self.n_pts)) for i in range(0, self.n_pts)] dpts_arr_Rin = [DPoint(Rin * cos(2 * pi * i / self.n_pts), Rin * sin(2 * pi * i / self.n_pts)) for i in range(0, self.n_pts)] outer_circle = Region(SimplePolygon().from_dpoly(DSimplePolygon(dpts_arr_Rout))) inner_circle = Region(SimplePolygon().from_dpoly(DSimplePolygon(dpts_arr_Rin))) ring = outer_circle - inner_circle #self.metal_region.insert(ring) #if self.inverse: self.empty_region = ring
def fill_poly(poly): bbox = poly.bbox() poly_reg = Region(poly) t_reg = Region() # Draw boundary around holes in the polygon for hole_i in range(0, poly.holes()): points = [p for p in poly.each_point_hole(hole_i)] points.append(points[0]) boundary = Path(points, 2 * d) poly_reg -= Region(boundary) # Draw boundary around the outer edge of the polygon points = [p for p in poly.each_point_hull()] points.append(points[0]) boundary = Path(points, 2 * d) poly_reg -= Region(boundary) # Fill the boundary box with holes y = bbox.p1.y + height while y < bbox.p2.y - height: x = bbox.p1.x + width while x < bbox.p2.x - width: box = pya.Box().from_dbox( pya.DBox(DPoint(x, y), DPoint(x + width, y + height))) x += dx t_reg.insert(box) y += dy # Select only inner holes holes_inside = t_reg.select_inside(poly_reg) for box in holes_inside.each(): poly.insert_hole(list(box.each_point_hull())) return poly
def fill_holes(obj, dx=10e3, dy=8e3, width=5e3, height=5e3, d=0): if (obj.is_cell_inst()): return None poly = obj.shape.polygon bbox = poly.bbox() poly_reg = Region(poly) t_reg = Region() y = bbox.p1.y + height while (y < bbox.p2.y - height): x = bbox.p1.x + width while (x < bbox.p2.x - width): box = pya.Box().from_dbox( pya.DBox(DPoint(x, y), DPoint(x + width, y + height))) x += dx t_reg.clear() t_reg.insert(box) qwe = t_reg.select_inside(poly_reg) if (qwe.is_empty()): continue edge_pairs = qwe.inside_check(poly_reg, d) if (edge_pairs.is_empty()): poly.insert_hole(box) y += dy obj.shape.polygon = poly
def draw(self): info_bridges1 = pya.LayerInfo(3, 0) # bridge photo layer 1 self.region_bridges1 = Region() self.layer_bridges1 = self.layout.layer(info_bridges1) info_bridges2 = pya.LayerInfo(4, 0) # bridge photo layer 2 self.region_bridges2 = Region() self.layer_bridges2 = self.layout.layer(info_bridges2) self.lv.add_missing_layers() self.draw_chip() self.draw_arc() self.bridgify_arc()
class MyDesign(ChipDesign): def draw(self): info_bridges1 = pya.LayerInfo(3, 0) # bridge photo layer 1 self.region_bridges1 = Region() self.layer_bridges1 = self.layout.layer(info_bridges1) info_bridges2 = pya.LayerInfo(4, 0) # bridge photo layer 2 self.region_bridges2 = Region() self.layer_bridges2 = self.layout.layer(info_bridges2) self.lv.add_missing_layers() self.draw_chip() self.draw_arc() self.bridgify_arc() def draw_chip(self): self.chip = CHIP_10x10_12pads self.chip_box: pya.DBox = self.chip.box self.region_bridges2.insert(self.chip_box) self.region_ph.insert(self.chip_box) def draw_arc(self): self.Z0 = CPWParameters(200e3, 100e3) cpw_start = (self.chip_box.p1 + self.chip_box.p2)/2 self.arc = CPWArc( z0=self.Z0, start=cpw_start, R=1.2e6, delta_alpha=5/4*np.pi, trans_in=DTrans.R0 ) self.arc.place(self.region_ph) def bridgify_arc(self): print(isinstance(self.arc, CPWArc)) print(type(self.arc)) Bridge1.bridgify_CPW( self.arc, bridges_step=100e3, dest=self.region_bridges1, dest2=self.region_bridges2, ) def _transfer_regs2cell(self): self.cell.shapes(self.layer_ph).insert(self.region_ph) self.cell.shapes(self.layer_el).insert(self.region_el) self.cell.shapes(self.layer_bridges1).insert(self.region_bridges1) self.cell.shapes(self.layer_bridges2).insert(self.region_bridges2) self.lv.zoom_fit()
def init_regions(self): self.metal_regions["bridges"] = Region() self.metal_regions["bridge_patches"] = Region() self.empty_regions["bridges"] = Region() self.empty_regions["bridge_patches"] = Region() patch_x = 20e3 patch_y = 10e3 patch_pos_y = 35e3 l1 = 23e3 l2 = 8e3 l3 = 22e3 w = 20e3 bridge_points = [ DPoint(-w / 2, l1), DPoint(-w / 2 - l2, l1 + l2), DPoint(-w / 2 - l2, l1 + l2 + l3), DPoint(w / 2 + l2, l1 + l2 + l3), DPoint(w / 2 + l2, l1 + l2), DPoint(w / 2, l1), DPoint(w / 2, -l1), DPoint(w / 2 + l2, -l1 - l2), DPoint(w / 2 + l2, -l1 - l2 - l3), DPoint(-w / 2 - l2, -l1 - l2 - l3), DPoint(-w / 2 - l2, -l1 - l2), DPoint(-w / 2, -l1) ] bridge_poly = DSimplePolygon(bridge_points) self.metal_regions["bridges"].insert(bridge_poly) rec1_points = [ DPoint(patch_x / 2, patch_pos_y), DPoint(patch_x / 2, patch_pos_y + patch_y), DPoint(-patch_x / 2, patch_pos_y + patch_y), DPoint(-patch_x / 2, patch_pos_y) ] rec2_points = [ DPoint(patch_x / 2, -patch_pos_y), DPoint(patch_x / 2, -(patch_pos_y + patch_y)), DPoint(-patch_x / 2, -(patch_pos_y + patch_y)), DPoint(-patch_x / 2, -patch_pos_y) ] rec1_poly = DSimplePolygon(rec1_points) rec2_poly = DSimplePolygon(rec2_points) self.metal_regions["bridge_patches"].insert(rec1_poly) self.metal_regions["bridge_patches"].insert(rec2_poly)
def __init__(self, Z0, start, L_coupling, L1, r, L2, N, gnd_width, trans_in=None): self.Z0 = Z0 self.gnd_width = gnd_width self.L_coupling = L_coupling self.L1 = L1 self.r = r self.L2 = L2 self.N = N self.primitives_gnd = {} super(EMResonator_TL2Qbit_worm, self).__init__(start, trans_in) self.init_primitives_gnd_trans() self.gnd_reg = Region() for elem in self.primitives_gnd.values(): self.gnd_reg = self.gnd_reg + elem.metal_region for i in range(self.N): for elem in self.primitives["coil" + str(i + 1)].primitives_gnd.values(): elem.make_trans(self.DCplxTrans_init) elem.make_trans(DCplxTrans(1, 0, False, self.origin)) self.gnd_reg = self.gnd_reg + elem.metal_region self.start = self.connections[0] self.end = self.connections[-1] self.dr = self.end - self.start self.alpha_start = self.angle_connections[0] self.alpha_end = self.angle_connections[1]
def __init__(self, origin, trans_in=None, inverse=False): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.connection_edges = [ ] # indexes of edges that are intended to connect to other polygons # indexes in "self.connection_edges" where Sonnet ports # should be placed self.sonnet_port_connections = [] self.angle_connections = [] # list with angle of connecting elements ## MUST BE IMLPEMENTED END ## self.connection_ptrs = [ ] # pointers to connected structures represented by their class instances self.origin = origin self.inverse = inverse self.metal_region = Region() self.empty_region = Region() self.metal_regions = OrderedDict() self.empty_regions = OrderedDict() self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = True self.empty_region.merged_semantics = True self.DCplxTrans_init = None self.ICplxTrans_init = None if (trans_in is not None): # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if (isinstance(trans_in, DCplxTrans)): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans(trans_in) elif (isinstance(trans_in, CplxTrans)): self.DCplxTrans_init = DCplxTrans().from_itrans(trans_in) self.ICplxTrans_init = ICplxTrans().from_trans(trans_in) elif (isinstance(trans_in, DTrans)): self.DCplxTrans_init = DCplxTrans(trans_in, 1) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans(trans_in), 1) elif (isinstance(trans_in, Trans)): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans(trans_in), 1) self.ICplxTrans_init = ICplxTrans(trans_in, 1) self._geometry_parameters = OrderedDict() self._init_regions_trans()
def init_regions(self): if self._ebeam: dw = 2e3 * 4 else: dw = 3e3 * 4 w = 2e3 * 4 l = (w * 7 + dw * 6) / 2 lengths = [ 3e3 * 4, 6e3 * 4, 8e3 * 4, 9e3 * 4, 8e3 * 4, 6e3 * 4, 3e3 * 4 ] empty_points = [ DPoint(0, -l), DPoint(0, l), DPoint(9e3 * 4, l), DPoint(9e3 * 4, -l) ] empty_poly = DSimplePolygon(empty_points) empty_region = Region(empty_poly) l0 = -l metal_region = Region(DSimplePolygon([])) for l1 in lengths: metal1 = Region( DSimplePolygon([ DPoint(0, l0), DPoint(0, l0 + w), DPoint(l1, l0 + w), DPoint(l1, l0) ])) metal_region += metal1 l0 = l0 + w + dw self.metal_region.insert(metal_region) self.empty_region.insert(empty_region - metal_region) self.connections = [DPoint(0, 0), DPoint(0, 0)] self.angle_connections = [pi, 0]
def init_regions(self): bridge_length = 85e3 bridge_width = 20e3 patch_width = 40e3 patch_length = 30e3 bridge = Box(DPoint(-bridge_width / 2, -bridge_length / 2), DPoint(bridge_width / 2, bridge_length / 2)) patch1 = Box(DPoint(-patch_width / 2, -bridge_length / 2 - patch_length / 3), DPoint(patch_width / 2, -bridge_length / 2 + 2 * patch_length / 3)) patch2 = Box(DPoint(-patch_width / 2, bridge_length / 2 + patch_length / 3), DPoint(patch_width / 2, bridge_length / 2 - 2 * patch_length / 3)) self.metal_regions["bridges"] = Region(bridge) self.metal_regions["bridge_patches"] = Region(patch1) + Region(patch2) self.empty_regions["bridges"] = Region() self.empty_regions["bridge_patches"] = Region()
def send_polygons(self, cell, layer_i=-1): if (layer_i == -1): # cell is a Region() r_cell = cell else: r_cell = Region(cell.begin_shapes_rec(layer_i)) for poly in r_cell: # print("sending polygon") self.send_polygon(poly.resolved_holes())
def draw_pinning_holes(self): selection_region = Region( pya.Box(Point(100e3, 100e3), Point(101e3, 101e3))) tmp_ph = self.region_ph.dup() other_regs = tmp_ph.select_not_interacting(selection_region) reg_to_fill = self.region_ph.select_interacting(selection_region) filled_reg = fill_holes(reg_to_fill) self.region_ph = filled_reg + other_regs
def __erase_in_layer(self, layer, box): reg_l = self._reg_from_layer(layer) box_reg = Region(box) reg_l &= box_reg temp_i = self.cell.layout().layer(pya.LayerInfo(PROGRAM.LAYER1_NUM, 0)) self.cell.shapes(temp_i).insert(reg_l) self.cell.layout().clear_layer(layer) self.cell.layout().move_layer(temp_i, layer) self.cell.layout().delete_layer(temp_i)
def init_regions(self): ll = DPoint(-self._s_l / 2, -self._s_w / 2) ur = DPoint(self._s_l / 2, self._s_w / 2) self.metal_region.insert(Box(DBox(ll, ur))) ll = DPoint(-(self._s_l + self._gap_l) / 2, -(self._s_w + self._gap_w) / 2) ur = DPoint((self._s_l + self._gap_l) / 2, (self._s_w + self._gap_w) / 2) protect_reg = Region(Box(DBox(ll, ur))) empty_region = protect_reg - self.metal_region self.empty_region.insert(empty_region) self.connections = [DPoint(0, 0)]
def inverse_destination(self, dest: Union[Region, Cell], layer_i: int = -1): """ Inverses empty regions and solid polygons on the given destination `dest` and `layer`. If layer is not specified, destination `dest` is interpreted as `pya.Region` instance. Otherwise, `dest` is interpreted as `pya.Cell` instance Parameters ---------- dest : Union[Region, Cell] destination, interpreted either as Region or Cell instances depending on whether layer was provided layer_i : Optional[int] positive layer index. Returns ------- None """ tmp_reg = Region() tmp_reg.insert(self.chip_box) if layer_i == -1: dest_reg = dest dest_reg ^= tmp_reg else: r_cell = Region(dest.begin_shapes_rec(layer_i)) r_cell ^= tmp_reg temp_layer_i = dest.layout().layer( pya.LayerInfo(PROGRAM.LAYER1_NUM, 0)) # Moving layers. # Due to internal representation, region polygons are actually # point to polygons in a cell. So we can dest.shapes(temp_layer_i).insert(r_cell) dest.layout().clear_layer(layer_i) dest.layout().move_layer(temp_layer_i, layer_i) dest.layout().delete_layer(temp_layer_i)
def __init__(self, cell_name): # getting main references of the application app = pya.Application.instance() mw = app.main_window() self.lv = mw.current_view() self.cv = None self.cell = None self.region_ph = Region() self.region_el = Region() #this insures that lv and cv are valid objects if (self.lv == None): self.cv = mw.create_layout(1) self.lv = mw.current_view() else: self.cv = self.lv.active_cellview() # find or create the desired by programmer cell and layer layout = self.cv.layout() layout.dbu = 0.001 if (layout.has_cell(cell_name)): self.cell = layout.cell(cell_name) else: self.cell = layout.create_cell(cell_name) info = pya.LayerInfo(1, 0) info2 = pya.LayerInfo(2, 0) self.layer_ph = layout.layer(info) # photoresist layer self.layer_el = layout.layer(info2) # e-beam lithography layer # clear this cell and layer self.cell.clear() # setting layout view self.lv.select_cell(self.cell.cell_index(), 0) self.lv.add_missing_layers() # design parameters that were passed to the last # self.draw(...) call are stored here as ordered dict self.design_pars = OrderedDict()
def extended_region(reg, extension=0): """ extends region in outer direction by `extension` value. extension is orthogonal to region`s polygons edges. Parameters ---------- reg : Region pya.Region instance extension : float extension in nm Returns ------- Region extended version of region """ tmp_reg = Region() ep = pya.EdgeProcessor() for poly in reg.each(): tmp_reg.insert( ep.simple_merge_p2p([poly.sized(extension, extension, 2)], False, False, 1)) return tmp_reg
def init_regions(self): self.metal_regions["photo"] = Region() self.empty_regions["photo"] = Region() self.metal_regions["bridges"] = Region() self.empty_regions["bridges"] = Region() self.metal_regions["bridge_patches"] = Region() self.empty_regions["bridge_patches"] = Region() self.connections = [DPoint(0, 0), self.dr] self.start = DPoint(0, 0) self.end = self.start + self.dr alpha = atan2(self.dr.y, self.dr.x) self.angle_connections = [alpha, alpha] alpha_trans = ICplxTrans().from_dtrans( DCplxTrans(1, alpha * 180 / pi, False, self.start)) self.metal_regions["photo"].insert( pya.Box(Point().from_dpoint(DPoint(0, -self.width / 2)), Point().from_dpoint(DPoint(self.dr.abs(), self.width / 2)))) self.empty_regions["photo"].insert( pya.Box( Point().from_dpoint(DPoint(0, self.width / 2)), Point().from_dpoint( DPoint(self.dr.abs(), self.width / 2 + self.gap)))) self.empty_regions["photo"].insert( pya.Box( Point().from_dpoint(DPoint(0, -self.width / 2 - self.gap)), Point().from_dpoint(DPoint(self.dr.abs(), -self.width / 2)))) self.metal_regions["photo"].transform(alpha_trans) self.empty_regions["photo"].transform(alpha_trans) if self.dr.x == 0: N_bridges = int((self.dr.y - self._bridge_interval) // self._bridge_interval + 1) for i in range(N_bridges): ab = Airbridge(self.start + DPoint( 0, (self._bridge_interval / 2 + i * self._bridge_interval) * sign(self.dr.y)), trans_in=DTrans.R90) self.metal_regions["bridges"] += ab.metal_regions["bridges"] self.metal_regions["bridges"] += ab.metal_regions[ "bridge_patches"] elif self.dr.y == 0: N_bridges = int((self.dr.x - self._bridge_interval) // self._bridge_interval + 1) print("N_bridges", N_bridges) for i in range(N_bridges): bridge_pos = self.start + DPoint( (self._bridge_interval / 2 + i * self._bridge_interval) * sign(self.dr.x), 0) ab = Airbridge(bridge_pos, trans_in=None) self.metal_regions["bridges"] += ab.metal_regions["bridges"] self.metal_regions["bridge_patches"] += ab.metal_regions[ "bridge_patches"]
def init_regions(self): w_res, g_res = self._resonator_cpw_params.width, self._resonator_cpw_params.gap w_protect_pad = self._w_claw_pad + g_res * 2 protect_aperture = self._claw_aperture + 2 * self._w_thin_ground protect_width = protect_aperture + 2 * w_protect_pad l_claw_pad = self._l_claw_pad w_claw = self._w_claw protect_points = [ DPoint(0, -g_res), DPoint(-protect_width / 2, -g_res), DPoint(-protect_width / 2, w_claw + l_claw_pad + g_res), DPoint(-protect_width / 2 + w_protect_pad, w_claw + l_claw_pad + g_res), DPoint(-protect_width / 2 + w_protect_pad, w_claw + g_res), DPoint(protect_width / 2 - w_protect_pad, w_claw + g_res), DPoint(protect_width / 2 - w_protect_pad, w_claw + l_claw_pad + g_res), DPoint(protect_width / 2, w_claw + l_claw_pad + g_res), DPoint(protect_width / 2, -g_res) ] protect_region = Region(DSimplePolygon(protect_points)) metal_points = [ DPoint(0, 0), DPoint(-protect_width / 2 + g_res, 0), DPoint(-protect_width / 2 + g_res, w_claw + l_claw_pad), DPoint(-protect_width / 2 + w_protect_pad - g_res, w_claw + l_claw_pad), DPoint(-protect_width / 2 + w_protect_pad - g_res, w_claw), DPoint(protect_width / 2 - w_protect_pad + g_res, w_claw), DPoint(protect_width / 2 - w_protect_pad + g_res, w_claw + l_claw_pad), DPoint(protect_width / 2 - g_res, w_claw + l_claw_pad), DPoint(protect_width / 2 - g_res, 0) ] metal_poly = DSimplePolygon(metal_points) self.metal_region.insert(metal_poly) empty_region = protect_region - self.metal_region self.empty_region.insert(empty_region) self.connections = [ DPoint(0, 0), DPoint(0, w_claw + g_res + self._w_thin_ground) ]
def send_polygons(self, cell, layer_i=-1): if (layer_i == -1): # cell is a Region() r_cell = cell else: r_cell = Region(cell.begin_shapes_rec(layer_i)) for poly in r_cell: # print("sending polygon") # No internal holes are allowed. This is # only KLayout specific internal representation. # So there is cuts in the polygon with internal # holes introduced by `resolved_holes()`. self.send_polygon(poly.resolved_holes())
def place(self, dest, layer_i=-1, region_name=None): if (layer_i != -1): r_cell = Region(dest.begin_shapes_rec(layer_i)) for primitive in self.primitives.values(): primitive.place(r_cell, region_name=region_name) temp_i = dest.layout().layer(pya.LayerInfo(PROGRAM.LAYER1_NUM, 0)) dest.shapes(temp_i).insert(r_cell) dest.layout().clear_layer(layer_i) dest.layout().move_layer(temp_i, layer_i) dest.layout().delete_layer(temp_i) else: for primitive in self.primitives.values(): primitive.place(dest, region_name=region_name)