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 subtract(self, blank_entities, tool_entities, keep_originals=True): if isinstance(blank_entities, list): for blank_entity in blank_entities: self.subtract(blank_entity, tool_entities, keep_originals=keep_originals) else: blank_entity = blank_entities #1 We clear the cell of all elements and create lists to store the polygons blank_polygon = self.gds_object_instances.pop(blank_entity.name) self.cell = self.gds_cells[ blank_entity.body. name] # assumes blank and tool are in same body self.cell.polygons.remove(blank_polygon) tool_polygons = [] for tool_entity in tool_entities: tool_polygon = self.gds_object_instances[tool_entity.name] if isinstance(tool_polygon, gdspy.PolygonSet): for polygon in tool_polygon.polygons: tool_polygons.append(polygon) else: tool_polygons.append(tool_polygon) #2 subtract operation tool_polygon_set = gdspy.PolygonSet(tool_polygons, layer=blank_entity.layer) subtracted = gdspy.boolean(blank_polygon, tool_polygon_set, 'not', precision=TOLERANCE, max_points=0, layer=blank_entity.layer) if subtracted is not None: #3 At last we update the cell and the gds_object_instance self.gds_object_instances[blank_entity.name] = subtracted self.cell.add(subtracted) else: print('Warning: the entity %s was fully \ subtracted' % blank_entity.name) dummy = gdspy.Polygon([[0, 0]]) self.gds_object_instances[blank_entity.name] = dummy self.cell.add(dummy) blank_entity.delete()
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 __convertShapely2gds(topCell, shape, layerNumber): exterior = list(shape.exterior.coords) interiors = [list(interior.coords) for interior in list(shape.interiors)] exterior = gdspy.Polygon(exterior, layer=layerNumber) interiors = gdspy.PolygonSet(interiors, layer=layerNumber) operands = [exterior, interiors] # The epsilon value of 1e-7 was chosen to avoid segfaults that would occur # at the default value of epsilon (1e-13) # If Python is crashing at this line in the future, increase the value of # epsilon to correct the issue. booled = gdspy.boolean(operands, lambda ext, int: ext and not int, layer=layerNumber, eps=1e-7) topCell.add(booled)
def rect_array(self, pos, size, columns,rows,spacing, origin=(0, 0), **kwargs): pos, size = parse_entry(pos, size) name = kwargs['name'] layer = kwargs['layer'] points = [(pos[0],pos[1]), (pos[0]+size[0],pos[1]+0), (pos[0]+size[0],pos[1]+size[1]), (pos[0],pos[1]+size[1])] poly1 = gdspy.Polygon(points, layer) self.gds_object_instances[name] = poly1 cell_to_copy = gdspy.Cell('cell_to_copy') self.gds_cells['cell_to_copy'] = cell_to_copy cell_to_copy.add(poly1) spacing = parse_entry(spacing) cell_array=gdspy.CellArray(cell_to_copy, columns, rows, spacing, origin) polygon_list=cell_array.get_polygons() poly2 = gdspy.PolygonSet(polygon_list, layer) self.cell.add(poly2) self.gds_object_instances[name] = poly2
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)
def cut_out_holes(polygons, layer=0, datatype=0): top_level_polygons = [] used_polygons = set() for polygon_ext in polygons: polygons_to_cut = [polygon_ext] for polygon_int in polygons: if polygon_ext is polygon_int: continue # if g.inside([polygon_ext], g.Polygon(polygon_int))[0]: if g.inside([polygon_int], g.Polygon(polygon_ext))[0]: polygons_to_cut.append(polygon_int) used_polygons.add(make_hashable(polygon_int)) if len(polygons_to_cut) >= 2: used_polygons.add(make_hashable( polygons_to_cut[0])) # don't add an un-cut exterior top_level_polygons.append(polygons_to_cut) for polygon in polygons: if make_hashable(polygon) not in used_polygons: top_level_polygons.append([polygon]) result = [ reduce(partial(cut_out_hole, layer=layer, datatype=datatype), polygons_to_cut) for polygons_to_cut in top_level_polygons ] return g.PolygonSet(result, layer=layer, datatype=datatype)
def generate_jj(self): contact_pad_a_outer = 10.5 contact_pad_b_outer = 6 self.contact_pad_b_outer = contact_pad_b_outer self.contact_pad_a_outer = contact_pad_a_outer if self.hole_in_squid_pad==True: contact_pad_a_inner = 7.5 contact_pad_b_inner = 1 else: contact_pad_a_inner = 0 contact_pad_b_inner = 0 # Add contact pad1 points0 = [(self._x0 - contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_outer / 2, self._y0), (self._x0 + contact_pad_a_outer / 2, self._y0), (self._x0 + contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), (self._x0 + contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), (self._x0 + contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), ] x1 = self._x0 y1 = self._y0 - contact_pad_b_outer # parametr1=H_b H_a = 0.5#1 H_b = self._parametr1 L_a = 4#10.7 L_b = 0.4#0.75 h = 0.16#0.5 if self.add_JJ == False: points1 = [(x1 - H_a / 2, y1), (x1 + H_a / 2, y1), (x1 + H_a / 2, y1 - H_b), (x1 - H_a / 2, y1 - H_b) ] else: points1 = [(x1 - 3 * H_a, y1 - H_b / 3), (x1 + H_a, y1 - H_b / 3), (x1 + H_a, y1 - H_b / 3 - self.jj3_height), (x1 - 2 * H_a, y1 - H_b / 3 - self.jj3_height), (x1 - 2 * H_a, y1 - H_b), (x1 - 3 * H_a, y1 - H_b) ] points1_1 = [(x1 - H_a, y1), (x1 - H_a/4, y1), (x1 - H_a/4, y1 - H_b / 4), (x1 - H_a + self.jj3_width, y1 - H_b / 4), (x1 - H_a + self.jj3_width, y1 - H_b / 3 + h), (x1 - H_a, y1 - H_b / 3 + h) ] x2 = x1 - 3* H_a + L_a/4 y2 = y1 - H_b points2 = [(x2 - L_a / 2, y2), (x2 + L_a / 2, y2), (x2 + L_a / 2, y2 - L_b), (x2 - L_a / 2, y2 - L_b) ] H1_a = self.jj2_width#0.8 H1_b = 1#2 H2_a = self.jj1_width#0.8 H2_b = 1#2 x3 = x2 - L_a / 2 + H1_a / 2 y3 = y2 - L_b x4 = x2 + L_a / 2 - H1_a / 2 y4 = y2 - L_b points3 = [(x3 - H1_a / 2, y3), (x3 + H1_a / 2, y3), (x3 + H1_a / 2, y3 - H1_b), (x3 - H1_a / 2, y3 - H1_b) ] points4 = [(x4 - H2_a / 2, y4), (x4 + H2_a / 2, y4), (x4 + H2_a / 2, y4 - H2_b), (x4 - H2_a / 2, y4 - H2_b) ] x5 = x3 + H1_a / 2 y5 = y3 - H1_b x6 = x4 - H2_a / 2 y6 = y4 - H2_b # parametr2=pad1_a # parametr3=pad2_a pad1_a = self.jj2_width pad1_b = 1#3 pad2_a = self.jj1_width pad2_b = 1#3 points5_for_pad1 = [(x5, y5), (x5, y5 - pad1_b), (x5 - pad1_a, y5 - pad1_b), (x5 - pad1_a, y5) ] points6_for_pad2 = [(x6, y6), (x6 + pad2_a, y6), (x6 + pad2_a, y6 - pad2_b), (x6, y6 - pad2_b) ] contact_pad1_a_outer = L_a+2#6#13 contact_pad1_b_outer = 2.5#6.4 contact_pad1_a_inner = L_a+1 contact_pad1_b_inner = 2 x7 = x2#self._x0 y7 = self._y0 - contact_pad_b_outer - H_b - L_b - H1_b - pad1_b - h - contact_pad1_b_outer x7_ = x7 y7_ = y7 + (contact_pad1_b_outer - contact_pad1_b_inner) points7 = [(x7 - contact_pad1_a_outer / 2, y7 + contact_pad1_b_outer), (x7 - contact_pad1_a_outer / 2, y7), (x7 + contact_pad1_a_outer / 2, y7), (x7 + contact_pad1_a_outer / 2, y7 + contact_pad1_b_outer), (x7_ + contact_pad1_a_inner / 2, y7_ + contact_pad1_b_inner), (x7_ + contact_pad1_a_inner / 2, y7_), (x7_ - contact_pad1_a_inner / 2, y7_), (x7_ - contact_pad1_a_inner / 2, y7_ + contact_pad1_b_inner)] x8 = x7_ - contact_pad1_a_inner / 2 y8 = y7_ + contact_pad1_b_inner x9 = x7_ + contact_pad1_a_inner / 2 y9 = y7_ + contact_pad1_b_inner # parametr4=pad3_b # parametr5=pad4_b pad3_a = 1.5#2.5 pad3_b = self.jj2_height pad4_a = 1.5#2.5 pad4_b = self.jj1_height points8_for_pad3 = [(x8, y8), (x8 + pad3_a, y8), (x8 + pad3_a, y8 - pad3_b), (x8, y8 - pad3_b)] points9_for_pad4 = [(x9 - pad4_a, y9), (x9, y9), (x9, y9 - pad4_b), (x9 - pad4_a, y9 - pad4_b)] delta = contact_pad1_b_outer L1_a = 3.4 L1_b = 0.5#1 L2_a = 3.4 L2_b = 0.5#1 x10 = x7 - contact_pad1_a_outer / 2 y10 = y7 + L1_b x11 = x7 + contact_pad1_a_outer / 2 y11 = y7 + L2_b rec1_a_outer = 5 rec1_b_outer = 5 if self.hole_in_squid_pad == True: rec1_a_inner = 2 rec1_b_inner = 1 else: rec1_a_inner = 0 rec1_b_inner = 0 rec2_a_outer = rec1_a_outer rec2_b_outer = rec1_b_outer rec2_a_inner = rec1_a_inner rec2_b_inner = rec1_b_inner self.rect_size_a = rec1_a_outer self.rect_size_b = rec1_b_outer points10 = [(x10 - L1_a, y10), (x10, y10), (x10, y10 - L1_b), (x10 - L1_a, y10 - L1_b)] points11 = [(x11, y11), (x11 + L2_a, y11), (x11 + L2_a, y11 - L2_b), (x11, y11 - L2_b)] x12 = x10 - L1_a - (rec1_a_outer / 2) y12 = y10 - L1_b / 2 + (rec1_b_outer / 2) x13 = x11 + L2_a + (rec2_a_outer / 2) y13 = y11 - L2_b / 2 + (rec2_b_outer / 2) self.rect1 = (x12, y12) self.rect2 = (x13, y13) points12 = [(x12 - rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_outer / 2, y12), (x12 + rec1_a_outer / 2, y12), (x12 + rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), (x12 + rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), (x12 + rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), ] points13 = [(x13 - rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_outer / 2, y13), (x13 + rec2_a_outer / 2, y13), (x13 + rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), (x13 + rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), (x13 + rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), ] if self.add_JJ == False: squid = gdspy.PolygonSet([points0, points1, points2, points3, points4, points5_for_pad1, points6_for_pad2, points7, points8_for_pad3, points9_for_pad4, points10, points11, points12, points13]) else: squid = gdspy.PolygonSet([points0, points1, points1_1, points2, points3, points4, points5_for_pad1, points6_for_pad2, points7, points8_for_pad3, points9_for_pad4,points10, points11, points12, points13]) return squid
def XX(W, S, tl=37, bl=33): ''' Generate XX crossover W : Width of the metal track. S : Spacing between the metal tracks. tl : Upper metal layer number. The default of 37 is the top metal layer of the MOCMOS technology. This is convenient when using 'Electric' to view the resulting GDS. bl : Lower metal layer number. The default of 33 is the 2nd metal layer of the MOCMOS technology. This is convenient when using 'Electric' to view the resulting GDS. ''' ########################## # Some initial constants # ########################## tanz = np.tan(np.pi / 8) x = S * tanz ############################# # Points for 'XX' structure # ############################# A4x = 2 * W + 1.5 * S - W * np.sqrt(2) - S / np.sqrt(2) A4y = 2 * W + 1.5 * S B4x = x + S / 2 + S / np.sqrt(2) + W + W * np.sqrt(2) B4y = A4y C4x = B4x C4y = W + 1.5 * S D4x = 1.5 * S + W - S / np.sqrt(2) D4y = C4y E4x = W + S / 2 + S / np.sqrt(2) E4y = W + S / 2 F4x = B4x F4y = E4y G4x = B4x G4y = S / 2 H4x = S / np.sqrt(2) + W * np.sqrt(2) + S / 2 H4y = G4y ###################################################### # Collect points of 'XX' into list of list of tuples # ###################################################### ###################################################### # Top of the 'XX' structure # # The two upper right to lower left crossover _/- # ###################################################### xtop = [[], []] xtop[0].append((A4x, A4y)) xtop[0].append((B4x, B4y)) xtop[0].append((C4x, C4y)) xtop[0].append((D4x, D4y)) xtop[0].append((-1.0 * E4x, -1.0 * E4y)) xtop[0].append((-1.0 * F4x, -1.0 * F4y)) xtop[0].append((-1.0 * G4x, -1.0 * G4y)) xtop[0].append((-1.0 * H4x, -1.0 * H4y)) xtop[1].append((E4x, E4y)) xtop[1].append((F4x, F4y)) xtop[1].append((G4x, G4y)) xtop[1].append((H4x, H4y)) xtop[1].append((-1.0 * A4x, -1.0 * A4y)) xtop[1].append((-1.0 * B4x, -1.0 * B4y)) xtop[1].append((-1.0 * C4x, -1.0 * C4y)) xtop[1].append((-1.0 * D4x, -1.0 * D4y)) ##################################################### # Bottom of the 'XX' structure # # The two lower right to upper left crossover -\_ # ##################################################### xbot = [[], []] xbot[0].append((A4x, -1.0 * A4y)) xbot[0].append((B4x, -1.0 * B4y)) xbot[0].append((C4x, -1.0 * C4y)) xbot[0].append((D4x, -1.0 * D4y)) xbot[0].append((-1.0 * E4x, E4y)) xbot[0].append((-1.0 * F4x, F4y)) xbot[0].append((-1.0 * G4x, G4y)) xbot[0].append((-1.0 * H4x, H4y)) xbot[1].append((E4x, -1.0 * E4y)) xbot[1].append((F4x, -1.0 * F4y)) xbot[1].append((G4x, -1.0 * G4y)) xbot[1].append((H4x, -1.0 * H4y)) xbot[1].append((-1.0 * A4x, A4y)) xbot[1].append((-1.0 * B4x, B4y)) xbot[1].append((-1.0 * C4x, C4y)) xbot[1].append((-1.0 * D4x, D4y)) ################################### # Generate 'XX' crossover polygon # ################################### XX_Shapes = [] XX_Shapes.append(gdspy.PolygonSet(xtop, tl)) XX_Shapes.append(gdspy.PolygonSet(xbot, bl)) ###################################### # Create GDS cell for 'XX' crossover # ###################################### XX = gdspy.Cell('XX', exclude_from_current=False) ########################################### # Add the 'XX' polygons into the GDS cell # ########################################### for shape in XX_Shapes: XX.add(shape) ######################## # Add via to crossover # ######################## ####################################################################### # Use cell 'VIA_ARR' generated by function 'VIA' as the via structure # ####################################################################### #via locations via_4l = [ (B4x - W / 2, -0.5 * (S + W)), (-1 * (B4x - W / 2), 0.5 * (S + W)), (B4x - W / 2, -1.5 * (W + S)), (-1 * (B4x - W / 2), 1.5 * (W + S)) ] for v_loc in via_4l: VIA = gdspy.CellReference('VIA_ARR') VIA.translate(v_loc[0], v_loc[1]) XX.add(VIA) #End of adding via XX.flatten() #End of 'XX' crossover generation #################################################### # Generate a mirrored version of 'XX' called 'XXM' # #################################################### XX_ref = gdspy.CellReference('XX', (0, 0), x_reflection=True) XXM = gdspy.Cell('XXM', exclude_from_current=False) XXM.add(XX_ref).flatten()
def makePolySet(self, path): ### Converts a path object to a polyset object return gdspy.PolygonSet(self.path.polygons)
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
def gen_gds(poly_coords: List[np.ndarray], filepath: str, extra_structures: List[np.ndarray] = None, deembed: bool = True) -> None: """Generate GDS given a list of polygon coordinates. Output GDS has units of microns and precision in nanometers. Args: poly_coords: List of polygon coordinates. Elements of list are n x 2 numpy.ndarrays. Assumes coordinates in nanometers. filepath: Name of the filepath to output gds file. extra_structures: List of polygons to be added to the gds that are not part of the levelset function. deembed: Boolean to control if polygon deembeding will occur or not. """ poly_cell = gdspy.Cell("POLYGONS", exclude_from_current=True) test_points = [] gds_polygons = [] # Convert polygon coordinates from nanometers to microns since # output is in microns. poly_coords = [np.array(poly) / NM_PER_UM for poly in poly_coords] for polygon in poly_coords: test_points.append(tuple(polygon[0])) gds_polygons.append(gdspy.Polygon(polygon, 0)) if deembed: containment_mx = [] for polygon in gds_polygons: containment_mx.append(gdspy.inside(test_points, [polygon])) # Subtract by identity matrix since polygon_i trivially contains # polygon_i. containment_mx = np.array(containment_mx) - np.eye(len(gds_polygons)) # overlap_list[i] tells how many polygons are contained in polygon i. overlap_list = np.sum(containment_mx, axis=1) overlap_num = 0 while sum(overlap_list) != 0: overlap_num = overlap_num + 1 # We loop until there are no longer any more polygons of a specific # overlap number before going to the next overlap number. # # The reasoning for this is as we begin to delete polygons, # the overlap number changes and so polygons which were of # overlap_num > 1, may become polygons of overlap_num = 1. # # np.where(overlap_list==overlap_num)[0].size is how we see if # any polygons satisfy the current overlap number. target_polys = np.where(overlap_list == overlap_num)[0] while target_polys.size != 0: # We iterate through each polygon in our polygon list until no # polygon satisfies the current overlap number. for i in target_polys[::-1]: containment_list = np.nonzero(containment_mx[i, :])[0] # Concatenate all the contained polygons to subtract out. poly_list = sum( [gds_polygons[j].polygons for j in containment_list], []) # Note that we had to turn precision from the default 1e-3 # to 1e-6 to avoid errors in the NOT operation. gds_polygons[i] = gdspy.boolean( gds_polygons[i], gdspy.PolygonSet(poly_list), "not", layer=0, precision=1e-6) for j in containment_list: gds_polygons[j] = None test_points[j] = None for k in range(len(gds_polygons) - 1, -1, -1): if gds_polygons[k] is None: del gds_polygons[k] del test_points[k] containment_mx = [] for polygon in gds_polygons: containment_mx.append(gdspy.inside(test_points, [polygon])) containment_mx = np.array(containment_mx) - np.eye( len(gds_polygons)) overlap_list = np.sum(containment_mx, axis=1) target_polys = np.where(overlap_list == overlap_num)[0] for polygon in gds_polygons: poly_cell.add(polygon) if extra_structures is not None: for extra_polygon in extra_structures: poly_cell.add(gdspy.Polygon(extra_polygon, 0)) gdspy.write_gds(filepath, cells=[poly_cell], unit=1.0e-6, precision=1.0e-9)
def generate_multi_vt_gds(self) -> None: """ PDK GDS only contains SLVT cells. This patch will generate the other 3(LVT, RVT, SRAM) VT GDS files. """ import gdspy # TODO: why did module import get lost above for some users? self.logger.info("Generate GDS for Multi-VT cells") orig_gds = os.path.join( self.extracted_tarballs_dir, "ASAP7_PDKandLIB.tar/ASAP7_PDKandLIB_v1p5/asap7libs_24.tar.bz2/asap7libs_24/gds/asap7sc7p5t_24.gds" ) # load original_gds asap7_original_gds = gdspy.GdsLibrary().read_gds(infile=orig_gds, units='import') original_cells = asap7_original_gds.cell_dict # This is an extra cell in the original GDS that has no geometry inside del original_cells['m1_template'] # required libs multi_libs = { "R": { "lib": gdspy.GdsLibrary(), "mvt_layer": None, }, "L": { "lib": gdspy.GdsLibrary(), "mvt_layer": 98 }, "SL": { "lib": gdspy.GdsLibrary(), "mvt_layer": 97 }, "SRAM": { "lib": gdspy.GdsLibrary(), "mvt_layer": 110 }, } # create new libs for vt, multi_lib in multi_libs.items(): multi_lib['lib'].name = asap7_original_gds.name.replace('SL', vt) for cell in original_cells.values(): poly_dict = cell.get_polygons(by_spec=True) # extract polygon from layer 100(the boundary for cell) boundary_polygon = poly_dict[(100, 0)] for vt, multi_lib in multi_libs.items(): mvt_layer = multi_lib['mvt_layer'] if mvt_layer: # copy boundary_polygon to mvt_layer to mark the this cell is a mvt cell. mvt_polygon = gdspy.PolygonSet(boundary_polygon, multi_lib['mvt_layer'], 0) mvt_cell = cell.copy(name=cell.name.replace('SL', vt), exclude_from_current=True, deep_copy=True).add(mvt_polygon) else: # RVT, just copy the cell mvt_cell = cell.copy(name=cell.name.replace('SL', vt), exclude_from_current=True, deep_copy=True) # add mvt_cell to corresponding multi_lib multi_lib['lib'].add(mvt_cell) for vt, multi_lib in multi_libs.items(): # write multi_lib multi_lib['lib'].write_gds( os.path.splitext(orig_gds)[0] + '_' + vt + '.gds')
def generate_3jj(self): contact_pad_a_outer = 10.5 contact_pad_b_outer = 3 self.contact_pad_b_outer = contact_pad_b_outer self.contact_pad_a_outer = contact_pad_a_outer contact_pad_a_inner = 7.5 contact_pad_b_inner = 1 self._x0 = self.center[0] self._y0 = self.center[ 1] - self.length - self.s / 2 + self.contact_pad_b_outer self._parametr1 = 10 #Hb self._parametr2 = self.jj['side_r_thick'] self._parametr3 = self.jj['up_l_thick'] self._parametr4 = self.jj['side_l_thick'] self._parametr5 = self.jj['side_r_thick'] # Add contact pad1 points0 = [ (self._x0 - contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_outer / 2, self._y0), (self._x0 + contact_pad_a_outer / 2, self._y0), (self._x0 + contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), (self._x0 + contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), (self._x0 + contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), ] x1 = self._x0 y1 = self._y0 - contact_pad_b_outer # parametr1=H_b H_a = 0.5 # 1 H_b = self._parametr1 L_a = 6 # 10.7 L_b = 0.75 h = 0.16 # 0.5 points1 = [(x1 - 3 * H_a, y1 - H_b / 2), (x1 + H_a, y1 - H_b / 2), (x1 + H_a, y1 - H_b / 2 - self._parametr4), (x1 - 2 * H_a, y1 - H_b / 2 - self._parametr4), (x1 - 2 * H_a, y1 - H_b), (x1 - 3 * H_a, y1 - H_b)] points1_1 = [(x1 - H_a, y1), (x1 - H_a / 4, y1), (x1 - H_a / 4, y1 - H_b / 3), (x1 - H_a + self._parametr3, y1 - H_b / 3), (x1 - H_a + self._parametr3, y1 - H_b / 2 + h), (x1 - H_a, y1 - H_b / 2 + h)] x2 = x1 y2 = y1 - H_b points2 = [(x2 - L_a / 2, y2), (x2 + L_a / 2, y2), (x2 + L_a / 2, y2 - L_b), (x2 - L_a / 2, y2 - L_b)] H1_a = 0.8 H1_b = 2 H2_a = 0.8 H2_b = 2 x3 = x2 - L_a / 2 + H1_a / 2 y3 = y2 - L_b x4 = x2 + L_a / 2 - H1_a / 2 y4 = y2 - L_b points3 = [(x3 - H1_a / 2, y3), (x3 + H1_a / 2, y3), (x3 + H1_a / 2, y3 - 2 * H1_b), (x3 - H1_a / 2, y3 - 2 * H1_b)] points4 = [(x4 - H2_a / 2, y4), (x4 + H2_a / 2, y4), (x4 + H2_a / 2, y4 - H2_b), (x4 - H2_a / 2, y4 - H2_b)] x5 = x3 + H1_a / 2 y5 = y3 - H1_b x6 = x4 - H2_a / 2 y6 = y4 - H2_b # parametr2=pad1_a # parametr3=pad2_a pad1_a = self._parametr3 pad1_b = 3 pad2_a = self._parametr2 pad2_b = 3 points5_for_pad1 = [(x5, y5), (x5, y5 - pad1_b), (x5 - pad1_a, y5 - pad1_b), (x5 - pad1_a, y5)] points6_for_pad2 = [(x6, y6), (x6 + pad2_a, y6), (x6 + pad2_a, y6 - pad2_b), (x6, y6 - pad2_b)] contact_pad1_a_outer = 13 contact_pad1_b_outer = 6.4 contact_pad1_a_inner = 12 contact_pad1_b_inner = 5.8 x7 = self._x0 y7 = self._y0 - contact_pad_b_outer - H_b - L_b - H1_b - pad1_b - h - contact_pad1_b_outer x7_ = x7 y7_ = y7 + (contact_pad1_b_outer - contact_pad1_b_inner) points7 = [ (x7 - contact_pad1_a_outer / 2, y7 + contact_pad1_b_outer), (x7 - contact_pad1_a_outer / 2, y7), (x7 + contact_pad1_a_outer / 2, y7), (x7 + contact_pad1_a_outer / 2, y7 + contact_pad1_b_outer), (x7_ + contact_pad1_a_inner / 2, y7_ + contact_pad1_b_inner), (x7_ + contact_pad1_a_inner / 2, y7_), (x7_ - contact_pad1_a_inner / 2, y7_), (x7_ - contact_pad1_a_inner / 2, y7_ + contact_pad1_b_inner) ] x8 = x7_ - contact_pad1_a_inner / 2 y8 = y7_ + contact_pad1_b_inner x9 = x7_ + contact_pad1_a_inner / 2 y9 = y7_ + contact_pad1_b_inner # parametr4=pad3_b # parametr5=pad4_b pad3_a = 4.5 # 2.5 pad3_b = self._parametr4 pad4_a = 4.5 # 2.5 pad4_b = self._parametr5 points8_for_pad3 = [(x8, y8), (x8 + pad3_a, y8), (x8 + pad3_a, y8 - pad3_b), (x8, y8 - pad3_b)] points9_for_pad4 = [(x9 - pad4_a, y9), (x9, y9), (x9, y9 - pad4_b), (x9 - pad4_a, y9 - pad4_b)] delta = 6 x10 = x7 - contact_pad1_a_outer / 2 y10 = y7 + delta x11 = x7 + contact_pad1_a_outer / 2 y11 = y7 + delta L1_a = 2.1 L1_b = 1 L2_a = 2.1 L2_b = 1 rec1_a_outer = 4.8 rec1_b_outer = 2.8 rec1_a_inner = 2 rec1_b_inner = 1 rec2_a_outer = rec1_a_outer rec2_b_outer = rec1_b_outer rec2_a_inner = rec1_a_inner rec2_b_inner = rec1_b_inner self.rect_size_a = rec1_a_outer self.rect_size_b = rec1_b_outer points10 = [(x10 - L1_a, y10), (x10, y10), (x10, y10 - L1_b), (x10 - L1_a, y10 - L1_b)] points11 = [(x11, y11), (x11 + L2_a, y11), (x11 + L2_a, y11 - L2_b), (x11, y11 - L2_b)] x12 = x10 - L1_a - (rec1_a_outer / 2) y12 = y10 - L1_b / 2 + (rec1_b_outer / 2) x13 = x11 + L2_a + (rec2_a_outer / 2) y13 = y11 - L2_b / 2 + (rec2_b_outer / 2) self.rect1 = (x12, y12) self.rect2 = (x13, y13) points12 = [ (x12 - rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_outer / 2, y12), (x12 + rec1_a_outer / 2, y12), (x12 + rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), (x12 + rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), (x12 + rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), ] points13 = [ (x13 - rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_outer / 2, y13), (x13 + rec2_a_outer / 2, y13), (x13 + rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), (x13 + rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), (x13 + rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), ] squid = gdspy.PolygonSet([ points0, points1, points1_1, points2, points3, points4, points5_for_pad1, points6_for_pad2, points7, points8_for_pad3, points9_for_pad4, points10, points11, points12, points13 ]) jj = gdspy.boolean(squid, squid, "or", layer=self.layer_configuration.jj_layer) if self.jjpos == 'up': jj = jj.rotate(np.pi, self.center) elif self.jjpos == 'left': jj = jj.rotate(-np.pi / 2, self.center) elif self.jjpos == 'right': jj = jj.rotate(np.pi / 2, self.center) return jj
def test_translate(): ps = gdspy.PolygonSet([[(0, 0), (1, 0), (1, 2), (0, 2)]]) ps.translate(-1, -2) tgt = gdspy.PolygonSet([[(-1, -2), (0, -2), (0, 0), (-1, 0)]]) assertsame(gdspy.Cell("test").add(ps), gdspy.Cell("TGT").add(tgt))
###################################################################### import gdspy import numpy lib = gdspy.GdsLibrary("TESTLIB", unit=1, precision=1e-7) ### PolygonSet cell = lib.new_cell("PolygonSet") p = gdspy.PolygonSet( [ [(10, 0), (11, 0), (10, 1)], [(11, 0), (10, 1), (11, 1)], [(11, 1), (12, 1), (11, 2)], ], 1, 2, ) cell.add(p) cell = lib.new_cell("PolygonSet_fillet") orig = gdspy.PolygonSet([ [ (0, 0), (-1, 0), (0, -1), (0.5, -0.5), (1, 0),
squareOffset = 10 + 5 + 35 / 2 bottomSquare = gdspy.Rectangle((-35 / 2, -35 / 2), (35 / 2, 35 / 2), layer=2) bottomSquareTR = gdspy.copy(bottomSquare) bottomSquareTR.translate(squareOffset, squareOffset) bottomSquareTL = gdspy.copy(bottomSquare) bottomSquareTL.translate(-squareOffset, squareOffset) bottomSquareBR = gdspy.copy(bottomSquare) bottomSquareBR.translate(squareOffset, -squareOffset) bottomSquareBL = gdspy.copy(bottomSquare) bottomSquareBL.translate(-squareOffset, -squareOffset) bottomMark = gdspy.Cell('Bottom Mark') bottomMark.add(bottomSquareTR) bottomMark.add(bottomSquareTL) bottomMark.add(bottomSquareBR) bottomMark.add(bottomSquareBL) bottomMarkRight = gdspy.PolygonSet(bottomMark.get_polygons(), layer=2) bottomMarkLeft = gdspy.copy(bottomMarkRight) bottomMarkRight.translate(markOffset, 0) bottomMarkLeft.translate(-markOffset, 0) cell.add(bottomMarkLeft) cell.add(bottomMarkRight) # SAVE THE FILE lib.write_gds('aml_marks.gds') gdspy.LayoutViewer(lib)
def union(parts_list): union = gdspy.PolygonSet([]) for p in parts_list: union = gdspy.boolean(union, p, 'or') return union
bool_path.segment(30, '+x') bool_path.turn(10, 'r', number_of_points=64) bool_path.segment(30, '-y') bool_path.turn(10, 'r', number_of_points=64) bool_path.segment(30, '-x') bool_path.turn(10, 'r', number_of_points=64) ## Ring inside the square path. ring = gdspy.Round((25, 25), 25 + width * 0.5, inner_radius=25 - width * 0.5, number_of_points=256) ## We create a PolygonSet that contains both our path segments and ## ring, and then append it to our list of operands. primitives.append(gdspy.PolygonSet(bool_path.polygons + ring.polygons)) ## The list of operands contains 2 polygon sets. We will subtract the ## 1st (narrower) from the 2nd (wider). For that we need to define a ## function that receives 2 integers (each representing an operand) and ## returns the operation we want executed. Here we use a lambda ## expression to do so. subtraction = lambda p1, p2: p2 and not p1 ## We perform the operation, put the resulting polygons in layer 1, and ## add to our boolean cell. bool_cell.add(gdspy.boolean(primitives, subtraction, max_points=199, layer=1)) ## ------------------------------------------------------------------ ## ## POLYGON OFFSET ## ------------------------------------------------------------------ ##
params = qd.Params(yaml.load(f, yaml.CSafeLoader)) ## These should probably be put in parameters.yaml n = params['evaporation.junctions.number'] overlap = params['evaporation.junctions.overlap'] # lx, ly, junction size wire = params['evaporation.junctions.wire'] # lx, ly, connecting piece between junctions undercut = params['evaporation.junctions.undercut'] # undercut for wires undercut_after_JJ = params['evaporation.junctions.undercut_after_JJ'] # undercut after junction dose_layers = [1, 2] evap_layers = params['evaporation.layers'] junction_array = JunctionArray(n, overlap, wire, undercut) chip.add_component(junction_array, cid='JJArray', layers=dose_layers) ## Simulate Evaporation polys = junction_array.get_polygons(by_spec=True) highdose = gdspy.PolygonSet(polys[(dose_layers[0], 0)]) lowdose = gdspy.PolygonSet(polys[(dose_layers[1], 0)]) evaporated = qj.simulate_evaporation( lowdose, highdose, **params['evaporation'] ) for i, (layer, evap) in enumerate(zip(evap_layers, evaporated)): chip.add_component(evap, f'evap_{i}', layers=layer) cells = chip.render(name='jj_array', draw_border=False) lib.write_gds('jj_array_test.gds', cells=cells)
cpwfeed.straight(250, widthEnd = 10, gapEnd = 5) cpwfeed.straight(250) cpwfeed.bend(150, 'l') cpwfeed.bend(150, 'r') cpwfeed.straight(2500 - 1000 - 3*150) cpwfeed.bend(150, 'r') cpwfeed.straight(8200) cpwfeed.bend(150, 'r') cpwfeed.straight(2500 - 1000 - 3*150) cpwfeed.bend(150, 'r') cpwfeed.bend(150, 'l') cpwfeed.straight(250) cpwfeed.straight(250, widthEnd = 300, gapEnd = 150) cpwfeed.straight(250) cpwfeed.openGap(150) gdslib.addPolyToCell(gdspy.PolygonSet(cpwfeed.path.polygons), device) # BOTTOM RESONATOR ARRAY f = linspace(6E9,6.1E9,6) # Fundamental frequency l4 = c/sqrt(ereff)/4./f*1E6 # length for lambda/4 resonator print(l4) for i in range(0,5): totalLength = l4[i] openDis = 10 capDist = 10*(1+i) cpwSrtExtend = 200 bendRad = 100 meanderLen = totalLength - openDis - capDist - cpwSrtExtend - pi*bendRad exec("cpw" + str(i) + " = gdslib.CPWPath(10,5,layer = 6)") exec("cpw" + str(i) + ".start([1900+ 625 + 1250*" + str(i) + ",2500 - 25],'+x')")
def XI(W, S, tl=37, bl=33, ext=None): ''' Generate XI crossover W : Width of the metal track. S : Spacing between the metal tracks. tl : Upper metal layer number. The default of 37 is the top metal layer of the MOCMOS technology. This is convenient when using 'Electric' to view the resulting GDS. bl : Lower metal layer number. The default of 33 is the 2nd metal layer of the MOCMOS technology. This is convenient when using 'Electric' to view the resulting GDS. ext : GDS cell name of the width to use. ''' ########################## # Some initial constants # ########################## Stanz = S * np.tan(np.pi / 8) Wtanz = W * np.tan(np.pi / 8) SdSqr2 = S / np.sqrt(2) WdSqr2 = W / np.sqrt(2) SpWd2 = S + W / 2 ############################################################################ # If 'ext' = None, then the natural width of the crossover is used. # # When 'ext' = 'XX' for example, the 'XI' width is extended to 'XX' width. # ############################################################################ if ext == None: edge_x = SpWd2 + WdSqr2 + W + Stanz else: CO = gdspy.CellReference(ext) edge_x = CO.get_bounding_box()[1][0] ############################# # Points for 'XI' structure # ############################# A3x = SpWd2 + WdSqr2 - Wtanz A3y = SpWd2 + W B3x = edge_x B3y = A3y C3x = B3x C3y = SpWd2 D3x = SpWd2 + WdSqr2 D3y = C3y E3x = SdSqr2 + W / 2 + Wtanz E3y = W / 2 F3x = B3x F3y = W / 2 G3x = B3x G3y = -W / 2 H3x = SdSqr2 + W / 2 H3y = -W / 2 I3x = H3x - Stanz I3y = -SpWd2 L3x = I3x - Wtanz L3y = -SpWd2 - W J3x = B3x J3y = I3y K3x = B3x K3y = L3y ###################################################### # Collect points of 'XI' into list of list of tuples # ###################################################### ###################################################### # Top of the 'XI' structure # # The two lower right to upper left crossover -\_ # ###################################################### xtop = [[], []] xtop[0].append((E3x, E3y)) xtop[0].append((F3x, F3y)) xtop[0].append((G3x, G3y)) xtop[0].append((H3x, H3y)) xtop[0].append((-1.0 * I3x, -1.0 * I3y)) xtop[0].append((-1.0 * J3x, -1.0 * J3y)) xtop[0].append((-1.0 * K3x, -1.0 * K3y)) xtop[0].append((-1.0 * L3x, -1.0 * L3y)) xtop[1].append((I3x, I3y)) xtop[1].append((J3x, J3y)) xtop[1].append((K3x, K3y)) xtop[1].append((L3x, L3y)) xtop[1].append((-1.0 * E3x, -1.0 * E3y)) xtop[1].append((-1.0 * F3x, -1.0 * F3y)) xtop[1].append((-1.0 * G3x, -1.0 * G3y)) xtop[1].append((-1.0 * H3x, -1.0 * H3y)) ############################################# # Bottom of the 'XI' structure # # Upper right to lower left crossover _/- # ############################################# xbot = [] xbot.append((A3x, A3y)) xbot.append((B3x, B3y)) xbot.append((C3x, C3y)) xbot.append((D3x, D3y)) xbot.append((-1.0 * A3x, -1.0 * A3y)) xbot.append((-1.0 * B3x, -1.0 * B3y)) xbot.append((-1.0 * C3x, -1.0 * C3y)) xbot.append((-1.0 * D3x, -1.0 * D3y)) ################################### # Generate 'XI' crossover polygon # ################################### XI_Shapes = [] XI_Shapes.append(gdspy.PolygonSet(xtop, tl)) XI_Shapes.append(gdspy.Polygon(xbot, bl)) ###################################### # Create GDS cell for 'XI' crossover # ###################################### XI = gdspy.Cell('XI', exclude_from_current=False) ########################################### # Add the 'XI' polygons into the GDS cell # ########################################### for shape in XI_Shapes: XI.add(shape) ######################## # Add via to crossover # ######################## ####################################################################### # Use cell 'VIA_ARR' generated by function 'VIA' as the via structure # ####################################################################### #via locations via_3l = [(edge_x - W / 2, (S + W)), (-(edge_x - W / 2), -(S + W))] for v_loc in via_3l: VIA = gdspy.CellReference('VIA_ARR') VIA.translate(v_loc[0], v_loc[1]) XI.add(VIA) #End of adding via XI.flatten() #End of 'XI' crossover generation #################################################### # Generate a mirrored version of 'XI' called 'XIM' # #################################################### XI_ref = gdspy.CellReference('XI', (0, 0), x_reflection=True) XIM = gdspy.Cell('XIM', exclude_from_current=False) XIM.add(XI_ref).flatten()
"xor", precision=0.1 * tolerance, max_points=0, ).polygons[0] break elif gdspy.inside(polys[i][:1], [poly], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean( [p], [poly], "xor", precision=0.1 * tolerance, max_points=0, ).polygons[0] i -= 1 xmax = max(xmax, poly[:, 0].max()) polys.append(poly) return polys if __name__ == "__main__": fp = FontProperties(family="serif", style="italic") text = gdspy.PolygonSet(render_text("Text rendering", 10, font_prop=fp), layer=1) lib = gdspy.GdsLibrary() cell = lib.new_cell("TXT") cell.add(text) lib.write_gds("fonts.gds") gdspy.LayoutViewer(lib)
def generate_jj(self): contact_pad_a_outer = 10.5 contact_pad_b_outer = 3 self.contact_pad_b_outer = contact_pad_b_outer self.contact_pad_a_outer = contact_pad_a_outer contact_pad_a_inner = 7.5 contact_pad_b_inner = 1 # Add contact pad1 points0 = [(self._x0 - contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_outer / 2, self._y0), (self._x0 + contact_pad_a_outer / 2, self._y0), (self._x0 + contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_outer / 2, self._y0 - contact_pad_b_outer), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), (self._x0 + contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), (self._x0 + contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2), (self._x0 - contact_pad_a_inner / 2, self._y0 - (contact_pad_b_outer - contact_pad_b_inner) / 2 - contact_pad_b_inner), ] x1 = self._x0 y1 = self._y0 - contact_pad_b_outer # parametr1=H_b H_a = 1 H_b = self._parametr1 L_a = 10.7 L_b = 0.75 points1 = [(x1 - H_a / 2, y1), (x1 + H_a / 2, y1), (x1 + H_a / 2, y1 - H_b), (x1 - H_a / 2, y1 - H_b) ] x2 = x1 y2 = y1 - H_b points2 = [(x2 - L_a / 2, y2), (x2 + L_a / 2, y2), (x2 + L_a / 2, y2 - L_b), (x2 - L_a / 2, y2 - L_b) ] H1_a = 0.8 H1_b = 2 H2_a = 0.8 H2_b = 2 x3 = x2 - L_a / 2 + H1_a / 2 y3 = y2 - L_b x4 = x2 + L_a / 2 - H1_a / 2 y4 = y2 - L_b points3 = [(x3 - H1_a / 2, y3), (x3 + H1_a / 2, y3), (x3 + H1_a / 2, y3 - H1_b), (x3 - H1_a / 2, y3 - H1_b) ] points4 = [(x4 - H2_a / 2, y4), (x4 + H2_a / 2, y4), (x4 + H2_a / 2, y4 - H2_b), (x4 - H2_a / 2, y4 - H2_b) ] x5 = x3 + H1_a / 2 y5 = y3 - H1_b x6 = x4 - H2_a / 2 y6 = y4 - H2_b # parametr2=pad1_a # parametr3=pad2_a pad1_a = self._parametr2 pad1_b = 3 pad2_a = self._parametr2 pad2_b = 3 points5_for_pad1 = [(x5, y5), (x5, y5 - pad1_b), (x5 - pad1_a, y5 - pad1_b), (x5 - pad1_a, y5) ] points6_for_pad2 = [(x6, y6), (x6 + pad2_a, y6), (x6 + pad2_a, y6 - pad2_b), (x6, y6 - pad2_b) ] contact_pad1_a_outer = 13 contact_pad1_b_outer = 6.4 contact_pad1_a_inner = 12 contact_pad1_b_inner = 5.8 h = 0.5 x7 = self._x0 y7 = self._y0 - contact_pad_b_outer - H_b - L_b - H1_b - pad1_b - h - contact_pad1_b_outer x7_ = x7 y7_ = y7 + (contact_pad1_b_outer - contact_pad1_b_inner) points7 = [(x7 - contact_pad1_a_outer / 2, y7 + contact_pad1_b_outer), (x7 - contact_pad1_a_outer / 2, y7), (x7 + contact_pad1_a_outer / 2, y7), (x7 + contact_pad1_a_outer / 2, y7 + contact_pad1_b_outer), (x7_ + contact_pad1_a_inner / 2, y7_ + contact_pad1_b_inner), (x7_ + contact_pad1_a_inner / 2, y7_), (x7_ - contact_pad1_a_inner / 2, y7_), (x7_ - contact_pad1_a_inner / 2, y7_ + contact_pad1_b_inner)] x8 = x7_ - contact_pad1_a_inner / 2 y8 = y7_ + contact_pad1_b_inner x9 = x7_ + contact_pad1_a_inner / 2 y9 = y7_ + contact_pad1_b_inner # parametr4=pad3_b # parametr5=pad4_b pad3_a = 2.5 pad3_b = self._parametr4 pad4_a = 2.5 pad4_b = self._parametr5 points8_for_pad3 = [(x8, y8), (x8 + pad3_a, y8), (x8 + pad3_a, y8 - pad3_b), (x8, y8 - pad3_b)] points9_for_pad4 = [(x9 - pad4_a, y9), (x9, y9), (x9, y9 - pad4_b), (x9 - pad4_a, y9 - pad4_b)] delta = 6 x10 = x7 - contact_pad1_a_outer / 2 y10 = y7 + delta x11 = x7 + contact_pad1_a_outer / 2 y11 = y7 + delta L1_a = 2.1 L1_b = 1 L2_a = 2.1 L2_b = 1 rec1_a_outer = 4.8 rec1_b_outer = 2.8 rec1_a_inner = 2 rec1_b_inner = 1 rec2_a_outer = rec1_a_outer rec2_b_outer = rec1_b_outer rec2_a_inner = rec1_a_inner rec2_b_inner = rec1_b_inner self.rect_size_a = rec1_a_outer self.rect_size_b = rec1_b_outer points10 = [(x10 - L1_a, y10), (x10, y10), (x10, y10 - L1_b), (x10 - L1_a, y10 - L1_b)] points11 = [(x11, y11), (x11 + L2_a, y11), (x11 + L2_a, y11 - L2_b), (x11, y11 - L2_b)] x12 = x10 - L1_a - (rec1_a_outer / 2) y12 = y10 - L1_b / 2 + (rec1_b_outer / 2) x13 = x11 + L2_a + (rec2_a_outer / 2) y13 = y11 - L2_b / 2 + (rec2_b_outer / 2) self.rect1 = (x12, y12) self.rect2 = (x13, y13) points12 = [(x12 - rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_outer / 2, y12), (x12 + rec1_a_outer / 2, y12), (x12 + rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_outer / 2, y12 - rec1_b_outer), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), (x12 + rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), (x12 + rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2), (x12 - rec1_a_inner / 2, y12 - (rec1_b_outer - rec1_b_inner) / 2 - rec1_b_inner), ] points13 = [(x13 - rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_outer / 2, y13), (x13 + rec2_a_outer / 2, y13), (x13 + rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_outer / 2, y13 - rec2_b_outer), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), (x13 + rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), (x13 + rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2), (x13 - rec2_a_inner / 2, y13 - (rec2_b_outer - rec2_b_inner) / 2 - rec2_b_inner), ] squid = gdspy.PolygonSet([points0, points1, points2, points3, points4, points5_for_pad1, points6_for_pad2, points7, points8_for_pad3, points9_for_pad4, points10, points11, points12, points13]) return squid
import numpy as np import gdspy from gdsCAD import * from matplotlib.font_manager import FontProperties from matplotlib.textpath import TextPath import fonts from fonts import * a = core.Boundary( [[(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)], [(0.0, 0.0), (0.5, 0.0), (0.5, 0.5), (0.0, 0.5)]], layer=1) b = gdspy.PolygonSet( [[(0.0, 0.0), (2.0, 0.0), (2.0, 2.0), (0.0, 2.0)], [(0.0, 0.0), (3.0, 0.0), (3.0, 3.0), (0.0, 3.0)]], layer=1) c = gdspy.PolygonSet(a.points, layer=1) d = core.Boundary(b.polygons, layer=1) def cadply(ply, ly): return gdspy.Polygon([list(i) for i in ply], layer=ly) #end def pypol2bdy(plst, ly): return core.Boundary(plst.polygons, layer=ly) #end
def ply_area(self): ply = gdspy.PolygonSet(self.shape.points) return ply.area()
def test_mirror(): ps = gdspy.PolygonSet([[(0, 0), (1, 0), (1, 2), (0, 2)]]) ps.mirror((-1, 1), (1, -1)) tgt = gdspy.PolygonSet([[(0, 0), (-2, 0), (-2, -1), (0, -1)]]) assertsame(gdspy.Cell("test").add(ps), gdspy.Cell("TGT").add(tgt))
def test_fillet(target): cell = gdspy.Cell("test") orig = gdspy.PolygonSet( [ [ (0, 0), (-1, 0), (0, -1), (0.5, -0.5), (1, 0), (1, 1), (4, -1), (1, 3), (1, 2), (0, 1), ], [(2, -1), (3, -1), (2.5, -2)], ] ) orig.datatypes = [0, 1] p = gdspy.copy(orig, 0, 5) p.layers = [1, 1] p.fillet(0.3, max_points=0) cell.add(p) p = gdspy.copy(orig, 5, 5) p.layers = [2, 2] p.fillet( [0.3, 0.2, 0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.4, 0.1, 0.2, 0], max_points=0 ) cell.add(p) p = gdspy.copy(orig, 5, 0) p.layers = [3, 3] p.fillet( [[0.1, 0.1, 0.4, 0, 0.4, 0.1, 0.1, 0.4, 0.4, 0.1], [0.2, 0.2, 0.5]], max_points=0, ) cell.add(p) p = gdspy.PolygonSet( [ [ (0, 0), (0, 0), (-1, 0), (0, -1), (0.5, -0.5), (1, 0), (1, 0), (1, 1), (4, -1), (1, 3), (1, 2), (0, 1), ], [(2, -1), (3, -1), (2.5, -2), (2, -1)], ], layer=4, ) p.datatypes = [0, 1] p.fillet([0.8, [10.0, 10.0, 20.0, 20.0]], max_points=199, precision=1e-6) cell.add(p) assertsame(cell, target["PolygonSet_fillet"], tolerance=1e-3)