def makeSlitArray(pitches, spacing, widths, lengths, rotAngle, arrayHeight, arraySpacing, layers): ''' Give it a single pitch and width and it will generate an array for all the lengths ''' if not (type(layers) == list): layers = [layers] if not (type(pitches) == list): pitches = [pitches] if not (type(lengths) == list): lengths = [lengths] if not (type(widths) == list): widths = [widths] for l in layers: i = -1 j = -1 manyslits = Cell("SlitArray") slitarray = Cell("SlitArray") pitch = pitches[0] width = widths[0] j += 1 i = -1 xlength = 0 slit = Cell("Slits") for length in lengths: spacing = length / 5. + 0.1 i += 1 pitchV = pitch / np.cos(np.deg2rad(rotAngle)) # widthV = width / np.cos(np.deg2rad(rotAngle)) # Nx = int(arrayWidth / (length + spacing)) Ny = int(arrayHeight / (pitchV)) # Define the slits if xlength == 0: translation = (length / 2., 0) xlength += length else: translation = (xlength + spacing + length / 2., 0) xlength += length + spacing pt1 = np.array((-length / 2., -width / 2.)) + translation pt2 = np.array((length / 2., width / 2.)) + translation rect = Rectangle(pt1, pt2, layer=l) rect = rect.copy().rotate(rotAngle) slit.add(rect) slits = CellArray(slit, 1, Ny, (0, pitchV)) # slits.translate((-(Nx - 1) * (length + spacing) / 2., -(Ny - 1)* (pitchV) / 2.)) slits.translate( (-slits.bounding_box[1, 0] / 2., -slits.bounding_box[1, 1] / 2.)) slitarray.add(slits) text = Label('w/p\n%i/%i' % (width * 1000, pitch * 1000), 2) lblVertOffset = 1.4 text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, arrayHeight / lblVertOffset)))) # Center justify label slitarray.add(text) # manyslits.add(slitarray,origin=((arrayWidth + arraySpacing) * i, (arrayHeight + 2.*arraySpacing) * j-arraySpacing/2.)) manyslits.add(slitarray) # self.add(manyslits, origin=(-i * (arrayWidth + arraySpacing) / 2, -j * (arrayHeight + arraySpacing) / 2)) # self.add(manyslits) return manyslits
def makeSlitArray3(pitches, spacing, widths, lengths, rotAngle, arrayHeight, arrayWidth, arraySpacing, layers): ''' Give it a single pitch and arrays for spacings/widths and it will generate an array for all the combinations Makes seperate frame for each pitch ''' if not (type(layers) == list): layers = [layers] if not (type(pitches) == list): pitches = [pitches] if not (type(lengths) == list): lengths = [lengths] if not (type(widths) == list): widths = [widths] for l in layers: i = -1 j = -1 manyslits = Cell("SlitArray") length = lengths[0] spacing = length / 5. + 0.1 # Set the spacing between arrays for pitch in pitches: j += 1 i = -1 for width in widths: # for pitch in pitches: i += 1 if i % 3 == 0: j += 1 # Move to array to next line i = 0 # Restart at left pitchV = pitch / np.cos(np.deg2rad(rotAngle)) # widthV = width / np.cos(np.deg2rad(rotAngle)) Nx = int(arrayWidth / (length + spacing)) Ny = int(arrayHeight / (pitchV)) # Define the slits slit = Cell("Slits") rect = Rectangle( (-length / 2., -width / 2.), (length / 2., width / 2.), layer=l) rect = rect.copy().rotate(rotAngle) slit.add(rect) slits = CellArray(slit, Nx, Ny, (length + spacing, pitchV)) slits.translate((-(Nx - 1) * (length + spacing) / 2., -(Ny - 1) * (pitchV) / 2.)) slitarray = Cell("SlitArray") slitarray.add(slits) text = Label('w/p/l\n%i/%i/%i' % (width * 1000, pitch * 1000, length * 1000), 2) lblVertOffset = 1.35 if j % 2 == 0: text.translate( tuple(np.array(-text.bounding_box.mean(0)) + np.array(( 0, -arrayHeight / lblVertOffset)))) # Center justify label else: text.translate( tuple(np.array(-text.bounding_box.mean(0)) + np.array(( 0, arrayHeight / lblVertOffset)))) # Center justify label slitarray.add(text) manyslits.add(slitarray, origin=((arrayWidth + arraySpacing) * i, ( arrayHeight + 2. * arraySpacing) * j - arraySpacing / 2.)) return manyslits
def slit_elongation_array(pitches, spacing, widths, lengths, rot_angle, array_height, array_spacing, layers): if not (type(layers) == list): layers = [layers] if not (type(pitches) == list): pitches = [pitches] if not (type(lengths) == list): lengths = [lengths] if not (type(widths) == list): widths = [widths] for l in layers: j = -1 manyslits = Cell("SlitArray") slitarray = Cell("SlitArray") pitch = pitches[0] width = widths[0] j += 1 i = -1 x_length = 0 slit = Cell("Slits") for length in lengths: spacing = length / 5. + 0.1 i += 1 pitch_v = pitch / np.cos(np.deg2rad(rot_angle)) n_y = int(array_height / pitch_v) # Define the slits if x_length == 0: translation = (length / 2., 0) x_length += length else: translation = (x_length + spacing + length / 2., 0) x_length += length + spacing pt1 = np.array((-length / 2., -width / 2.)) + translation pt2 = np.array((length / 2., width / 2.)) + translation rect = Rectangle(pt1, pt2, layer=l) rect = rect.copy().rotate(rot_angle) slit.add(rect) slits = CellArray(slit, 1, n_y, (0, pitch_v)) slits.translate( (-slits.bounding_box[1, 0] / 2., -slits.bounding_box[1, 1] / 2.)) slitarray.add(slits) text = Label('w/p\n%i/%i' % (width * 1000, pitch * 1000), 2) lbl_vert_offset = 1.4 text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, array_height / lbl_vert_offset)))) # Center justify label slitarray.add(text) manyslits.add(slitarray) return manyslits
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 makeArrowShape(self, length, width, rotAngle, spacing, Nx, Ny, layers): if not (type(layers) == list): layers = [layers] pt1 = np.array((-width * 0.3, -width / 2.)) pt2 = np.array((length, width / 2.)) slit = Cell("Slit") for l in layers: rect = Rectangle(pt1, pt2, layer=l) slit.add(rect) shape = Cell('Shapes') shape.add(slit, rotation=-120) shape.add(slit, rotation=120) xspacing = (width + spacing) / np.cos(np.deg2rad(30)) yspacing = (length + spacing / 2.) * np.sin(np.deg2rad(60)) shapearray = CellArray(shape, Nx, Ny, (xspacing, yspacing * 2.), origin=(-(Nx * xspacing - spacing) / 2., -(Ny * yspacing - spacing) / 2.)) allshapes = Cell('All Shapes') allshapes.add(shapearray) # allshapes.add(shapearray2) # allshapes.add(shape) self.add(allshapes)
def makeXShape(self, length, width, rotAngle, spacing, Nx, Ny, layers): if not (type(layers) == list): layers = [layers] pt1 = np.array((-length / 2., -width / 2.)) pt2 = np.array((length / 2., width / 2.)) slit = Cell("Slit") for l in layers: rect = Rectangle(pt1, pt2, layer=l) slit.add(rect) shape = Cell('Shapes') shape.add(slit, rotation=60) shape.add(slit, rotation=120) xspacing = (length + spacing) * np.cos(np.deg2rad(60)) yspacing = (length + spacing) * np.sin(np.deg2rad(60)) shapearray = CellArray(shape, Nx, Ny, (xspacing, yspacing), origin=(-(Nx * xspacing - spacing) / 2., -(Ny * yspacing - spacing) / 2.)) # shapearray2 = CellArray(shape, Nx, Ny/2,(xspacing,yspacing*2.),origin=(xspacing/2.-(Nx*xspacing-spacing)/2.,yspacing-(Ny*yspacing-spacing*np.tan(np.deg2rad(60)))/2.)) # shapearray = CellArray(shape, Nx, Ny,(xspacing,yspacing)) # shapearray.rotate(rotAngle) # shapearray.translate((-shapearray.bounding_box.mean(0)[0]/2.,-shapearray.bounding_box.mean(0)[1]/2.)) allshapes = Cell('All Shapes') allshapes.add(shapearray) # allshapes.add(shapearray2) # allshapes.add(shape) self.add(allshapes)
def makeYShapes(self, length, width, rotAngle, spacing, Nx, Ny, layers): if not (type(layers) == list): layers = [layers] 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) shape = Cell('Shapes') shape.add(slit, rotation=0 + rotAngle) shape.add(slit, rotation=120 + rotAngle) shape.add(slit, rotation=240 + rotAngle) # CellArray(slit, Nx, Ny,(length + spacing, pitchV)) xspacing = length + spacing yspacing = (length + spacing) * np.sin(np.deg2rad(60)) shapearray = CellArray( shape, Nx, Ny / 2, (xspacing, yspacing * 2.), origin=(-(Nx * xspacing - spacing) / 2., -(Ny * yspacing - spacing * np.sin(np.deg2rad(60))) / 2.)) shapearray2 = CellArray( shape, Nx, Ny / 2, (xspacing, yspacing * 2.), origin=( xspacing / 2. - (Nx * xspacing - spacing) / 2., yspacing - (Ny * yspacing - spacing * np.sin(np.deg2rad(60))) / 2.)) allshapes = Cell('All Shapes') allshapes.add(shapearray) allshapes.add(shapearray2) self.add(allshapes)
def make_rotating_slits(length, width, N, radius, layers, angleRef=False): cell = Cell('RotatingSlits') if not (type(layers) == list): layers = [layers] allslits = Cell('All Slits') angles = np.linspace(0, 360, 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) if angleRef: labelCell = Cell('AngleLabels') lineCell = Cell('Line') pt1 = (-radius * 0.9, 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) labelCell.add(lineCell, rotation=0) labelCell.add(lineCell, rotation=60) labelCell.add(lineCell, rotation=-60) labelCell.add(dLine, rotation=30) labelCell.add(dLine, rotation=90) labelCell.add(dLine, rotation=-30) cell.add(labelCell) return cell
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 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 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 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
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)
# %%Create the layout and output GDS file layout = Layout('LIBRARY', precision=1e-10) wafer = MBEWafer('MembranesWafer', wafer_r=wafer_r, cells=[topCell], cell_gap=CELL_GAP, mkWidth=tDicingMarks, cellsAtEdges=False) file_string = str(waferVer) filename = file_string.replace(' ', '_') # Add pattern for ellipsometry check of SiO2 etching size = 2000 rect = Rectangle((size / 2., size / 2.), (-size / 2., -size / 2.), layer=10) rectCell = Cell('EtchCheckSquare') rectCell.add(rect) rect_layout = Layout('LIBRARY') rect_layout.add(rectCell) rect_layout.save(filename + '_etchCheck.gds') rect_layout.add(rectCell) # wafer.add(rectCell, origin=(0, -2000)) layout.add(wafer) layout.save(filename + '.gds') # Output down chip for doing aligned jobs layout_down = Layout('LIBRARY') layout_down.add(wafer.block_down) layout_down.save(filename + '_downblock.gds')
def make_slit_array(x_vars, y_vars, stat_vars, var_names, spacing, rot_angle, array_height, array_width, array_spacing, layers): if len(var_names) != 3: raise Exception('Error! Need to have three variable names.') if not (type(layers) == list): layers = [layers] if not (type(x_vars) == list): x_vars = [x_vars] if not (type(y_vars) == list): y_vars = [y_vars] if not (type(stat_vars) == list): stat_vars = [stat_vars] x_var_name = var_names[0] y_var_name = var_names[1] stat_var_name = var_names[2] for l in layers: j = -1 manyslits = Cell("SlitArray") for x_var in x_vars: j += 1 i = -1 for y_var in y_vars: i += 1 if i % 3 == 0: j += 1 # Move to array to next line i = 0 # Restart at left var_dict = { x_var_name: x_var, y_var_name: y_var, stat_var_name: stat_vars[0] } pitch = var_dict['pitch'] width = var_dict['width'] length = var_dict['length'] pitch_v = pitch / np.cos(np.deg2rad(rot_angle)) # widthV = width / np.cos(np.deg2rad(rotAngle)) n_x = int(array_width / (length + spacing)) n_y = int(array_height / pitch_v) # Define the slits slit = Cell("Slits") rect = Rectangle((-length / 2., -width / 2.), (length / 2., width / 2.), layer=l) rect = rect.copy().rotate(rot_angle) slit.add(rect) slits = CellArray(slit, n_x, n_y, (length + spacing, pitch_v)) slits.translate((-(n_x - 1) * (length + spacing) / 2., -(n_y - 1) * pitch_v / 2.)) slit_array = Cell("SlitArray") slit_array.add(slits) text = Label( 'w/p/l\n%i/%i/%i' % (width * 1000, pitch * 1000, length * 1000), 2) lbl_vert_offset = 1.35 if j % 2 == 0: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, -array_height / lbl_vert_offset))) ) # Center justify label else: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, array_height / lbl_vert_offset))) ) # Center justify label slit_array.add(text) manyslits.add(slit_array, origin=((array_width + array_spacing) * i, (array_height + 2. * array_spacing) * j - array_spacing / 2.)) return manyslits
def make_arm(width, length, layer, cell_name='branch'): cell = Cell(cell_name) rect = Rectangle((0, -width / 2.), (length, width / 2.), layer=layer) cell.add(rect) return cell