def make_align_markers(self, t, w, position, layers, cross=False): if not (type(layers) == list): layers = [layers] self.align_markers = Cell("AlignMarkers") for l in layers: if not cross: am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l) elif cross: crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t), (t, w / 2), (0, w / 2), (0, 0)] crosspts.extend( tuple(map(tuple, (-np.array(crosspts)).tolist()))) # crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.), # (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.), # (t / 2., -t / 2.), (t / 2., -h / 2.), # (-t / 2., -h / 2.), (-t / 2., -t / 2.), # (-w / 2., -t / 2.), (-w / 2., t / 2.)] am0 = Boundary(crosspts, layer=l) # Create gdsCAD shape # am1 = Polygon(crosspts) #Create shapely polygon for later calculation am1 = am0.copy().translate(tuple(np.array(position) * [1, 1])) # 850,850 am2 = am0.copy().translate(tuple(np.array(position) * [-1, 1])) # 850,850 am3 = am0.copy().translate(tuple(np.array(position) * [1, -1])) # 850,850 am4 = am0.copy().translate(tuple(np.array(position) * [-1, -1])) # 850,850 # am4 = am0.copy().scale((-1, -1)) #Reflect in both x and y-axis self.align_markers.add([am1, am2, am3, am4]) self.add(self.align_markers)
def add_waferLabel(self, label, layers, pos=None): """ Create a label """ if not (type(layers) == list): layers = [layers] if self._label is None: self._label = Cell(self.name + '_LBL') self.add(self._label) else: self._label.elements = [] offset = np.array([0, -self.wafer_r + self.block_gap]) if pos is None else np.array(pos) labelsize = 1000. for l in layers: txt = LineLabel(label, labelsize, style='romand', line_width=labelsize / 20., layer=l) bbox = txt.bounding_box txt.translate(-np.mean(bbox, 0)) # Center text around origin txt.translate(offset) # Translate it to bottom of wafer self._label.add(txt)
def add_tem_nanowires(self): size = 500 y_offset = 1300 shapes_big = make_shape_array(size, 0.02, 0.5, 'Tris_right', l_smBeam, labels=False) shapes_small = make_shape_array(size, 0.005, 0.5, 'Tris_right', l_smBeam, labels=False) tem_shapes = Cell('TEMShapes') # tem_shapes.add(shapes_big, origin=(2200 - size / 2., y_offset - size / 2.)) tem_shapes.add(shapes_small, origin=(-2200 - size / 2., y_offset - size / 2.)) for x, y in self.upCenters: self.add(tem_shapes, origin=(x, y)) for x, y in self.downCenters: self.add(tem_shapes, origin=( x, y - 2 * y_offset)) # Don't rotate because of directionality
def make_many_shapes(self, array_size, shape_areas, pitch, shapes, skew, layer): offset_x = array_size * 1.25 offset_y = array_size * 1.25 cur_y = 0 many_shape_cell = Cell('ManyShapes') for area in shape_areas: cur_x = 0 for shape in shapes: write_top_labels = cur_y == 0 write_side_labels = cur_x == 0 s_array = self.make_shape_array(array_size, area, pitch, shape, layer, skew, toplabels=write_top_labels, sidelabels=write_side_labels) many_shape_cell.add(s_array, origin=(cur_x - array_size / 2., cur_y - array_size / 2.)) cur_x += offset_x cur_y -= offset_y self.add(many_shape_cell, origin=(-offset_x * (len(shapes) - 1) / 2., offset_y * (len(skews) - 1) / 2.))
def frame_label(self, label_txt, size, beam): text = Label(label_txt, size, layer=beam) lblVertOffset = 0.4 text.translate(tuple( np.array(-text.bounding_box.mean(0)))) # Center justify label lbl_cell = Cell('frame_label') lbl_cell.add(text) self.add(lbl_cell, origin=(0, self.size_y * lblVertOffset / 2.))
def add_chip_labels(self): wafer_lbl = PATTERN + '\n' + WAFER_ID text = Label(wafer_lbl, 20., layer=l_lgBeam) text.translate(tuple( np.array(-text.bounding_box.mean(0)))) # Center justify label chip_lbl_cell = Cell('chip_label') chip_lbl_cell.add(text) self.block_up.add(chip_lbl_cell, origin=(0, -3000)) self.block_down.add(chip_lbl_cell, origin=(0, 3000))
def __init__(self, name, size, borderLayers): if not (type(borderLayers) == list): borderLayers = [borderLayers] Cell.__init__(self, name) self.size_x, self.size_y = size # Create the border of the cell for l in borderLayers: self.border = Box((-self.size_x / 2., -self.size_y / 2.), (self.size_x / 2., self.size_y / 2.), 1, layer=l) self.add(self.border) # Add border to the frame
def add_wafer_outline(self, layers): """ Create Wafer Outline """ if not (type(layers) == list): layers = [layers] outline = Cell('WAF_OLINE') for l in layers: circ = Circle((0, 0), self.wafer_r, 100, layer=l) outline.add(circ) self.add(outline)
def add_chip_labels(self): wafer_lbl = "AN1.3\n" + WAFER_ID text = Label(wafer_lbl, 20., layer=l_lgBeam) text.translate(tuple( np.array(-text.bounding_box.mean(0)))) # Center justify label chip_lbl_cell = Cell('chip_label') chip_lbl_cell.add(text) for x, y in self.upCenters: self.add(chip_lbl_cell, origin=(x, y - 3000)) for x, y in self.downCenters: self.add(chip_lbl_cell, origin=(x, y + 3000))
def processCheck_CleavingMark(self, yPosition, layers): if not (type(layers) == list): layers = [layers] for l in layers: pt1 = (100, yPosition) pt2 = (2000, yPosition) pt3 = (-1100, yPosition) pt4 = (-2800, yPosition) line1 = Path([pt1, pt2], width=10, layer=l) line2 = Path([pt3, pt4], width=10, layer=l) cMarkCell = Cell('Cleaving Mark') cMarkCell.add(line1) cMarkCell.add(line2) self.add(cMarkCell)
def make_many_shapes(array_size, shape_areas, pitch, shapes, layer): offset_x = array_size * 1.25 offset_y = array_size * 1.25 cur_y = 0 many_shape_cell = Cell('ManyShapes') for area in shape_areas: cur_x = 0 for shape in shapes: write_labels = cur_y == 0 s_array = make_shape_array(array_size, area, pitch, shape, layer, labels=write_labels) many_shape_cell.add(s_array, origin=(cur_x, cur_y)) cur_x += offset_x cur_y -= offset_y return many_shape_cell
def make_branch(length, width, layers, rot_angle=0): pt1 = np.array((0, -width / 2.)) pt2 = np.array((length, width / 2.)) slit = Cell("Slit") for l in layers: rect = Rectangle(pt1, pt2, layer=l) slit.add(rect) branch = Cell('Branch-{}/{}-lw'.format(length, width)) branch.add(slit, rotation=0 + rot_angle) branch.add(slit, rotation=120 + rot_angle) branch.add(slit, rotation=240 + rot_angle) return branch
def build_and_add_blocks(self): """ Create blocks and add them to the wafer Cell """ self.upCellLattice = self.getCellLattice(cellsize=2000) # Create a cell for the triangular blocks block_up = Cell('upblock') for x, y in self.upCellLattice: block_up.add(self.cells, origin=(x, y)) # Take each point in block lattice and make a copy of the block in that location for x, y in self.upCenters: self.add(block_up, origin=(x, y)) if self.symmetric_chips: for x, y in self.downCenters: self.add(block_up, origin=(x, y), rotation=180) else: self.downCellLattice = np.array(self.upCellLattice) * np.array( [1, -1]) block_down = Cell('downblock') for x, y in self.downCellLattice: block_down.add(self.cells, origin=(x, y)) for x, y in self.downCenters: self.add(block_down, origin=(x, y))
def add_orientation_text(self, layers): """ Create Orientation Label """ if not (type(layers) == list): layers = [layers] tblock = Cell('WAF_ORI_TEXT') for l in layers: for (t, pt) in list(self.o_text.items()): txt = Label(t, 1000, layer=l) bbox = txt.bounding_box txt.translate(-np.mean(bbox, 0)) # Center text around origin txt.translate(np.array(pt)) tblock.add(txt) self.add(tblock)
def dashed_line(pt1, pt2, dashlength, width, layer): line = LineString((pt1, pt2)) dash_pts = np.arange(0, line.length, dashlength).tolist() if len(dash_pts) % 2 == 1: # Odd number dash_pts.append(line.length) # Add last point on line dash_pts = list( map(line.interpolate, dash_pts)) # Interpolate points along this line to make dashes dash_pts = [pt.xy for pt in dash_pts] dash_pts = np.reshape(dash_pts, (-1, 2, 2)) lines = [ Path(list(linepts), width=width, layer=layer) for linepts in dash_pts ] dline = Cell('DASHLINE') dline.add(lines) return dline
def __init__( self, name, cells=None, wafer_r=25.5e3, trisize=10e3, cellsize=2e3, block_gap=0., cell_gap=200., doMCSearch=True, MCIterations=30, # Small square cells doMCBlockSearch=True, MCBlockIterations=50, # Large triangular blocks mkWidth=10, cellsAtEdges=False, symmetric_chips=True): Cell.__init__(self, name) self.wafer_r = wafer_r self.trisize = trisize self.cellsize = cellsize self.block_gap = block_gap self.cell_gap = cell_gap self.doMCSearch = doMCSearch self.MCIterations = MCIterations self.doMCBlockSearch = doMCBlockSearch self.MCBlockIterations = MCBlockIterations # Create a circle shape with the radius of the wafer circ = Point(0., 0.) self.waferShape = circ.buffer(wafer_r) self.blockOffset = (0, 0) self.cells = cells self.cell_layers = self._cell_layers() self._label = None self.upCellLattice = [] self.downCellLattice = [] self.upCenters = [] self.downCenters = [] self.upTris = [] self.downTris = [] self.cellsAtEdges = cellsAtEdges self.symmetric_chips = symmetric_chips
def makeAlignMarkers(self, t, w, position, layers, cross=False): if not (type(layers) == list): layers = [layers] self.aMarkers = Cell("AlignMarkers") for l in layers: if not (cross): am1 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l) elif cross: h = w crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.), (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.), (t / 2., -t / 2.), (t / 2., -h / 2.), (-t / 2., -h / 2.), (-t / 2., -t / 2.), (-w / 2., -t / 2.), (-w / 2., t / 2.)] am1 = Boundary(crosspts, layer=l) # Create gdsCAD shape # am1 = Polygon(crosspts) #Create shapely polygon for later calculation am1 = am1.translate(tuple(position)) # 850,850 am2 = am1.copy().scale((-1, 1)) # Reflect in x-axis am3 = am1.copy().scale((1, -1)) # Reflect in y-axis am4 = am1.copy().scale((-1, -1)) # Reflect in both x and y-axis self.aMarkers.add([am1, am2, am3, am4]) self.add(self.aMarkers)
def add_tem_nanowires(self): size = 500 y_offset = 1000 shapes_big = make_shape_array(size, 0.02, 0.5, 'Tris_right', l_smBeam, labels=False) shapes_small = make_shape_array(size, 0.005, 0.5, 'Tris_right', l_smBeam, labels=False) tem_shapes = Cell('TEMShapes') # tem_shapes.add(shapes_big, origin=(2200 - size / 2., y_offset - size / 2.)) tem_shapes.add(shapes_small, origin=(-size / 2., -size / 2.)) self.block_up.add(tem_shapes, origin=(-2200, y_offset)) self.block_down.add(tem_shapes, origin=(2200, -y_offset))
def add_theory_cell(self): theory_cells = Cell('TheoryCells') theory_cells.add(make_theory_cell(), origin=(-200, 0)) theory_cells.add(make_theory_cell_br(), origin=(200, 0)) self.block_up.add(theory_cells, origin=(0, 1300)) self.block_down.add(theory_cells, origin=(0, -1300))
def make_align_markers(self, t, w, position, layers, cross=False, auto_marks=False): if not (type(layers) == list): layers = [layers] self.align_markers = Cell("AlignMarkers") self.align_marker = Cell("AlignMarker") for l in layers: if not cross: am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l) self.align_marker.add(am0) elif cross: crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t), (t, w / 2), (0, w / 2), (0, 0)] crosspts.extend( tuple(map(tuple, (-np.array(crosspts)).tolist()))) # crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.), # (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.), # (t / 2., -t / 2.), (t / 2., -h / 2.), # (-t / 2., -h / 2.), (-t / 2., -t / 2.), # (-w / 2., -t / 2.), (-w / 2., t / 2.)] am0 = Boundary(crosspts, layer=l) # Create gdsCAD shape self.align_marker.add(am0) # am1 = Polygon(crosspts) #Create shapely polygon for later calculation if auto_marks: # automatic alignment marks for the e-beam tool auto_mark_rect = Rectangle((-10., -10.), (10., 10.), layer=l) auto_mark = Cell("AutoMark") auto_mark.add(auto_mark_rect) self.align_marker.add(auto_mark, origin=(100, 100)) self.align_marker.add(auto_mark, origin=(-100, 100)) self.align_marker.add(auto_mark, origin=(100, -100)) self.align_marker.add(auto_mark, origin=(-100, -100)) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [1, 1])) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [-1, 1])) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [1, -1])) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [-1, -1])) self.add(self.align_markers)
def processCheck_Slits(self, position, arrayWidth, slitWidth, pitch, length, rotation, layers): if not (type(layers) == list): layers = [layers] Nx = int(arrayWidth / pitch) Ny = 1 for l in layers: # Define the slits slit = Cell("Slits") rect = Rectangle((-slitWidth / 2., -length / 2.), (slitWidth / 2., length / 2.), layer=l) slit.add(rect) slits = CellArray(slit, Nx, Ny, (pitch, 0)) slits.translate((-(Nx) * (pitch) / 2., 0.)) slits.translate(position) slitarray = Cell("ProcessCheckingSlits") slitarray.add(slits) self.add(slitarray)
def add_theory_cell(self): theory_cells = Cell('TheoryCells') theory_cells.add(make_theory_cell(), origin=(-200, 0)) theory_cells.add(make_theory_cell_br(), origin=(200, 0)) for x, y in self.upCenters: self.add(theory_cells, origin=(x, y + 1300)) for x, y in self.downCenters: self.add(theory_cells, origin=( x, y - 1300 )) # Don't rotate because of directionality of branched membranes
def make_rotating_branches(length, width, N, radius, layers, angle_sweep=360, angle_ref=False, angle_offset=0): cell = Cell('RotatingBranches') if not (type(layers) == list): layers = [layers] allslits = Cell('All Slits') angles = np.linspace(0, angle_sweep, N) translation = (radius, 0) pt1 = np.array((-length / 2., -width / 2.)) + translation pt2 = np.array((length / 2., width / 2.)) + translation branch = make_branch(length, width, layers) for element in branch.elements: element.origin = [radius, 0] for angle in angles: allslits.add(branch.copy(), rotation=angle_offset + angle) cell.add(allslits) for l in layers: if angle_ref: labelCell = Cell('AngleLabels') lineCell = Cell('Line') pt1 = (0, 0) pt2 = (radius * 0.9, 0) line = Path([pt1, pt2], width=width, layer=l) dLine = dashed_line(pt1, pt2, 2, width, l) lineCell.add(line) rot_angle = 0 while True: if abs(rot_angle) > abs(angle_sweep): break if abs(rot_angle) % 60 == 0: labelCell.add(lineCell, rotation=rot_angle) if (abs(rot_angle) - 30) % 60 == 0: labelCell.add(dLine, rotation=rot_angle) rot_angle += np.sign(angle_sweep) * 15 cell.add(labelCell) return cell
def make_shape_array(self, array_size, shape_area, shape_pitch, type, layer, skew, toplabels=False, sidelabels=False): num_of_shapes = int(np.ceil(array_size / shape_pitch)) base_cell = Cell('Base') if 'tris' in type.lower(): triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4) tri_shape = scale( RegPolygon([0, 0], triangle_side, 3, layer=layer), [skew, 1.0]) tri_cell = Cell('Tri') tri_cell.add(tri_shape) if 'right' in type.lower(): base_cell.add(tri_cell, rotation=0) elif 'left' in type.lower(): base_cell.add(tri_cell, rotation=-180) elif 'down' in type.lower(): base_cell.add(tri_cell, rotation=30) # not working for skew yet elif 'up' in type.lower(): base_cell.add(tri_cell, rotation=-30) # not working for skew yet elif type.lower() == "circles": circ_radius = np.sqrt(shape_area / np.pi) circ = scale(Disk([0, 0], circ_radius, layer=layer), [skew, 1.0]) base_cell.add(circ) elif type.lower() == 'hexagons': hex_side = np.sqrt(shape_area / 6. / np.sqrt(3) * 4) hex_shape = scale(RegPolygon([0, 0], hex_side, 6, layer=layer), [skew, 1.0]) hex_cell = Cell('Hex') hex_cell.add(hex_shape) base_cell.add(hex_cell, rotation=0) shape_array = CellArray(base_cell, num_of_shapes, num_of_shapes, [shape_pitch, shape_pitch]) shape_array_cell = Cell('Shape Array') shape_array_cell.add(shape_array) lbl_dict = { 'hexagons': 'hex', 'circles': 'circ', 'tris_right': 'triR', 'tris_left': 'triL' } if toplabels: text = Label('{}'.format(lbl_dict[type.lower()]), 2, layer=layer) lblVertOffset = 0.8 text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((array_size / 2., array_size / lblVertOffset)))) # Center justify label shape_array_cell.add(text) if sidelabels: text = Label('a={:.0f}knm2'.format(shape_area * 1000), 2, layer=layer) lblHorizOffset = 1.5 text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((-array_size / lblHorizOffset, array_size / 2.)))) # Center justify label shape_array_cell.add(text) return shape_array_cell
class Frame(Cell): """ Make a frame for writing to with ebeam lithography Params: -name of the frame, just like when naming a cell -size: the size of the frame as an array [xsize,ysize] """ def __init__(self, name, size, border_layers): if not (type(border_layers) == list): border_layers = [border_layers] Cell.__init__(self, name) self.size_x, self.size_y = size # Create the border of the cell for l in border_layers: self.border = Box((-self.size_x / 2., -self.size_y / 2.), (self.size_x / 2., self.size_y / 2.), 1, layer=l) self.add(self.border) # Add border to the frame self.align_markers = None def frame_label(self, label_txt, size, beam): text = Label(label_txt, size, layer=beam) lblVertOffset = 0.4 text.translate(tuple( np.array(-text.bounding_box.mean(0)))) # Center justify label lbl_cell = Cell('frame_label') lbl_cell.add(text) self.add(lbl_cell, origin=(0, self.size_y * lblVertOffset / 2.)) def make_align_markers(self, t, w, position, layers, cross=False, auto_marks=False): if not (type(layers) == list): layers = [layers] self.align_markers = Cell("AlignMarkers") self.align_marker = Cell("AlignMarker") for l in layers: if not cross: am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l) self.align_marker.add(am0) elif cross: crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t), (t, w / 2), (0, w / 2), (0, 0)] crosspts.extend( tuple(map(tuple, (-np.array(crosspts)).tolist()))) # crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.), # (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.), # (t / 2., -t / 2.), (t / 2., -h / 2.), # (-t / 2., -h / 2.), (-t / 2., -t / 2.), # (-w / 2., -t / 2.), (-w / 2., t / 2.)] am0 = Boundary(crosspts, layer=l) # Create gdsCAD shape self.align_marker.add(am0) # am1 = Polygon(crosspts) #Create shapely polygon for later calculation if auto_marks: # automatic alignment marks for the e-beam tool auto_mark_rect = Rectangle((-10., -10.), (10., 10.), layer=l) auto_mark = Cell("AutoMark") auto_mark.add(auto_mark_rect) self.align_marker.add(auto_mark, origin=(100, 100)) self.align_marker.add(auto_mark, origin=(-100, 100)) self.align_marker.add(auto_mark, origin=(100, -100)) self.align_marker.add(auto_mark, origin=(-100, -100)) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [1, 1])) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [-1, 1])) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [1, -1])) self.align_markers.add(self.align_marker, origin=tuple(np.array(position) * [-1, -1])) self.add(self.align_markers) # TODO: Center array around the origin def make_shape_array(self, array_size, shape_area, shape_pitch, type, layer, skew, toplabels=False, sidelabels=False): num_of_shapes = int(np.ceil(array_size / shape_pitch)) base_cell = Cell('Base') if 'tris' in type.lower(): triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4) tri_shape = scale( RegPolygon([0, 0], triangle_side, 3, layer=layer), [skew, 1.0]) tri_cell = Cell('Tri') tri_cell.add(tri_shape) if 'right' in type.lower(): base_cell.add(tri_cell, rotation=0) elif 'left' in type.lower(): base_cell.add(tri_cell, rotation=-180) elif 'down' in type.lower(): base_cell.add(tri_cell, rotation=30) # not working for skew yet elif 'up' in type.lower(): base_cell.add(tri_cell, rotation=-30) # not working for skew yet elif type.lower() == "circles": circ_radius = np.sqrt(shape_area / np.pi) circ = scale(Disk([0, 0], circ_radius, layer=layer), [skew, 1.0]) base_cell.add(circ) elif type.lower() == 'hexagons': hex_side = np.sqrt(shape_area / 6. / np.sqrt(3) * 4) hex_shape = scale(RegPolygon([0, 0], hex_side, 6, layer=layer), [skew, 1.0]) hex_cell = Cell('Hex') hex_cell.add(hex_shape) base_cell.add(hex_cell, rotation=0) shape_array = CellArray(base_cell, num_of_shapes, num_of_shapes, [shape_pitch, shape_pitch]) shape_array_cell = Cell('Shape Array') shape_array_cell.add(shape_array) lbl_dict = { 'hexagons': 'hex', 'circles': 'circ', 'tris_right': 'triR', 'tris_left': 'triL' } if toplabels: text = Label('{}'.format(lbl_dict[type.lower()]), 2, layer=layer) lblVertOffset = 0.8 text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((array_size / 2., array_size / lblVertOffset)))) # Center justify label shape_array_cell.add(text) if sidelabels: text = Label('a={:.0f}knm2'.format(shape_area * 1000), 2, layer=layer) lblHorizOffset = 1.5 text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((-array_size / lblHorizOffset, array_size / 2.)))) # Center justify label shape_array_cell.add(text) return shape_array_cell def make_many_shapes(self, array_size, shape_areas, pitch, shapes, skew, layer): offset_x = array_size * 1.25 offset_y = array_size * 1.25 cur_y = 0 many_shape_cell = Cell('ManyShapes') for area in shape_areas: cur_x = 0 for shape in shapes: write_top_labels = cur_y == 0 write_side_labels = cur_x == 0 s_array = self.make_shape_array(array_size, area, pitch, shape, layer, skew, toplabels=write_top_labels, sidelabels=write_side_labels) many_shape_cell.add(s_array, origin=(cur_x - array_size / 2., cur_y - array_size / 2.)) cur_x += offset_x cur_y -= offset_y self.add(many_shape_cell, origin=(-offset_x * (len(shapes) - 1) / 2., offset_y * (len(skews) - 1) / 2.))
def add_tem_membranes(self, widths, length, pitch, layer): tem_membranes = Cell('TEM_Membranes') n = 3 curr_y = 0 for width in widths: membrane = Path([(-length / 2., 0), (length / 2., 0)], width=width, layer=layer) membrane_cell = Cell('Membrane_w{:.0f}'.format(width * 1000)) membrane_cell.add(membrane) membrane_array = CellArray(membrane_cell, 1, n, (0, pitch)) membrane_array_cell = Cell('MembraneArray_w{:.0f}'.format(width * 1000)) membrane_array_cell.add(membrane_array) tem_membranes.add(membrane_array_cell, origin=(0, curr_y)) curr_y += n * pitch n2 = 5 tem_membranes2 = Cell('Many_TEM_Membranes') tem_membranes2.add( CellArray(tem_membranes, 1, n2, (0, n * len(widths) * pitch))) self.block_up.add(tem_membranes2, origin=(0, -2000)) # self.block_up.add(tem_membranes2, origin=(0, -1400), rotation=90) self.block_down.add(tem_membranes2, origin=(0, 2000))
def make_rotating_slits(length, width, N, radius, layers, angle_sweep=360, angle_ref=False): cell = Cell('RotatingSlits') if not (type(layers) == list): layers = [layers] allslits = Cell('All Slits') angles = np.linspace(0, angle_sweep, N) # radius = length*12. translation = (radius, 0) pt1 = np.array((-length / 2., -width / 2.)) + translation pt2 = np.array((length / 2., width / 2.)) + translation slit = Cell("Slit") for l in layers: rect = Rectangle(pt1, pt2, layer=l) slit.add(rect) for angle in angles: allslits.add(slit.copy(), rotation=angle) cell.add(allslits) for l in layers: if angle_ref: label_cell = Cell('AngleLabels') line_cell = Cell('Line') pt1 = (0, 0) pt2 = (radius * 0.9, 0) line = Path([pt1, pt2], width=width, layer=l) d_line = dashed_line(pt1, pt2, 2, width, l) line_cell.add(line) rot_angle = 0 while True: if abs(rot_angle) > abs(angle_sweep): break if abs(rot_angle) % 60 == 0: label_cell.add(line_cell, rotation=rot_angle) if (abs(rot_angle) - 30) % 60 == 0: label_cell.add(d_line, rotation=rot_angle) rot_angle += np.sign(angle_sweep) * 15 cell.add(label_cell) return cell
smField3 = Frame(lbl, (smFrameSize, smFrameSize), []) smField3.frame_label(lbl, 3, l_smBeam) smField3.make_align_markers(2., 20., (180., 180.), l_lgBeam, cross=True) smField3.make_many_shapes(25, areas, pitch, shapes, skew, l_smBeam) skew = skews[3] lbl = "Sk={:.1f}x".format(skew) smField4 = Frame(lbl, (smFrameSize, smFrameSize), []) smField4.frame_label(lbl, 3, l_smBeam) smField4.make_align_markers(2., 20., (180., 180.), l_lgBeam, cross=True) smField4.make_many_shapes(25, areas, pitch, shapes, skew, l_smBeam) centerAlignField = Frame("CenterAlignField", (smFrameSize, smFrameSize), []) # Add everything together to a top cell topCell = Cell("TopCell") topCell.add(lgField) smFrameSpacing = 400 # Spacing between the three small frames dx = smFrameSpacing + smFrameSize dy = smFrameSpacing + smFrameSize topCell.add(smField1, origin=(-dx / 2., dy / 2.)) topCell.add(smField2, origin=(dx / 2., dy / 2.)) topCell.add(smField3, origin=(-dx / 2., -dy / 2.)) topCell.add(smField4, origin=(dx / 2., -dy / 2.)) # topCell.add(centerAlignField, origin=(0., 0.)) # %%Create the layout and output GDS file layout = Layout('LIBRARY', precision=1e-10) wafer = MBEWafer('MembranesWafer', wafer_r=wafer_r,
def make_shape_array(array_size, shape_area, shape_pitch, type, layer): num_of_shapes = int(np.ceil(array_size / shape_pitch)) base_cell = Cell('Base') if type.lower() == "circles": circ_radius = np.sqrt(shape_area / np.pi) circ = Disk([0, 0], circ_radius, layer=layer) base_cell.add(circ) elif type.lower() == 'tris_down': triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4) tri_shape = RegPolygon([0, 0], triangle_side, 3, layer=layer) tri_cell = Cell('Tri') tri_cell.add(tri_shape) base_cell.add(tri_cell, rotation=30) elif type.lower() == 'tris_up': triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4) tri_shape = RegPolygon([0, 0], triangle_side, 3, layer=layer) tri_cell = Cell('Tri') tri_cell.add(tri_shape) base_cell.add(tri_cell, rotation=-30) elif type.lower() == 'hexagons': hex_side = np.sqrt(shape_area / 6. / np.sqrt(3) * 4) hex_shape = RegPolygon([0, 0], hex_side, 6, layer=layer) hex_cell = Cell('Hex') hex_cell.add(hex_shape) base_cell.add(hex_cell, rotation=0) shape_array = CellArray(base_cell, num_of_shapes, num_of_shapes, [shape_pitch, shape_pitch]) shape_array_cell = Cell('Shape Array') shape_array_cell.add(shape_array) text = Label('{}'.format(type), 2) lblVertOffset = 0.8 text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((array_size / 2., array_size / lblVertOffset)))) # Center justify label shape_array_cell.add(text) return shape_array_cell
def make_theory_cell_br(): ''' Makes the theory cell and returns it as a cell''' # Growth Theory Slit Elongation pitch = [0.500] lengths = list(np.logspace(-3, 0, 20) * 8.0) # Logarithmic widths = [0.044, 0.028, 0.016, 0.012, 0.008] TheorySlitElong = Cell('LenWidthDependence') arrayHeight = 20. arraySpacing = 30. spacing = 10. TheorySlitElong.add( slit_elongation_array(pitch, spacing, widths[0], lengths, 0., arrayHeight, arraySpacing, l_smBeam)) TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[1], lengths, 0., arrayHeight, arraySpacing, l_smBeam), origin=(0, -30)) TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[2], lengths, 0., arrayHeight, arraySpacing, l_smBeam), origin=(0, -60)) TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[3], lengths, 0., arrayHeight, arraySpacing, l_smBeam), origin=(0, -90)) TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[4], lengths, 0., arrayHeight, arraySpacing, l_smBeam), origin=(0, -120)) # Length Dependence LenWidDep = Cell('LenWidDependence') pitch = [0.5] lengths = list(np.logspace(-2, 0, 10) * 8.0) # Logarithmic widths = [0.044, 0.016, 0.008] arrayHeight = 20. arrayWidth = arrayHeight arraySpacing = 30. spacing = 0.5 for i, length in enumerate(lengths): for j, width in enumerate(widths): LenWidDep.add(make_branch_array(pitch, width, length, ['pitch', 'width', 'length'], spacing, 0, arrayHeight, arrayWidth, arraySpacing, l_smBeam), origin=(i * 30, j * 30)) # Make rotating slits shape_len = 3. shape_wid = 0.044 N = 13 # number of shapes in the 120 degree arc N_rows = 8 angle_sweep = 180 wheel_rad = 25. wheel1 = Cell('RotDependence_LongSlits') for i in range(N_rows): angle_offset = (i % 2) * 7.5 _angle_sweep = 180. - (i % 2) * 15. _N = int(N * _angle_sweep / angle_sweep) + (i % 2) angle_ref = False if i == 0: angle_ref = True wheel1.add( make_rotating_branches(shape_len, shape_wid, _N, wheel_rad + i * shape_len, l_smBeam, angle_sweep=_angle_sweep, angle_ref=angle_ref, angle_offset=angle_offset)) wheel2 = Cell('RotDependence_ShortSlits') angle_sweep = -180 wheel2.add( make_rotating_slits(2, 0.044, 91, 6. * 2, l_smBeam, angle_ref=True, angle_sweep=angle_sweep)) for i in range(10): # number of concentric rings to make wheel2.add( make_rotating_slits(2, 0.044, 91, (7.2 + i * 1.2) * 2, l_smBeam, angle_sweep=angle_sweep)) # Make branch devices shape_len = 3. shape_wid = 0.044 N = 13 # number of shapes in the 120 degree arc N_rows = 2 angle_sweep = 180 wheel_rad = 50. wheel3 = Cell('RotDependence_BranchDev') for i in range(N_rows): angle_offset = (i % 2) * 7.5 _angle_sweep = 180. - (i % 2) * 15. _N = int(N * _angle_sweep / angle_sweep) + (i % 2) angle_ref = False if i == 0: angle_ref = True wheel3.add( make_rotating_branch_devices(shape_len, shape_wid, _N, wheel_rad + i * shape_len * 2., l_smBeam, angle_sweep=_angle_sweep, angle_ref=angle_ref, angle_offset=angle_offset)) # Pitch Dependence PitchDep = Cell('PitchDependence') pitches = list(np.round(np.logspace(-1, 1, 10), 1)) # Logarithmic length = [2.] widths = [0.044, 0.016, 0.008] arrayHeight = 20. arrayWidth = arrayHeight arraySpacing = 30. spacing = 0.5 for j, width in enumerate(widths): for i, pitch in enumerate(pitches): PitchDep.add(make_branch_array(pitch, width, length, ['pitch', 'width', 'length'], spacing, 0, arrayHeight, arrayWidth, arraySpacing, l_smBeam), origin=(i * 30, j * 30)) # Make arrays of various shapes hexagon_array = make_shape_array(20, 0.02, 0.75, 'Hexagons', l_smBeam) circles_array = make_shape_array(20, 0.02, 0.75, 'Circles', l_smBeam) triangle_down_array = make_shape_array(20, 0.02, 0.75, 'Tris_down', l_smBeam) triangle_up_array = make_shape_array(20, 0.02, 0.75, 'Tris_up', l_smBeam) # Merry Christmas! xmas_texts = [ LineLabel('Merry Christmas!', 2, style='gothgbt', line_width=0.044, layer=l_smBeam), LineLabel('Merry Christmas!', 2, style='italict', line_width=0.044, layer=l_smBeam), LineLabel('Merry Christmas!', 2, style='scriptc', line_width=0.044, layer=l_smBeam), LineLabel('Merry Christmas!', 2, style='scripts', line_width=0.044, layer=l_smBeam), LineLabel('Merry Christmas!', 2, style='romanc', line_width=0.044, layer=l_smBeam), LineLabel('Merry Christmas!', 2, style='romand', line_width=0.044, layer=l_smBeam) ] xmax_cell = Cell('MerryChristmas') for i, xmas_text in enumerate(xmas_texts): xmas_text.translate( tuple( np.array(-xmas_text.bounding_box.mean(0)) + np.array([20, -80 - i * 10.]))) # Center justify label xmax_cell.add(xmas_text) TopCell = Cell('GrowthTheoryTopCell') TopCell.add(wheel1, origin=(-170., -50.), rotation=-90.) TopCell.add(wheel2, origin=(-175., -50.), rotation=-90.) TopCell.add(wheel3, origin=(0, -80)) TopCell.add(PitchDep, origin=(-200., -250.)) TopCell.add(LenWidDep, origin=(-200., -50.)) TopCell.add(xmax_cell, origin=(-110., 60.)) return TopCell