num_lines = 20, line_width = 0.4, diameter = 20, layer = 0 ) qp(D) # quickplot the geometry create_image(D, 'litho_star') # example-litho_calipers import phidl.geometry as pg from phidl import quickplot as qp D = pg.litho_calipers( notch_size = [1,5], notch_spacing = 2, num_notches = 7, offset_per_notch = 0.1, row_spacing = 0, layer1 = 1, layer2 = 2) qp(D) # quickplot the geometry create_image(D, 'litho_calipers') # example-extract import phidl.geometry as pg from phidl import quickplot as qp from phidl import Device E = Device() E.add_ref(pg.ellipse(layer = {0,1})) #X = pg.ellipse(layer = {0,1}) D = pg.extract(E, layers = [0,1])
# experimental and may change with time. # Let's save this file so we can practice importing it in the next step D.write_gds('MyNewGDS.gds') #============================================================================== # Premade geometry: Lithography shapes #============================================================================== # PHIDL comes with a set of handy functions for creating standard lithographic # test structures, such as calipers (for detecting fabrication-layer-offsets), # stars, and positive + negative-tone steps D = Device() d1 = D << pg.litho_calipers(notch_size=[3, 10], notch_spacing=2, num_notches=7, offset_per_notch=0.2, row_spacing=0, layer1=1, layer2=2).rotate(90) d2 = D << pg.litho_steps( line_widths=[1, 2, 4, 8, 16 ], line_spacing=10, height=80, layer=0).movex(80) d3 = D << pg.litho_star(num_lines=16, line_width=3, diameter=80, layer=4).movex(240) d1.y = d2.y = d3.y qp(D) D.write_gds('LithographyTestStructuresMetrics.gds') #============================================================================== # Importing GDS files #==============================================================================
def verniers(scale=[1, 0.5, 0.1], layers=[1, 2], label='TE', text_size=20, reversed=False): """ Create a cell with vernier aligners. Parameters ---------- scale : iterable of float (default [1,0.5,0.25]) each float in list is the offset of a vernier. for each of them a vernier will be created in the X-Y axis layers : 2-len iterable of int (default [1,2]) define the two layers for the verniers. label : str (default "TE") add a label to the set of verniers. text_size : float (default) label size reversed : boolean if true, creates a negative alignment mark for the second layer Returns ------- cell : phidl.Device. """ cell = dl.Device(name="verniers") import numpy if not isinstance(scale, numpy.ndarray): scale = np.array(scale) scale = np.sort(scale) xvern = [] for dim in scale: notch_size = [dim * 5, dim * 25] notch_spacing = dim * 10 num_notches = 5 notch_offset = dim row_spacing = 0 layer1 = layers[0] layer2 = layers[1] cal=pg.litho_calipers(\ notch_size,\ notch_spacing,\ num_notches,\ notch_offset,\ row_spacing,\ layer1,\ layer2) cal.flatten() if reversed: tobedel = cal.get_polygons(by_spec=(layer2, 0)) cal = cal.remove_polygons( lambda pts, layer, datatype: layer == layer2) replica = dl.Device() replica.add(gdspy.PolygonSet(tobedel, layer=layer2)) frame = dl.Device() frame.add(pg.bbox(replica.bbox, layer=layer2)) frame_ext = dl.Device() frame_ext.add( gdspy.PolygonSet(frame.copy('tmp', scale=1.5).get_polygons(), layer=layer2)) frame_ext.flatten() frame_ext.move(origin=frame_ext.center, destination=replica.center) new_cal = pg.boolean(replica, frame_ext, 'xor', layer=layer2) new_cal.rotate(angle=180, center=(cal.xmin + cal.xsize / 2, cal.ymin)) new_cal.move(destination=(0, -notch_size[1])) cal << new_cal cal.flatten() xvern.append(cal) g = dl.Group(xvern) g.distribute(direction='y', spacing=scale[-1] * 20) g.align(alignment='x') xcell = dl.Device(name="x") for x in xvern: xcell << x xcell = pt.join(xcell) vern_x = cell << xcell vern_y = cell << xcell vern_y.rotate(angle=-90) vern_y.move(origin=(vern_y.xmin,vern_y.y),\ destination=(vern_x.x+scale[-1]*10,vern_x.ymin-scale[-1]*10)) cell.absorb(vern_x) cell.absorb(vern_y) label = pg.text(text=label, size=text_size, layer=layers[0]) label.move(destination=(cell.xmax - label.xsize / 2, cell.ymax - 2 * label.ysize)) overlabel = pg.bbox(label.bbox, layer=layers[1]) overlabel_scaled = dl.Device().add( gdspy.PolygonSet(overlabel.copy('tmp', scale=2).get_polygons(), layer=layers[1])) overlabel_scaled.move(origin=overlabel_scaled.center,\ destination=label.center) cutlab = pg.boolean(label, overlabel_scaled, 'xor', layer=layers[1]) cell << label cell << cutlab cell = pt.join(cell) return cell