def make_shape_array(self, array_size, shape_area, shape_pitch, type, layer, 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 = RegPolygon([0, 0], triangle_side, 3, layer=layer) 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=60) elif 'down' in type.lower(): base_cell.add(tri_cell, rotation=30) elif 'up' in type.lower(): base_cell.add(tri_cell, rotation=-30) elif 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() == '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) if toplabels: 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) if sidelabels: text = Label('a={:.0f}nm2'.format(shape_area * 1000**2), 2) 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 add_cellLabels(self, layers, center=False): if not (type(layers) == list): layers = [layers] cellLattice = sorted(self.upCellLattice, key=itemgetter(1, 0)) # Sort the array first celllabelsUp = Cell('CellLabelsUp') h = self.cellsize vOffsetFactor = 1. txtSize = 200 for i, pt in enumerate(cellLattice): cellid = string.uppercase[i] celllabel = Cell('LBL_F_' + cellid) for l in layers: txt = Label(cellid, txtSize, layer=l) bbox = txt.bounding_box offset = np.array(pt) txt.translate(-np.mean(bbox, 0)) # Center text around origin txt.translate(offset) # Translate it to bottom of wafer celllabel.add(txt) if center: celllabelsUp.add(celllabel) # Middle of cell else: celllabelsUp.add( celllabel, origin=(0, -h / 2. * vOffsetFactor + np.mean(bbox, 0)[1])) # Bottom of cell for tri in self.upTris: self.add(celllabelsUp, origin=tri.centroid) cellLattice = sorted(self.downCellLattice, key=itemgetter(1, 0), reverse=True) celllabelsDown = Cell('CellLabelsDown') h = self.cellsize for i, pt in enumerate(cellLattice): cellid = string.uppercase[i] celllabel = Cell('LBL_F_' + cellid) for l in layers: txt = Label(cellid, txtSize, layer=l) bbox = txt.bounding_box offset = np.array(pt) txt.translate(-np.mean(bbox, 0)) # Center text around origin if self.symmetric_chips: txt.rotate(180) txt.translate(offset) # Translate it to bottom of wafer celllabel.add(txt) if center: celllabelsDown.add(celllabel) # Middle of cell else: celllabelsDown.add( celllabel, origin=(0, -h / 2. * vOffsetFactor + np.mean(bbox, 0)[1])) # Bottom of cell for tri in self.downTris: self.add(celllabelsDown, origin=tri.centroid)
def add_blockLabels(self, layers, center=False): if not (type(layers) == list): layers = [layers] vOffsetFactor = 1. blocklabelsUp = Cell('BlockLabelsUp') h = self.upTris[0].bounds[3] - self.upTris[0].bounds[1] sl_lattice = self.trisize + self.block_gap / np.tan(np.deg2rad(30)) h_lattice = np.sqrt(3.) / 2. * sl_lattice base = h_lattice for tri in self.upTris: lbl_col = self.blockcols[np.round(tri.centroid.x, 8)] lbl_row = self.blockrows[base * round(float(tri.bounds[1]) / base)] blockid = str(lbl_col) + str(lbl_row) blocklabel = Cell('LBL_B_' + blockid) for l in layers: txt = Label(blockid, 1000, layer=l) bbox = txt.bounding_box offset = np.array(tri.centroid) txt.translate(-np.mean(bbox, 0)) # Center text around origin txt.translate(offset) # Translate it to bottom of wafer blocklabel.add(txt) blocklabelsUp.add(blocklabel) if center: self.add(blocklabelsUp) else: self.add(blocklabelsUp, origin=(0, h / 2. * vOffsetFactor)) blocklabelsDown = Cell('BlockLabelsDown') for tri in self.downTris: lbl_col = self.blockcols[np.round(tri.centroid.x, 8)] lbl_row = self.blockrows[base * round(float(tri.bounds[1]) / base)] blockid = str(lbl_col) + str(lbl_row) blocklabel = Cell('LBL_' + blockid) for l in layers: txt = Label(blockid, 1000, layer=l) bbox = txt.bounding_box offset = np.array(tri.centroid) txt.translate(-np.mean(bbox, 0)) # Center text around origin if self.symmetric_chips: txt.rotate(180) txt.translate(offset) # Translate it to bottom of wafer blocklabel.add(txt) blocklabelsDown.add(blocklabel) if center: self.add(blocklabelsDown) else: self.add(blocklabelsDown, origin=(0, -h / 2. * vOffsetFactor))
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 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 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 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 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 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 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 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_branch_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 manybranches = Cell("ManyBranches") 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'] branch = make_branch(length, width, layers, rot_angle=rot_angle) x_spacing = length + pitch y_spacing = (length + pitch) * np.sin(np.deg2rad(60)) n_x = int(array_width / x_spacing) n_x2 = int((array_width - x_spacing / 2.) / x_spacing) n_y = np.round(array_height / 2. / y_spacing) n_y2 = np.round( (array_height - y_spacing / 2.) / 2. / y_spacing) shape_array = CellArray( branch, n_x, n_y, (x_spacing, y_spacing * 2.), origin=(-(n_x * x_spacing - pitch) / 2., -(2. * n_y * y_spacing - pitch * np.sin(np.deg2rad(60))) / 2.)) if n_x == n_x2: translation = (x_spacing / 2. - (n_x2 * x_spacing - pitch) / 2., y_spacing - (2. * n_y * y_spacing - pitch * np.sin(np.deg2rad(60))) / 2.) else: translation = (-(n_x2 * x_spacing - pitch) / 2., y_spacing - (2. * n_y * y_spacing - pitch * np.sin(np.deg2rad(60))) / 2.) shape_array2 = CellArray(branch, n_x2, n_y2, (x_spacing, y_spacing * 2.), origin=translation) branch_array = Cell( 'BranchArray-{:.2f}/{:.3f}/{:.1f}-lwp'.format( length, width, spacing)) branch_array.add(shape_array) branch_array.add(shape_array2) text = Label( 'w/p/l\n{:.0f}/{:.1f}/{:.1f}'.format( width * 1000, pitch, length), 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 branch_array.add(text) manybranches.add( branch_array, origin=((array_width + array_spacing) * i, (array_height + 2. * array_spacing) * j - array_spacing / 2.)) return manybranches
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