def add_block_labels(self, layers, unique_ids=False, save_ids=True, load_ids=True): if type(layers) is not list: layers = [layers] txtSize = 400 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. + 000)) #Shifted by 0.0 mm in y. ???
rot_angle = 0 _width = widths_1x1 _length = lengths_1x1 _slit = 1 _pitch = [pitch_std,pitch_std,pitch_std] #Coordinates of the large field and Marker positioning geometry lg_orig_x, lg_orig_y = -outer_margin - lgField_size/2 - (lgField_num-lg_col)*lgField_spacing, - outer_margin - lgField_size/2 - (lg_row+1)*lgField_spacing lgMark_margin = 50. lgMark_position = lgField_size/2 - lgMark_margin #Large Field lgField = Frame("LargeField", (lgField_size, lgField_size), []) # Create the large write field lgField.make_align_markers(10., 200., (lgMark_position, lgMark_position), l_markers, joy_markers=True, camps_markers=True) lgField_label = Label(lg_label, 40., position = (lg_orig_x-250, lg_orig_y + lgField_size/2 - 100), layer=l_lgBeam) # Middle Fields Definition mdCell = Cell("Middle Cell") md_spac_fact = 0.1 # Max 4x4 Middle Fields md_size_x = ((1 - md_spac_fact*(1 + md_num_col))*lgField_size)/md_num_col md_size_y = ((1 - md_spac_fact*(1 + md_num_row))*lgField_size)/md_num_row if md_num_col > 1: sp_col = md_num_col -1 else: sp_col = 1 if md_num_row > 1: sp_row = md_num_row -1 else: sp_row = 1 md_spacing_x = md_size_x + (md_spac_fact*lgField_size)*(md_num_col - 1)/sp_col
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) many_crosses = Cell("CrossArray") x_pos = 0 y_pos = 0 array_pitch = ny * (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 # 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 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... 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 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_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) 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 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)