def make_branch_device_array(self, spacing, _widths, array_height, array_width, array_spacing, len_inner, len_outer, n_membranes, layers): if not (type(layers) == list): layers = [layers] if not (type(_widths) == list): _widths = [_widths] for l in layers: i = -1 j = 0 manydevices = Cell("ManyDevices") for width in _widths: device = self.make_branch_device(width, spacing, len_inner, len_outer, n_membranes, l) [[x_min, y_min], [x_max, y_max]] = device.bounding_box x_size = abs(x_max - x_min) y_size = abs(y_max - y_min) i += 1 if i % 3 == 0: j += 1 # Move to array to next line i = 0 # Restart at left nx = int(array_width / (x_size + spacing)) ny = int(array_height / (y_size + spacing)) devices = CellArray(device, nx, ny, (x_size + spacing, y_size + spacing)) devices.translate((-(nx - 1) * (x_size + spacing) / 2., -(ny - 1) * (y_size + spacing) / 2.)) device_array = Cell("DeviceArray") device_array.add(devices) # Make the labels for each array of devices text = Label( 'w/s/l\n%i/%.1f/%i' % (width * 1000, spacing, len_outer), 5) lbl_vertical_offset = 1.40 if j % 2 == 0: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, -array_height / lbl_vertical_offset))) ) # Center justify label else: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, array_height / lbl_vertical_offset))) ) # Center justify label # TODO: Finish this below device_array.add(text) manydevices.add( device_array, origin=((array_width + array_spacing) * i, (array_height + 2. * array_spacing) * j - array_spacing / 2.)) self.add(manydevices, origin=(-i * (array_width + array_spacing) / 2, -(j + 1.5) * (array_height + array_spacing) / 2))
def add_cleave_xsection_nws(self): pitches = [0.5, 1., 2., 4.] widths = [10., 20., 40., 60., 100., 160., 240.] n_membranes = 10 length = 50 spacing = 10 cleave_xsection_cell = Cell("CleaveCrossSection") y_offset = 0 for pitch in pitches: for width in widths: nm_cell = Cell("P{:.0f}W{:.0f}".format(pitch, width)) slit = Path([(-length / 2., 0), (length / 2., 0)], width=width / 1000., layer=l_smBeam) nm_cell.add(slit) nm_cell_array = Cell("P{:.0f}W{:.0f}_Array".format(pitch, width)) tmp = CellArray(nm_cell, 1.0, n_membranes, [0, pitch]) nm_cell_array.add(tmp) cleave_xsection_cell.add(nm_cell_array, origin=(0, y_offset + pitch * n_membranes)) y_offset += pitch * n_membranes + spacing text = Label("P{:.1f}W{:.0f}".format(pitch, width), 1.0, layer=l_smBeam) text.translate(tuple(np.array(-text.bounding_box.mean(0)))) # Center justify label txt_cell = Cell("lbl_P{:.1f}W{:.0f}".format(pitch, width)) txt_cell.add(text) cleave_xsection_cell.add(txt_cell, origin=(length * 0.75, y_offset - 8.0)) cleave_xsection_cell.add(txt_cell, origin=(-length * 0.75, y_offset - 8.0)) y_offset += spacing * 3 center_x, center_y = (5000, 5000) for block in self.blocks: block.add(cleave_xsection_cell, origin=(center_x + 1150, center_y - 463)) # block.add(cleave_xsection_cell, origin=(center_x - 350, center_y + 350), rotation=45.) # >> VP_mod: disabled << block.add(cleave_xsection_cell, origin=(center_x + 463, center_y - 1150), rotation=90.) # >> VP_mod: disabled<<
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_slit_array(self, _pitches, spacing, _widths, _lengths, rot_angle, array_height, array_width, 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] manyslits = i = j = None for l in layers: i = -1 j = -1 manyslits = Cell("SlitArray") pitch = _pitches[0] for length in _lengths: 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 pitch_v = pitch / np.cos(np.deg2rad(rot_angle)) # widthV = width / np.cos(np.deg2rad(rotAngle)) nx = int(array_width / (length + spacing)) ny = 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, nx, ny, (length + spacing, pitch_v)) slits.translate((-(nx - 1) * (length + spacing) / 2., -(ny - 1) * pitch_v / 2.)) slit_array = Cell("SlitArray") slit_array.add(slits) text = Label('w/p/l\n%i/%i/%i' % (width * 1000, pitch, length), 5, layer=l) lbl_vertical_offset = 1.35 if j % 2 == 0: text.translate( tuple(np.array(-text.bounding_box.mean(0)) + np.array(( 0, -array_height / lbl_vertical_offset)))) # Center justify label else: text.translate( tuple(np.array(-text.bounding_box.mean(0)) + np.array(( 0, array_height / lbl_vertical_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.)) self.add(manyslits, origin=(-i * (array_width + array_spacing) / 2, -(j + 1.5) * ( array_height + array_spacing) / 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 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) center_x, center_y = (self.block_size[0]/2., self.block_size[1]/2.) for block in self.blocks: block.add(chip_lbl_cell, origin=(center_x, center_y - 4850))
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, layer=l_smBeam) 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_chip_labels(self): wafer_lbl = PATTERN + '\n' + WAFER_ID text = Label(wafer_lbl, 3., layer=l_smBeam) text.translate(tuple( np.array(-text.bounding_box.mean(0)))) # Center justify label chip_lbl_cell = Cell('chip_label') chip_lbl_cell.add(text) # Add it in all the cells for (i, pt) in enumerate(self.block_pts): origin = (pt + np.array([0.5, 0.5])) * self.block_size origin += np.array([0, -2850]) self.add(chip_lbl_cell, origin=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_shape_array(array_size, shape_area, shape_pitch, type, layer, labels=True): 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 labels: text = Label('{}'.format(type), 2, layer=l_smBeam) 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 add_block_labels(self, layers): txtSize = 2000 for (i, pt) in enumerate(self.block_pts): origin = (pt + np.array([0.5, 0.5])) * self.block_size blk_lbl = self.blockcols[pt[0]] + self.blockrows[pt[1]] for l in layers: txt = Label(blk_lbl, txtSize, layer=l) bbox = txt.bounding_box offset = np.array(pt) txt.translate(-np.mean(bbox, 0)) # Center text around origin lbl_cell = Cell("lbl_" + blk_lbl) lbl_cell.add(txt) origin += np.array([0, 0]) self.add(lbl_cell, origin=origin)
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) center_x, center_y = (5000, 5000) for block in self.blocks: block.add(chip_lbl_cell, origin=(center_x, center_y - 200)) block.add(chip_lbl_cell, origin=(center_x, center_y - 4500)) block.add(chip_lbl_cell, origin=(center_x + 4500, center_y), rotation= 90) block.add(chip_lbl_cell, origin=(center_x, center_y + 4500), rotation= 180) block.add(chip_lbl_cell, origin=(center_x - 4500, center_y), rotation= 270)
def add_block_labels(self, layers, quasi_unique_labels=False): if type(layers) is not list: layers = [layers] txtSize = 800 if quasi_unique_labels: unique_label_string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' possible_labels = [ "".join(x) for x in itertools.product(unique_label_string, repeat=2) ] blockids_set = set() while len(blockids_set) < len(self.blocks): blockids_set.add(random_choice(possible_labels)) blockids = list(blockids_set) for i, block in enumerate(self.blocks): blocklabel = Cell('LBL_B_' + blockids[i]) for l in layers: txt = Label(blockids[i], txtSize, layer=l) bbox = txt.bounding_box offset = (0, 0) txt.translate( -np.mean(bbox, 0)) # Center text around origin txt.translate(offset) # Translate it to bottom of wafer blocklabel.add(txt) block.add(blocklabel, origin=(self.block_size[0] / 2., self.block_size[1] / 2.)) else: for (i, pt) in enumerate(self.block_pts): origin = (pt + np.array([0.5, 0.5])) * self.block_size blk_lbl = self.blockcols[pt[0]] + self.blockrows[pt[1]] for l in layers: txt = Label(blk_lbl, txtSize, layer=l_lgBeam) bbox = txt.bounding_box offset = np.array(pt) txt.translate( -np.mean(bbox, 0)) # Center text around origin lbl_cell = Cell("lbl_" + blk_lbl) lbl_cell.add(txt) origin += np.array([0, 2000]) # Translate it up by 2mm self.add(lbl_cell, origin=origin)
def makeSlitArray(self, pitches, spacing, widths, lengths, rotAngle, arrayHeight, arrayWidth, arraySpacing, 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: i = -1 j = -1 manyslits = Cell("SlitArray") pitch = pitches[0] for length in lengths: 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, length), 5) 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.)) self.add(manyslits, origin=(-i * (arrayWidth + arraySpacing) / 2, -(j + 1.5) * (arrayHeight + arraySpacing) / 2))
def make_branch_array(x_vars, y_vars, stat_vars, var_names, spacing, rot_angle, array_height, array_width, array_spacing, layers): array_angle = 25 # 60 for 111 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) * np.cos(np.deg2rad(array_angle)) # y_spacing = (length + pitch) * np.sin(np.deg2rad(array_angle)) # n_x = int(array_width / x_spacing) # n_y = int(array_width / y_spacing) # shape_array = CellArray(branch, n_x, n_y, (x_spacing, y_spacing), origin=( # -(n_x * x_spacing - pitch * np.cos(np.deg2rad(array_angle))) / 2., # -(n_y * y_spacing - pitch * np.sin(np.deg2rad(array_angle))) / 2.)) branch_array = Cell( 'BranchArray-{:.0f}/{:.0f}/{:.2f}-wpl'.format( width, spacing, length)) # branch_array.add(shape_array) dir1 = pitch dir2 = length + 2 * pitch pts = generate_lattice([array_height, array_width], [[dir1, dir2], [dir2, dir1]]) for pt in pts: pt += np.array([-array_width / 2., -array_height / 2.]) branch_array.add(branch, origin=pt) if length * 1000 % 1000 == 0: text = Label('w/p/l\n{:.0f}/{:.0f}/{:.0f}'.format( width * 1000, pitch * 1000, length), 2, layer=l_smBeam) elif length * 1000 % 100 == 0: text = Label('w/p/l\n{:.0f}/{:.0f}/{:.1f}'.format( width * 1000, pitch * 1000, length), 2, layer=l_smBeam) else: text = Label('w/p/l\n{:.0f}/{:.0f}/{:.2f}'.format( width * 1000, pitch * 1000, length), 2, layer=l_smBeam) 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, layer=l_smBeam) 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_shape_array(self, array_size, shape_area, shape_pitch, type, layer, skew, toplabels=False, sidelabels=False): """ :param array_size: :param shape_area: :param shape_pitch: :param type: :param layer: :param skew: :param toplabels: :param sidelabels: :return: """ num_of_shapes = int(np.ceil(array_size / shape_pitch)) base_cell = Cell('Base') if 'tri' 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() == "circle": 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() == 'hexagon': 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) elif type.lower() == 'square': sq_side = np.sqrt(shape_area) sq_shape = scale( Rectangle([-sq_side / 2., -sq_side / 2.], [sq_side / 2., sq_side / 2.], layer=layer), [skew, 1.0]) sq_cell = Cell('Square') sq_cell.add(sq_shape) base_cell.add(sq_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 = { 'hexagon': 'hex', 'circle': 'circ', 'tris_right': 'triR', 'tris_left': 'triL', 'square': 'sqr' } if toplabels: text = Label('p={:.0f}nm'.format(shape_pitch * 1000), 10., layer=l_lgBeam) 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('s={:.0f}nm'.format(np.sqrt(shape_area) * 1000), 10., layer=l_lgBeam) 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 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, layer=l_smBeam) 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 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, layer=l_smBeam) 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 make_branch_array(self, _widths, _lengths, nx, ny, spacing_structs, spacing_arrays, rot_angle, layers): if not (type(layers) == list): layers = [layers] if not (type(_lengths) == list): _lengths = [_lengths] if not (type(_widths) == list): _widths = [_widths] l = layers[0] _length = _lengths[0] manyslits = i = j = None slits = [] for width in _widths: slit = Cell("Slit_{:.0f}".format(width * 1000)) line = Path([[-_length / 2., 0], [_length / 2., 0]], width=width, layer=l) slit.add(line) slits.append(slit) buffers = self.make_branch_device(0.08, 1.0, _lengths[0] / 2., _lengths[0] / 2., 4, layers[0], buffers_only=True) many_crosses = Cell("CrossArray") x_pos = 0 y_pos = 0 array_pitch = (ny - 1) * ( length + spacing_structs) - spacing_structs + spacing_arrays for j, width_vert in enumerate(_widths[::-1]): for i, width_horiz in enumerate(_widths): # Define a single cross cross = Cell("Cross_{:.0f}_{:.0f}".format( width_horiz * 1000, width_vert * 1000)) cross.add(slits[i]) # Horizontal slit cross.add(slits[j], rotation=90) # Vertical slit cross.add(buffers) # Define the cross array cross_array = Cell("CrossArray_{:.0f}_{:.0f}".format( width_horiz * 1000, width_vert * 1000)) slit_array = CellArray( cross, nx, ny, (_length + spacing_structs, _length + spacing_structs)) slit_array.translate( (-(nx - 1) * (_length + spacing_structs) / 2., (-(ny - 1) * (_length + spacing_structs) / 2.))) cross_array.add(slit_array) many_crosses.add(cross_array, origin=(x_pos, y_pos)) x_pos += array_pitch y_pos += array_pitch x_pos = 0 # Make the labels lbl_cell = Cell("Lbl_Cell") for i, width in enumerate(_widths): text_string = 'W{:.0f}'.format(width * 1000) text = Label(text_string, 5, layer=l) text.translate(tuple(np.array(-text.bounding_box.mean(0)))) x_offset = -1.5 * array_pitch + i * array_pitch text.translate(np.array((x_offset, 0))) # Center justify label lbl_cell.add(text) centered_cell = Cell('Centered_Cell') bbox = np.mean(many_crosses.bounding_box, 0) # Get center of cell centered_cell.add(many_crosses, origin=tuple(-bbox)) lbl_vertical_offset = 1.5 centered_cell.add(lbl_cell, origin=(0, -bbox[1] * lbl_vertical_offset)) centered_cell.add(lbl_cell, origin=(-bbox[1] * lbl_vertical_offset, 0), rotation=90) self.add(centered_cell, rotation=rot_angle)
def add_block_labels(self, layers, unique_ids=False, save_ids=True, load_ids=True): if type(layers) is not list: layers = [layers] 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 txtSize = 1000 blockids = [] if not unique_ids: for (i, tri) in enumerate(self.upTris + self.downTris): lbl_col = self.blockcols[np.round(tri.centroid.x, 8)] lbl_row = self.blockrows[base * round(float(tri.bounds[1]) / base)] blockids.append(str(lbl_col) + str(lbl_row)) else: existing_ids = {} existing_id_set = set() # Load the previously-used IDs from a JSON file if load_ids: master_db = '../../../ChipIDs_DB.json' if os.path.isfile(master_db): with open(master_db, 'r') as f: try: existing_ids = json.load(f) existing_id_set = set([ item for sublist in list(existing_ids.values()) for item in sublist ]) # Check if wafer is in the loaded database if load_ids and WAFER_ID in existing_ids: blockids = existing_ids[WAFER_ID] # If there is a reading error then proceed with a warning except json.decoder.JSONDecodeError: print( "Json Error: Couldn't load chip IDs from database!" ) existing_id_set = set() # If the IDs haven't already been set by loading them from the database if not blockids: # Generate some new IDs, but only use the ones that haven't previously been used unique_label_string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' possible_label_set = set([ "".join(x) for x in itertools.product(unique_label_string, repeat=2) ]) possible_label_set = possible_label_set - existing_id_set # Remove chip lbls from the set of possible lbls blockids_set = set() while len(blockids_set) < len(self.upTris + self.downTris): blockids_set.add(random_choice(list(possible_label_set))) blockids = list(blockids_set) # Save the labels to a file if save_ids: existing_ids.update({WAFER_ID: blockids}) json_string = json.dumps(existing_ids) json_string = json_string.replace( "], ", "],\n") # Make the file a bit easier to read in notepad with open(master_db, 'w') as f: f.write(json_string) block_labels = Cell('BlockLabels') for (i, tri) in enumerate(self.upTris + self.downTris): blockid = blockids[i] 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) block_labels.add(blocklabel) self.add(block_labels)
def make_slit_array(self, _pitches, spacing, _widths, _lengths, rot_angle, array_height, array_width, 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] manyslits = i = j = None for l in layers: i = -1 j = -1 manyslits = Cell("SlitArray") pitch = _pitches[0] for length in _lengths: 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 nx = int(array_width / (length + spacing)) ny = int(array_height / pitch) # Define the slits slit = Cell("Slits") rect = Rectangle((-length / 2., -width / 2.), (length / 2., width / 2.), layer=l) slit.add(rect) slits = CellArray(slit, nx, ny, (length + spacing, pitch)) slits.translate((-(nx - 1) * (length + spacing) / 2., -(ny - 1) * pitch / 2.)) slit_array = Cell("SlitArray") slit_array.add(slits) text = Label('w/p/l\n%i/%i/%i' % (width * 1000, pitch, length), 5, layer=l) lbl_vertical_offset = 1.35 if j % 2 == 0: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, -array_height / lbl_vertical_offset)) )) # Center justify label else: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, array_height / lbl_vertical_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.)) # This is an ugly hack to center rotated slits, should fix this properly... hacky_offset_x = 200 if rot_angle == 45 else 0 # TODO: fix this ugly thing hacky_offset_y = -25 if rot_angle == 45 else 0 self.add(manyslits, origin=(-i * (array_width + array_spacing) / 2 + hacky_offset_x, -(j + 1.5) * (array_height + array_spacing) / 2 + hacky_offset_y), rotation=rot_angle)
def add_block_labels(self, layers, unique_labels=False, save_ids=True, load_ids=True): if type(layers) is not list: layers = [layers] txtSize = 800 db_IDs = {} master_db = '../../../ChipIDs_DB.json' if os.path.isfile(master_db): with open(master_db, 'r') as f: try: db_IDs = json.load(f) db_label_set = set([ item for sublist in list(db_IDs.values()) for item in sublist ]) # Check if wafer is in the loaded database if load_ids and WAFER_ID in db_IDs: blockids = db_IDs[WAFER_ID] else: load_ids = False # If there is a reading error then proceed with a warning except json.decoder.JSONDecodeError: print("Json Error: Couldn't load chip IDs from database!") load_ids = False # Otherwise generate the IDs on the spot, still taking into account the database labels to avoid duplicates if not load_ids: if unique_labels: unique_label_string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' possible_label_set = set([ "".join(x) for x in itertools.product(unique_label_string, repeat=2) ]) possible_label_set = possible_label_set - db_label_set # Remove chip lbls from the set of possible lbls blockids_set = set() while len(blockids_set) < len(self.blocks): blockids_set.add(random_choice(list(possible_label_set))) blockids = list(blockids_set) else: blockids = [] for (i, pt) in enumerate(self.block_pts): blockids.append(self.blockcols[pt[0]] + self.blockrows[pt[1]]) # TODO: Save it to a master list of all the IDs for easy searching! # Check if the wafer ID already exists in the database, if not create new entry # Save the labels to a file if save_ids: # with open(filename_ids, 'w+') as f: # with open(master_db, 'a+') as f2: # for item in blockids: # f.write("%s\n" % item) # f2.write("%s\n" % item) db_IDs.update({WAFER_ID: blockids}) with open(master_db, 'w') as f: indent = 4 # Write the labels to the cells for i, block in enumerate(self.blocks): blocklabel = Cell('LBL_B_' + blockids[i]) for l in layers: txt = Label(blockids[i], txtSize, layer=l) bbox = txt.bounding_box offset = (0, 0) txt.translate(-np.mean(bbox, 0)) # Center text around origin txt.translate(offset) # Translate it to bottom of wafer blocklabel.add(txt) block.add(blocklabel, origin=(self.block_size[0] / 2., self.block_size[1] / 2.))
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, layer=l_smBeam) 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 add_block_labels(self, layers, unique_ids=False, save_ids=True, load_ids=True): if type(layers) is not list: layers = [layers] txtSize = 1000 blockids = [] if not unique_ids: for (i, pt) in enumerate(self.block_pts): blockids.append(self.blockcols[pt[0]] + self.blockrows[pt[1]]) else: existing_ids = {} existing_id_set = set() # Load the previously-used IDs from a JSON file if load_ids: master_db = '../../../ChipIDs_DB.json' if os.path.isfile(master_db): with open(master_db, 'r') as f: try: existing_ids = json.load(f) existing_id_set = set([ item for sublist in list(existing_ids.values()) for item in sublist ]) # Check if wafer is in the loaded database if load_ids and WAFER_ID in existing_ids: blockids = existing_ids[WAFER_ID] # If there is a reading error then proceed with a warning except json.decoder.JSONDecodeError: print( "Json Error: Couldn't load chip IDs from database!" ) existing_id_set = set() # If the IDs haven't already been set by loading them from the database if not blockids: # Generate some new IDs, but only use the ones that haven't previously been used unique_label_string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' possible_label_set = set([ "".join(x) for x in itertools.product(unique_label_string, repeat=2) ]) possible_label_set = possible_label_set - existing_id_set # Remove chip lbls from the set of possible lbls blockids_set = set() while len(blockids_set) < len(self.blocks): blockids_set.add(random_choice(list(possible_label_set))) blockids = list(blockids_set) # Save the labels to a file if save_ids: existing_ids.update({WAFER_ID: blockids}) json_string = json.dumps(existing_ids) json_string = json_string.replace( "], ", "],\n") # Make the file a bit easier to read in notepad with open(master_db, 'w') as f: f.write(json_string) # Write the labels to the cells for i, block in enumerate(self.blocks): blocklabel = Cell('LBL_B_' + blockids[i]) for l in layers: txt = Label(blockids[i], txtSize, layer=l) bbox = txt.bounding_box offset = (0, 0) txt.translate(-np.mean(bbox, 0)) # Center text around origin txt.translate(offset) # Translate it to bottom of wafer blocklabel.add(txt) block.add(blocklabel, origin=(self.block_size[0] / 2., self.block_size[1] / 2. - 400))
def makeSlitArray2(pitches, spacing, widths, lengths, rotAngle, arrayHeight, arrayWidth, arraySpacing, layers): ''' Give it a single pitch and lengths/widths and it will generate an array for all the combinations Makes seperate frame for each length value ''' 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") pitch = pitches[0] for length in lengths: 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 membrane = Path([(-length / 2., 0), (length / 2., 0)], width=width, layer=l) membrane_cell = Cell('Membrane_w{:.0f}_l{:.0f}'.format( width * 1000, length * 1000)) membrane_cell.add(membrane) slit = Cell("Slits") slit.add(membrane_cell, rotation=rotAngle) if Nx <= 1: slits = CellArray(slit, Nx, Ny, (length, pitchV)) slits.translate((0, -(Ny - 1) * (pitchV) / 2.)) else: 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), 2, layer=l_smBeam) 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 make_slit_patterns(self, sflabels, _pitches, spacing, _widths, _lengths, rot_angle, array_height, array_width, 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] manyslits = i = j = None for l in layers: i = -1 j = -1 manyslits = Cell("SlitArray") pitch = _pitches[0] for length in _lengths: 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 nx = int(array_width / (length + spacing)) ny = int(array_height / pitch) # Define the slits slit = Cell("Slit_w{:.0f}".format(width * 1000)) slit_path = Path([(-length / 2., 0), (length / 2., 0)], width=width, layer=l) slit.add(slit_path) slits = CellArray(slit, nx, ny, (length + spacing, pitch)) slits.translate((-(nx - 1) * (length + spacing) / 2., -(ny - 1) * pitch / 2.)) slit_array = Cell("SlitArray_w{:.0f}".format(width * 1000)) slit_array.add(slits) text = Label('w/p/l\n%i/%i/%i' % (width * 1000, pitch, length), 5, layer=l) lbl_vertical_offset = 1.35 if j % 2 == 0: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, -array_height / lbl_vertical_offset)) )) # Center justify label else: text.translate( tuple( np.array(-text.bounding_box.mean(0)) + np.array((0, array_height / lbl_vertical_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.)) specific_label = Label(sflabels, 20, layer=l) specific_label.translate( (-lbl_vertical_offset * smMarkerPosition, -lbl_vertical_offset * smMarkerPosition)) # Center Small Field slit_array.add(specific_label) # This is an ugly hack to center rotated slits, should fix this properly... if rot_angle == 45: # TODO: fix this ugly thing hacky_offset_x = 200 hacky_offset_y = -25 elif rot_angle == 90: hacky_offset_x = 356 hacky_offset_y = 96.5 elif rot_angle == 180: hacky_offset_x = 260 hacky_offset_y = 452 elif rot_angle == 270 or rot_angle == -90: hacky_offset_x = -96.5 hacky_offset_y = 356 else: hacky_offset_x = 0 hacky_offset_y = 0 self.add(manyslits, origin=(-(i * (array_width + array_spacing)) / 2 + hacky_offset_x, -(j + 1.5) * (array_height + array_spacing) / 2 + hacky_offset_y), rotation=rot_angle)
def make_tapered_cross_array(self, _nom_width, _taper_widths, _length, _taper_length, nx, ny, spacing_structs, spacing_arrays, rot_angle, layers): if not (type(layers) == list): layers = [layers] if not (type(_taper_widths) == list): _taper_widths = [_taper_widths] if type(_nom_width ) == list: # Only accept a single membrane width for now _nom_width = _nom_width[0] if type(_length ) == list: # Only accept a single membrane length for now _length = _length[0] if type(_taper_length ) == list: # Only accept a single taper length for now _taper_length = _taper_length[0] layer = layers[0] many_crosses = Cell("CrossArray") x_pos = 0 y_pos = 0 array_pitch = ny * (length + spacing_structs) - spacing_structs + spacing_arrays membrane_cell = Cell('Testing') # fix the taper length, put this in a loop and iterate over various combined taper width values for j, tw_vert in enumerate(_taper_widths): for i, tw_horiz in enumerate(_taper_widths): # Define a single cross cross = self.make_tapered_cross(_nom_width, _nom_width, tw_horiz, tw_vert, _length, _length, _taper_length, _taper_length, layer) # Define the cross array cross_array = Cell("TaperedCrossArray_{:.0f}_{:.0f}".format( tw_horiz * 1000, tw_vert * 1000)) slit_array = CellArray( cross, nx, ny, (_length + spacing_structs, _length + spacing_structs)) slit_array.translate( (-(nx - 1) * (_length + spacing_structs) / 2., (-(ny - 1) * (_length + spacing_structs) / 2.))) cross_array.add(slit_array) many_crosses.add(cross_array, origin=(x_pos, y_pos)) x_pos += array_pitch y_pos += array_pitch x_pos = 0 # Make the labels lbl_cell = Cell("Lbl_Cell") for i, width in enumerate(_taper_widths): text_string = 'TW{:.0f}'.format(width * 1000) text = Label(text_string, 5, layer=layer) text.translate(tuple(np.array(-text.bounding_box.mean(0)))) x_offset = -1.5 * array_pitch + i * array_pitch text.translate(np.array((x_offset, 0))) # Center justify label lbl_cell.add(text) # Make label for the whole field frame_lbl = Cell("Cell_Label") text_string = 'NomW {:.0f}, TL {:.0f}'.format(_nom_width * 1000, _taper_length * 1000) text = Label(text_string, 5, layer=layer) text.translate(tuple(np.array(-text.bounding_box.mean(0)))) frame_lbl.add(text) centered_cell = Cell('Centered_Cell') bbox = np.mean(many_crosses.bounding_box, 0) # Get center of cell centered_cell.add(many_crosses, origin=tuple(-bbox)) centered_cell.add(frame_lbl, origin=(0, -200)) lbl_vertical_offset = 1.5 centered_cell.add(lbl_cell, origin=(0, -bbox[1] * lbl_vertical_offset)) centered_cell.add(lbl_cell, origin=(-bbox[1] * lbl_vertical_offset, 0), rotation=90) self.add(centered_cell, rotation=rot_angle)