def save_multiple(shapes, filename, layers=None, cell_name="POLYGON", datatype=1000, ignore_interiors=False, **kw): if DO_RELOAD: reload(gdspy) poly_cell = gdspy.Cell(cell_name) for i, shape in enumerate(shapes): if not ignore_interiors and shape.has_interiors(): raise ValueError( "Polygon contains interiors, which can not be represented" " in the GDS file format. To ignore, call with ignore_interiors=True" ) vertex_lists = shape.get_exterior_vertex_lists() for vl in vertex_lists: if len(vl) > MAX_VERTICES: raise ValueError("Polygon contains {} vertices, more than the" " limit of {} vertices".format( len(vl), MAX_VERTICES)) layer = 0 if layers is not None: layer = layers[i] # shapely always duplicates the first vertex as the last vertex, get rid of that gds_poly = gdspy.Polygon(vl[:-1], datatype=datatype, layer=layer) poly_cell.add(gds_poly) gdspy.write_gds(filename, **kw)
def test(self): ld_fulletch = {'layer': 91, 'datatype': 1} ld_partetch = {'layer': 2, 'datatype': 3} ld_liftoff = {'layer': 0, 'datatype': 7} # um = 1 # cm = 10000*um # wafer_rad = 75*cm # die_size = [2500*um, 2500*um] # shot_size = [ 20, 20] main_cell = gdspy.Cell('MAIN') # shot_cell = gdspy.Cell('SHOT') die_cell = gdspy.Cell('DIE') # main_cell.add(die_cell) for die in self._gross_die: die_rect = gdspy.Rectangle( ((die.x()), (die.y())), ((die.x() + die.width()), (die.y() + die.height())), **ld_liftoff) die_cell.add(die_rect) # shot_cell.add(gdspy.CellArray(die_cell, shot_size[0], shot_size[1], (die_size[0], die_size[1]))) # main_cell.add(gdspy.CellArray(shot_cell, 20, 20, (die_size[0]*shot_size[0], die_size[1]*shot_size[1]))) wafer_poly = gdspy.Polygon([((qp.x()), (qp.y())) for qp in self._wafer_pts], **ld_fulletch) ebr_poly = gdspy.Polygon([(qp.x(), qp.y()) for qp in self._ebr_pts], **ld_partetch) main_cell.add(wafer_poly) main_cell.add(ebr_poly) gdspy.write_gds('first.gds')
def writeOut(self): """ @brief write GDSII, Pin, Bin for file based version Need to setGDS() and setPinBB Should be removed in later versions """ gdspy.write_gds(self.outGDS, [self.cell], unit=1.0e-6, precision=1.0e-9)
def corners2gds(corners, args): polyidx = [] with open(args.corner_seq, 'r') as f: for line in f: line = line.strip().split(',') tmp = [int(x) for x in line] polyidx.append(tmp) poly_cell = gdspy.Cell('tmp') polyvertice = [] for i, idx in enumerate(polyidx): polyvertice.append(idx2xy(corners, idx)) # poly=gdspy.Polygon(polyvertice,1) # poly_cell.add(poly) poly = gdspy.PolygonSet(polyvertice, 1) # poly_cell.add(poly) xlength = max(corners[:, 0]) - min(corners[:, 0]) ylength = max(corners[:, 1]) - min(corners[:, 1]) nX = args.nX nY = args.nY xsep = max(xlength, ylength) * args.sep ysep = xsep for i in range(nX): for j in range(nY): xpos = (xlength + xsep) * (i + 1) ypos = (ylength + ysep) * (j + 1) trans = gdspy.copy(poly, xpos, ypos) poly_cell.add(trans) if args.out_file is not None: gdspy.write_gds(args.out_file, unit=args.scale * 1.0e-9, precision=1.0e-9)
def writeDB(self, cktIdx, flipCell): """ @brief write to GdsData. Current version GDS is file based Need to setGDS() Should write to layoutDB in future. """ gdspy.write_gds(self.outGDS, [self.cell], unit=1.0e-6, precision=1.0e-9) ckt = self.dDB.subCkt(cktIdx) gdsData = ckt.GdsData() BB = basic.basic.BB(self.cell, flipCell) #bound = self.cell.cell.get_bounding_box() gdsData.setBBox(int(BB[0]), int(BB[1]), int(BB[2]), int(BB[3])) ckt.layout().setBoundary(int(BB[0]), int(BB[1]), int(BB[2]), int(BB[3])) gdsData.gdsFile = self.outGDS # Match pin name, current implementation is integer, bulk need to be ommited for res/cap/mos # Example, 0:drain, 1:gate, etc... nets = dict() for idx in range(ckt.numNets()): nets[int(ckt.net(idx).name)] = idx net_name = 0 for pin in self.cell.pin(): if net_name not in nets: net_name += 1 continue shape = pin.normalize_shape() if shape[1] > shape[3]: ckt.net(nets[net_name]).setIoShape(shape[3], shape[2], shape[1], shape[4]) else: ckt.net(nets[net_name]).setIoShape(shape[1], shape[2], shape[3], shape[4]) assert shape[1] < shape[3], "Device_generator, xLo = xHi" assert shape[2] < shape[4], "Device_generator, yLo > yHi" ckt.net(nets[net_name]).ioLayer = shape[0] net_name += 1
def contour2gds(contour0, args): """transform contour list to gds """ contour = [[ele[0] for ele in arr] for arr in contour0] if args.sharpen: contour = sharpenCorner(contour, args) flat_list = [item for sublist in contour for item in sublist] x = [arr[0] for arr in flat_list] y = [arr[1] for arr in flat_list] xlength = max(x) - min(x) ylength = max(y) - min(y) maxY = max(y) contour = [[[ele[0], maxY - ele[1]] for ele in arr] for arr in contour] poly_cell = gdspy.Cell('tmp') poly = gdspy.PolygonSet(contour, 1) nX = args.nX nY = args.nY xsep = max(xlength, ylength) * args.sep ysep = xsep for i in range(nX): for j in range(nY): xpos = (xlength + xsep) * (i + 1) ypos = (ylength + ysep) * (j + 1) trans = gdspy.copy(poly, xpos, ypos) poly_cell.add(trans) if args.out_file is not None: gdspy.write_gds(args.out_file, unit=args.scale * 1.0e-9, precision=1.0e-9)
def generate_gds(self, file): for cell_name in self.gds_cells.keys(): filename = file + '_%s.gds' % cell_name gdspy.write_gds(filename, cells=[cell_name], unit=1.0, precision=1e-9)
def write_gds(self, filename, unit=1e-6, precision=1e-9, auto_rename=True, max_cellname_length=28): if filename[-4:] != '.gds': filename += '.gds' tempname = self.name referenced_cells = list(self.get_dependencies(recursive=True)) all_cells = [self] + referenced_cells # Autofix names so there are no duplicates if auto_rename == True: all_cells_sorted = sorted(all_cells, key=lambda x: x.uid) used_names = {'toplevel': 1} for c in all_cells_sorted: if max_cellname_length is not None: new_name = c._internal_name[:max_cellname_length] else: new_name = c._internal_name if new_name not in used_names: used_names[new_name] = 1 c.name = new_name else: c.name = new_name + ('%0.3i' % used_names[new_name]) used_names[new_name] += 1 self.name = 'toplevel' gdspy.write_gds(filename, cells=all_cells, name='library', unit=unit, precision=precision) self.name = tempname return filename
def test_robustpath_togds(tmpdir): cell = gdspy.Cell('robustpath') rp = gdspy.RobustPath((0, 0), 0.1, layer=[1]) rp.segment((1, 1)) rp.segment((2, 3), 0) cell.add(rp) rp = gdspy.RobustPath((2, 0), [0.1, 0.2], 0.2, ends=['round', (0.2, 0.1)], layer=4, datatype=[1, 1], gdsii_path=True) rp.segment((3, 1)) cell.add(rp) rp = gdspy.RobustPath((0, 0), 0.1, layer=5, tolerance=1e-5, max_points=0, max_evals=1e6, gdsii_path=True) rp.segment((10, 0)) rp.turn(20, 'll') rp.turn(20, 'rr') rp.turn(20, 'll') cell.add(rp) fname = str(tmpdir.join('test.gds')) with pytest.warns(UserWarning): gdspy.write_gds(fname, unit=1, precision=1e-7) lib = gdspy.GdsLibrary(infile=fname, rename={'robustpath': 'file'}) assertsame(lib.cell_dict['file'], cell, tolerance=1e-3) gdspy.current_library = gdspy.GdsLibrary()
def save(shape, filename, cell_name="POLYGON", datatype=1000, ignore_interiors=False, **kw): if DO_RELOAD: reload(gdspy) poly_cell = gdspy.Cell(cell_name) if not ignore_interiors and shape.has_interiors(): raise ValueError( "Polygon contains interiors, which can not be represented" " in the GDS file format. To ignore, call with ignore_interiors=True" ) vertex_lists = shape.get_exterior_vertex_lists() for vl in vertex_lists: if len(vl) > MAX_VERTICES: raise ValueError( f"Polygon contains {len(vl)} vertices, more than the limit of {MAX_VERTICES} vertices" ) # shapely always duplicates the first vertex as the last vertex, get rid of that gds_poly = gdspy.Polygon(vl[:-1], datatype=datatype) poly_cell.add(gds_poly) gdspy.write_gds(filename, **kw)
def test_write_gds(library, tmpdir): gdspy.current_library = library fname1 = str(tmpdir.join('test1.gds')) gdspy.write_gds(fname1, name='lib', unit=2e-6, precision=1e-8) lib1 = gdspy.GdsLibrary(infile=fname1, units='convert', rename={'cell1': '1'}, layers={2: 4}, datatypes={4: 2}, texttypes={6: 7}) assert lib1.name == 'lib' assert len(lib1.cell_dict) == 4 assert set(lib1.cell_dict.keys()) == {'1', 'cell2', 'cell3', 'cell04'} c = lib1.cell_dict['1'] assert len(c.polygons) == len(c.labels) == 1 assert c.polygons[0].area() == 12.0 assert c.polygons[0].layers == [4] assert c.polygons[0].datatypes == [2] assert c.labels[0].text == 'label' assert c.labels[0].position[0] == 2 and c.labels[0].position[1] == -2 assert c.labels[0].anchor == 4 assert c.labels[0].rotation == 45 assert c.labels[0].magnification == 1.5 assert c.labels[0].x_reflection == True assert c.labels[0].layer == 5 assert c.labels[0].texttype == 7 c = lib1.cell_dict['cell2'] assert len(c.polygons) == 2 assert isinstance(c.polygons[0], gdspy.Polygon) and isinstance( c.polygons[1], gdspy.Polygon) c = lib1.cell_dict['cell3'] assert len(c.references) == 1 assert c.references[0].ref_cell == lib1.cell_dict['1'] assert c.references[0].origin[0] == 0 and c.references[0].origin[1] == 2 assert c.references[0].rotation == -90 assert c.references[0].magnification == 2 assert c.references[0].x_reflection == True c = lib1.cell_dict['cell04'] assert len(c.references) == 1 assert c.references[0].ref_cell == lib1.cell_dict['cell2'] assert c.references[0].origin[0] == -2 and c.references[0].origin[1] == -4 assert c.references[0].rotation == 180 assert c.references[0].magnification == 0.5 assert c.references[0].x_reflection == True assert c.references[0].spacing[0] == 2 and c.references[0].spacing[1] == 8 assert c.references[0].columns == 2 assert c.references[0].rows == 3 fname2 = str(tmpdir.join('test2.gds')) with open(fname2, 'wb') as fout: gdspy.write_gds(fout, name='lib2', unit=2e-3, precision=1e-5) with open(fname2, 'rb') as fin: lib2 = gdspy.GdsLibrary() lib2.read_gds(fin) assert lib2.name == 'lib2' assert len(lib2.cell_dict) == 4
def write(self, filename=DEFAULT_FILENAME): """Saves the generated structures. Args: filename: name of the file to be saved ommiting the .gds extension. """ gdspy.write_gds('{0}.gds'.format(filename), unit=self.unit, precision=self.precision)
def klayout(self,filename): # Check if klayout is already running. If not, write gds and open klayout. # If it is, just update the gds file if("klayout" in (p.name() for p in psutil.process_iter())): #Write the pattern as a gds file gdspy.write_gds(filename, unit=1.0e-6, precision=1.0e-9) else: gdspy.write_gds(filename, unit=1.0e-6, precision=1.0e-9) kl = call('./klayout_viewer %s' %filename,shell=True)
def generate_gds(self, file, max_points): for instance in self.gds_object_instances.keys(): obj = self.gds_object_instances[instance] if isinstance(obj, gdspy.Polygon) or isinstance(obj, gdspy.PolygonSet): self.gds_object_instances[instance] = obj.fracture(max_points=max_points, precision=1e-9) for cell_name in self.gds_cells.keys(): filename = file+'_%s.gds'%cell_name gdspy.write_gds(filename, cells=[cell_name], unit=1.0, precision=1e-9)
def generate_hall_bar_array(title, width_list, length_xx_list, dx, dy, orientation=0, leg_type='default'): """ Generates a gdspy cell populated with single nanowires with the specified parameters :param title: str. Also filename :param width_list: list of floats. In um :param length_xx_list: list of floats. In um :param dx: float. Distance in um between neighboring structures :param dy: float. Distance in um between neighboring structures :param orientation: float in degrees. 0deg is horizontal. :param leg_type: {'fishbone', 'default'} :return: gdspy viewer """ cell = gdspy.Cell(title) tools.make_title(title, cell, y=2 * dy, text_size=20) for i, w in enumerate(width_list): for j, L in enumerate(length_xx_list): wire_list = [] # will contain a wire and eventually labels, SmartWalls... x = j * dx y = - i * dy # labels if y == 0: x_label = 'L_xx=' + str(L) tools.make_x_label(x_label, wire_list, y=dy) if x == 0: y_label = 'w=' + str(int(w * 1000)) + 'nm\n' tools.make_y_label(y_label, wire_list, x=-dx) length_S_to_junction = 1.5 length_total = L + 2 * length_S_to_junction length_leg = 1 if j % 2 == 0: reservoir_enable = True else: reservoir_enable = False struct = tools.modified_hall_bar(w, length_total=length_total, length_leg=length_leg, length_xx=L, leg_offset=0, orientation=orientation, leg_type=leg_type, reservoir_enable=reservoir_enable) wire_list.append(struct) tools.add_label('X{}Y{}'.format(str(j), str(i)), wire_list, text_size=2, layer=20) # adds a number label to the wire_cell # tools.add_label('W{}L{}X{}Y{}'.format(str(int(w*1000)), str(L), str(j), str(i)), wire_list, text_size=2) # adds a number label to the wire_cell tools.move_list(wire_list, x, y) # translates the entire wire_cell cell.add(wire_list) gdspy.write_gds(os.path.join(pattern_directory, title + '.gds'), cells=[cell], unit=1.0e-6, precision=1e-11) # 1um unit, 1e-11 precision allows total cell area up to ~20mm*20mm return gdspy.LayoutViewer(cells=[cell])
def generate_gds_raster(lattice, raster, filename, unit=1e-6, tolerance=0.01, cell_bound=True, levels=[0.5]): """Traces a rasterization projected onto a lattice to generate a GDS file Note ---- The ``gdspy`` and ``scikit-image`` packages are required for exporting rasterized GDS files. Parameters ---------- lattice : Lattice raster : 2D array of floats filename : str unit : float, optional The GDS spatial units. Default is 1e-6, or 1 um. tolerance : float , optional The GDS tolerance parameter. Default is 0.01. cell_bound : bool, optional Whether a Polygon should be added to define the unit cell boundary. Default is True. levels : List[float], optional List of the raster levels to trace with ``skimage.measure.find_contours``. Default is [0.5]. """ contours = skimage.measure.find_contours(raster, levels) polygons = [] T = np.hstack((lattice.a1[:, np.newaxis], lattice.a2[:, np.newaxis])) for contour in contours: #TODO(ian): make sure that this coord transform is correct #TODO(ian): generalize the 0.5 boundary coords = T @ (contour/(np.array(raster.shape)[np.newaxis,:]-1) - 0.5).T points = [(x, y) for (x, y) in zip(coords[0,:], coords[1,:])] poly = gdspy.Polygon(points, layer=0, datatype=0) polygons.append(poly) gdspy.current_library = gdspy.GdsLibrary() cell = gdspy.Cell('CELL') cell.add(polygons) # TODO(ian): Need to do a boolean operation here if cell_bound: bounds = T @ np.array([[-0.5, -0.5, +0.5, +0.5],[-0.5, +0.5, +0.5, -0.5]]) points = [(x, y) for (x, y) in zip(bounds[0,:], bounds[1,:])] boundary = gdspy.Polygon(points, layer=0, datatype=1) cell.add(boundary) gdspy.write_gds(filename, unit=unit)
def write_gds(self, filename, unit=1e-6, precision=1e-9): if filename[-4:] != '.gds': filename += '.gds' tempname = self.name self.name = 'toplevel' referenced_cells = list(self.get_dependencies(recursive=True)) all_cells = [self] + referenced_cells gdspy.write_gds(filename, cells=all_cells, name='library', unit=unit, precision=precision) self.name = tempname
def test_flexpath_togds(tmpdir): cell = gdspy.Cell("flexpath") fp = gdspy.FlexPath([(0, 0), (0.5, 0.5), (1, 1)], 0.1, layer=[1], gdsii_path=True) cell.add(fp) fp = gdspy.FlexPath([(3, 0), (3.5, 0.5), (4, 1)], 0.1, layer=[21]) cell.add(fp) fp = gdspy.FlexPath( [(1, 0), (2, 1)], 0.1, [-0.1, 0.1], max_points=6, ends=["round", "extended"], layer=[2, 3], gdsii_path=True, ) cell.add(fp) fp = gdspy.FlexPath( [(2, 0), (3, 1)], [0.1, 0.2], 0.2, ends=(0.2, 0.1), layer=4, datatype=[10, 10], gdsii_path=True, ) cell.add(fp) fp = gdspy.FlexPath( [(0, 0), (0.5, 0), (1, 0), (1, 1), (0, 1), (-1, -2), (-2, 0)], 0.05, [0, -0.1, 0, 0.1], corners=["natural", "circular bend", "circular bend", "circular bend"], tolerance=1e-5, ends=["flush", "extended", (0.1, 0.2), "flush"], layer=[10, 11, 11, 12], bend_radius=[0, 0.3, 0.3, 0.2], gdsii_path=True, ).translate(-5, 0) cell.add(fp) fp = gdspy.FlexPath([(i, 2 + i**2) for i in numpy.linspace(0, 1, 8192)], 0.01, gdsii_path=True) cell.add(fp) fname = str(tmpdir.join("test.gds")) with pytest.warns(UserWarning): gdspy.write_gds(fname, unit=1, precision=1e-7) lib = gdspy.GdsLibrary(infile=fname, rename={"flexpath": "file"}) assertsame(lib.cell_dict["file"], cell, tolerance=1e-3) gdspy.current_library = gdspy.GdsLibrary()
def generate_2d_array(title, x_labels, y_labels, unit_function, arg_2d_list, dx=40, dy=40, preview=False): """ Generates a 2D array of patterns with unique identifiers, a title, a column of labels on the left and a row of labels on top :param title: string, also filename :param x_labels: list of strings, each is the label for a column :param y_labels: list of strings, each is the label for a row :param unit_function: a function that takes each args tuple as parameters and returns a gdspy shape :param dx: float, x distance in um :param dy: float, y distance in um :return: writes a .gds file and launches the gdspy layout viewer """ if len(x_labels) != len(arg_2d_list[0]) or len(y_labels) != len(arg_2d_list): print('Check dimensions of arg_2d_list and x/y_labels!') raise ValueError cell = gdspy.Cell(title) tools.make_title(title, cell, y=2 * dy, text_size=20) for y_count, arg_1d_list in enumerate(arg_2d_list): for x_count, args in enumerate(arg_1d_list): x = x_count * dx y = -y_count * dy wire_cell = [] # will contain a wire and eventually labels, SmartWalls... # labels if y == 0: x_label = x_labels[x_count] tools.make_x_label(x_label, wire_cell, y=dy, text_size=5) if x == 0: y_label = y_labels[y_count] tools.make_y_label(y_label, wire_cell, x=-dx/2, y=dy/2, text_size=4) wire_shape = unit_function(**args) if type(wire_shape) == tuple: for single_shape in wire_shape: wire_cell.append(single_shape) else: wire_cell.append(wire_shape) if x_count != 0: # left most row can be labeled by the big X labels tools.add_label('X{}Y{}'.format(str(x_count), str(y_count)), wire_cell, x=-dx/2, y=dy/2, text_size=2, layer=11) # adds a number label to the wire_cell tools.move_list(wire_cell, x, y) # translates the entire wire_cell cell.add(wire_cell) gdspy.write_gds(os.path.join(pattern_directory, title + '.gds'), cells=[cell], unit=1.0e-6, precision=1e-11) # 1um unit, 1e-11 precision allows total cell area up to ~20mm*20mm if preview: return gdspy.LayoutViewer(cells=[cell])
def corners2gds(corners, args): poly_cell = gdspy.Cell('tmp') polyidx = [None] * 3 polyidx[0] = [0, 1, 2, 5, 4, 3, 8, 7, 6] polyidx[1] = [ 18, 20, 19, 17, 28, 27, 12, 11, 26, 30, 10, 14, 13, 9, 29, 25, 22, 21, 24, 23, 16, 15, 39, 40, 29, 31, 41, 42, 37, 38, 43, 44, 32, 44, 30, 45, 46, 33, 34, 51, 49, 50, 52, 35, 36, 47, 48 ] polyidx[2] = [53, 54, 55, 58, 56, 57, 59, 60, 58, 59, 60, 61, 62] for i, idx in enumerate(polyidx): polyvertice = idx2xy(corners, idx) poly = gdspy.Polygon(polyvertice, 1) poly_cell.add(poly) if args.out_file is not None: gdspy.write_gds(args.out_file, unit=1.0e-6, precision=1.0e-9)
def contour2gds(contour0, args): # print 'contour0',contour0 contour = [[ele[0] for ele in arr] for arr in contour0] # print 'contour1',contour if args.sharpen: contour = sharpenCorner(contour, args) # print 'contour2',contour flat_list = [item for sublist in contour for item in sublist] # print 'flat_list',flat_list x = [arr[0] for arr in flat_list] y = [arr[1] for arr in flat_list] # print 'x', x # print 'y', y xlength = max(x) - min(x) ylength = max(y) - min(y) maxY = max(y) # contour=[[[ele[0][0],maxY-ele[0][1]] for ele in arr] for arr in contour0] contour = [[[ele[0], maxY - ele[1]] for ele in arr] for arr in contour] # for sublist in contour: # for ele in sublist: # ele[1]=maxY-ele[1] poly_cell = gdspy.Cell('tmp') poly = gdspy.PolygonSet(contour, 1) # poly_cell.add(poly) # print 'max/min x',max(x),min(x) # print 'max/min y',max(y),min(y) # print 'length',xlength,ylength nX = args.nX nY = args.nY xsep = max(xlength, ylength) * args.sep ysep = xsep for i in range(nX): for j in range(nY): xpos = (xlength + xsep) * (i + 1) ypos = (ylength + ysep) * (j + 1) trans = gdspy.copy(poly, xpos, ypos) poly_cell.add(trans) if args.out_file is not None: gdspy.write_gds(args.out_file, unit=args.scale * 1.0e-9, precision=1.0e-9)
def gen_gds(save_folder: str, sim_width: float) -> None: """Generates a GDS file of the grating. Args: save_folder: Location where log files are saved. It is assumed that the optimization plan is also saved there. sim width: width of the simulation """ # Load the optimization plan. with open(os.path.join(save_folder, "optplan.json")) as fp: plan = optplan.loads(fp.read()) dx = plan.transformations[-1].parametrization.simulation_space.mesh.dx # Load the data from the latest log file. with open(workspace.get_latest_log_file(save_folder), "rb") as fp: log_data = pickle.load(fp) if log_data["transformation"] != plan.transformations[-1].name: raise ValueError("Optimization did not run until completion.") coords = log_data["parametrization"]["vector"] * dx # if plan.transformations[-1].parametrization.inverted: # coords = np.insert(coords, 0, 0, axis=0) # coords = np.insert(coords, -1, sim_width, axis=0) # TODO Not sure about this part below creating rectangles # Change the variables and names here # `coords` now contains the location of the grating edges. Now draw a # series of rectangles to represent the grating. grating_poly = [] for i in range(0, len(coords), 2): grating_poly.append( ((coords[i], -sim_width / 2), (coords[i], sim_width / 2), (coords[i - 1], sim_width / 2), (coords[i - 1], -sim_width / 2))) # Save the grating to `annulus.gds`. grating = gdspy.Cell("ANNULUS", exclude_from_current=True) grating.add(gdspy.PolygonSet(grating_poly, 100)) gdspy.write_gds(os.path.join(save_folder, "annulus.gds"), [grating], unit=1.0e-9, precision=1.0e-9)
def bitmarker_2inch(): dx = 20 dy = 20 # text_size = 100 nrows = 32 ncols = 32 output_dir = r'/Users/wgz/Downloads' title = 'BitmarkerArray' cell = gp.Cell(title) for x in range(ncols): for y in range(nrows): # x_label = string.ascii_uppercase[x] # y_label = str(y) # shape = gp.Text(x_label+y_label, text_size, position=(x*dx, -y*dy), layer=10) shape = tools.bitmarker(x, y) shape.translate(x*dx, -y*dy) cell.add(shape) gp.LayoutViewer(cells=[cell]) gp.write_gds(os.path.join(output_dir, title + '.gds'), cells=[cell], unit=1.0e-6, precision=1e-10)
def klayout(self, filename): # Check if klayout is already running. If not, write gds and open klayout. # If it is, just update the gds file if ("klayout" in (p.name() for p in psutil.process_iter())): #Write the pattern as a gds file gdspy.write_gds(filename, unit=1.0e-6, precision=1.0e-9) else: gdspy.write_gds(filename, unit=1.0e-6, precision=1.0e-9) # kl = call('./klayout_viewer %s' %filename,shell=True) file = open("klayout_viewer", "w") file.write("#!/bin/bash") file.write("\n") file.write("\n") file.write("FOLDER=$PWD") file.write("\n") file.write("\n") file.write( "/Applications/klayout.scripts/KLayoutEditor.app/Contents/MacOS/KLayoutEditor.sh -s ${FOLDER}/${@}" ) file.close() self.call_bash("klayout_viewer", filename)
def create_ring_gds(radius, width): # Reload the library each time to prevent gds library name clashes importlib.reload(gdspy) ringCell = gdspy.Cell("ring_resonator_r{}_w{}".format(radius, width)) # Draw the ring ringCell.add( gdspy.Round((0, 0), inner_radius=radius - width / 2, radius=radius + width / 2, layer=RING_LAYER)) # Draw the first source ringCell.add( gdspy.Rectangle((radius - width, 0), (radius + width, 0), SOURCE0_LAYER)) # Draw the second source ringCell.add( gdspy.Rectangle((-radius - width, 0), (-radius + width, 0), SOURCE1_LAYER)) # Draw the monitor location ringCell.add( gdspy.Rectangle((radius - width / 2, 0), (radius + width / 2, 0), MONITOR_LAYER)) # Draw the simulation domain pad = 2 # padding between waveguide and edge of PML ringCell.add( gdspy.Rectangle((-radius - width / 2 - pad, -radius - width / 2 - pad), (radius + width / 2 + pad, radius + width / 2 + pad), SIMULATION_LAYER)) filename = "ring_r{}_w{}.gds".format(radius, width) gdspy.write_gds(filename, unit=1.0e-6, precision=1.0e-9) return filename
def generate_gds(phc, filename, unit=1e-6, tolerance=0.01): """Export a GDS file for all layers of a photonic crystal Note ---- The ``gdspy`` package is required for exporting GDS files. Parameters ---------- phc : PhotCryst filename : str unit : float, optional The GDS spatial units. Default is 1e-6, or 1 um. tolerance : float , optional The GDS tolerance parameter. Default is 0.01. """ gdspy.current_library = gdspy.GdsLibrary() cell = gdspy.Cell('CELL') # TODO: Can also add a `datatype`, ranging from 0-255, to each shape for use # by whatever program ends up reading the GDS for i, layer in enumerate(phc.layers): for shape in layer.shapes: if type(shape) in [Poly, Square, Hexagon]: points = [(x, y) for (x,y) in zip(shape.x_edges[:-1], shape.y_edges[:-1])] poly = gdspy.Polygon(points, layer=i, datatype=1) cell.add(poly) elif type(shape) == Circle: circle = gdspy.Round((shape.x_cent, shape.y_cent), shape.r, layer=i, datatype=1, tolerance=tolerance) cell.add(circle) else: raise RuntimeError("Unknown shape type, %s, found in layer %d of phc" % (type(shape), i)) gdspy.write_gds(filename, unit=unit)
def svg2gds_bend(df: pd.DataFrame, line_width: float = 0.125, bend_radius: float = 5, gds_filename: str = 'fiberBoard896bend.gds', save_folder: str = './results/') -> None: gdspy.current_library = gdspy.GdsLibrary() # gdspy.unit=1e-3 cell = gdspy.Cell('wiring896') for i in range(df.shape[0]): points = [] for j in range(len(df["inflection_x"][i])): points = points + [ tuple([df["inflection_x"][i][j], df["inflection_y"][i][j]]) ] # multiply 1000 to convert mm to um sp = gdspy.FlexPath(points, line_width, corners="circular bend", bend_radius=bend_radius, gdsii_path=True) cell.add(sp) gdspy.write_gds(save_folder + gds_filename)
def poly2gds(polyvertice, corners, args): f = open('auto.seq', 'w') epsilon = 4 for vset in polyvertice: # print('vset',vset) seqList = [] for v in vset: for i, corner in enumerate(corners): dist = distance(v, corner) if dist <= epsilon: # print('dist',dist) seqList.append(i) continue f.write(','.join(str(x) for x in seqList) + '\n') # print('seqList',seqList) f.close() poly_cell = gdspy.Cell('tmp') poly = gdspy.PolygonSet(polyvertice, 1) # poly_cell.add(poly) xlength = max(corners[:, 0]) - min(corners[:, 0]) ylength = max(corners[:, 1]) - min(corners[:, 1]) nX = args.nX nY = args.nY xsep = max(xlength, ylength) * args.sep ysep = xsep for i in range(nX): for j in range(nY): xpos = (xlength + xsep) * (i + 1) ypos = (ylength + ysep) * (j + 1) trans = gdspy.copy(poly, xpos, ypos) # print poly poly_cell.add(trans) if args.out_file is not None: gdspy.write_gds(args.out_file, unit=args.scale * 1.0e-9, precision=1.0e-9)
# cdc = ContraDirectionalCoupler(wgt, length=30.0, gap=1.0, period=0.5, dc=0.5, angle=np.pi/12.0, width_top=3.0, width_bot=2.0, input_bot=True, **wg1.portlist["output"]) # tk.add(top, cdc) # wg1=Waveguide([(0,0), (0,100), (50,200), (50, 215)], wgt) wg1=Waveguide([(0,0), (100,0)], wgt) tk.add(top, wg1) cdc2 = ContraDirectionalCoupler(wgt, length=30.0, gap=1.0, period=0.5, dc=0.5, angle=np.pi/12.0, width_top=3.0, width_bot=2.0, dw_top=0.4, dw_bot=0.2, input_bot=False, contradc_wgt=contradc_wgt, fins=True, **wg1.portlist["output"]) tk.add(top, cdc2) # x0,y0 = cdc2.portlist["input_bot"]["port"] # wg2=Waveguide([(x0,y0), (x0,y0-15), (x0+50,y0-115), (x0+50, y0-215)], wgt) # tk.add(top, wg2) # dc1 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **wg1.portlist["output"]) # dc2 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=True, **dc1.portlist["output_top"]) # dc3 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **dc1.portlist["output_bot"]) # dc4 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **dc2.portlist["output_bot"]) # dc5 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=True, **dc2.portlist["output_top"]) # dc6 = ContraDirectionalCoupler(wgt, length=30.0, gap=0.5, period=0.220, dc=0.5, angle=np.pi/6.0, width_top=2.0, width_bot=0.75, input_bot=False, **dc3.portlist["output_bot"]) # tk.add(top, dc1) # tk.add(top, dc2) # tk.add(top, dc3) # tk.add(top, dc4) # tk.add(top, dc5) # tk.add(top, dc6) # gdspy.LayoutViewer(cells=top) gdspy.write_gds('contradc.gds', unit=1.0e-6, precision=1.0e-9)
100, ltail=100, d_dots=d_dots, constriction=False, SQUID=False) res4_x = 4500 res4_coarse = [ rs.move(i, res4_x, feedline_bot - feedline_sep + feedline_y) for i in res4[0] ] res4_fine = [ rs.move(i, res4_x, feedline_bot - feedline_sep + feedline_y) for i in res4[1] ] res4_remove = [ rs.move(i, res4_x, feedline_bot - feedline_sep + feedline_y) for i in res4[2] ] for i in res4_coarse: poly_cell.add(gdspy.Polygon(i, 4)) for i in res4_fine: poly_cell.add(gdspy.Polygon(i, 4)) DC = rs.DC_contacts_etch(4800, 5800, 10, 100, 300, 10) for i in DC: poly_cell.add(gdspy.Polygon(i, 5)) #Write the pattern as a gds file os.chdir(folder) gdspy.write_gds('chip_test.gds', unit=1.0e-6, precision=1.0e-9) # gdspy.LayoutViewer()
text2 = gdspy.copy(text1, 0, -20) label1 = gdspy.Label( 'Created with gdspy ' + gdspy.__version__, (-7, -36), 'nw', layer=6) label2 = gdspy.copy(label1, 0, -20) trans_cell.add(text1) trans_cell.add(text2) trans_cell.add(label1) trans_cell.add(label2) # ------------------------------------------------------------------ # # OUTPUT # ------------------------------------------------------------------ # # Output the layout to a GDSII file (default to all created cells). # Set the units we used to micrometers and the precision to nanometers. gdspy.write_gds('tutorial.gds', unit=1.0e-6, precision=1.0e-9) # ------------------------------------------------------------------ # # IMPORT # ------------------------------------------------------------------ # # Import the file we just created, and extract the cell 'POLYGONS'. To # avoid naming conflict, we will rename all cells. gdsii = gdspy.GdsLibrary() gdsii.read_gds( 'tutorial.gds', rename={ 'POLYGONS': 'IMPORT_POLY', 'PATHS': 'IMPORT_PATHS', 'OPERATIONS': 'IMPORT_OPER', 'SLICE': 'IMPORT_SLICE',
def test_write_gds(tmpdir): gdspy.current_library = gdspy.GdsLibrary() c1 = gdspy.Cell('fu_rw_gds_1') c1.add(gdspy.Rectangle((0, -1), (1, 2), 2, 4)) c1.add(gdspy.Label('label', (1, -1), 'w', 45, 1.5, True, 5, 6)) c2 = gdspy.Cell('fu_rw_gds_2') c2.add(gdspy.Round((0, 0), 1, number_of_points=32, max_points=20)) c3 = gdspy.Cell('fu_rw_gds_3') c3.add(gdspy.CellReference(c1, (0, 1), -90, 2, True)) c4 = gdspy.Cell('fu_rw_gds_4') c4.add(gdspy.CellArray(c2, 2, 3, (1, 4), (-1, -2), 180, 0.5, True)) fname1 = str(tmpdir.join('test1.gds')) gdspy.write_gds(fname1, name='lib', unit=2e-6, precision=1e-8) lib1 = gdspy.GdsLibrary( infile=fname1, units='convert', rename={'fu_rw_gds_1': '1'}, layers={2: 4}, datatypes={4: 2}, texttypes={6: 7}) assert lib1.name == 'lib' assert len(lib1.cell_dict) == 4 assert set(lib1.cell_dict.keys()) == { '1', 'fu_rw_gds_2', 'fu_rw_gds_3', 'fu_rw_gds_4' } c = lib1.cell_dict['1'] assert len(c.elements) == len(c.labels) == 1 assert c.elements[0].area() == 12.0 assert c.elements[0].layers == [4] assert c.elements[0].datatypes == [2] assert c.labels[0].text == 'label' assert c.labels[0].position[0] == 2 and c.labels[0].position[1] == -2 assert c.labels[0].anchor == 4 assert c.labels[0].rotation == 45 assert c.labels[0].magnification == 1.5 assert c.labels[0].x_reflection == True assert c.labels[0].layer == 5 assert c.labels[0].texttype == 7 c = lib1.cell_dict['fu_rw_gds_2'] assert len(c.elements) == 2 assert isinstance(c.elements[0], gdspy.Polygon) \ and isinstance(c.elements[1], gdspy.Polygon) c = lib1.cell_dict['fu_rw_gds_3'] assert len(c.elements) == 1 assert isinstance(c.elements[0], gdspy.CellReference) assert c.elements[0].ref_cell == lib1.cell_dict['1'] assert c.elements[0].origin[0] == 0 and c.elements[0].origin[1] == 2 assert c.elements[0].rotation == -90 assert c.elements[0].magnification == 2 assert c.elements[0].x_reflection == True c = lib1.cell_dict['fu_rw_gds_4'] assert len(c.elements) == 1 assert isinstance(c.elements[0], gdspy.CellArray) assert c.elements[0].ref_cell == lib1.cell_dict['fu_rw_gds_2'] assert c.elements[0].origin[0] == -2 and c.elements[0].origin[1] == -4 assert c.elements[0].rotation == 180 assert c.elements[0].magnification == 0.5 assert c.elements[0].x_reflection == True assert c.elements[0].spacing[0] == 2 and c.elements[0].spacing[1] == 8 assert c.elements[0].columns == 2 assert c.elements[0].rows == 3 fname2 = str(tmpdir.join('test2.gds')) with open(fname2, 'wb') as fout: gdspy.write_gds(fout, name='lib2', unit=2e-3, precision=1e-5) with open(fname2, 'rb') as fin: lib2 = gdspy.GdsLibrary() lib2.read_gds(fin) assert lib2.name == 'lib2' assert len(lib2.cell_dict) == 4