def generate_JJ(self, connection_part): JJ_part_length = 39 # TODO: maybe we need to find a way to remove this value from here, but for now it's fine max_x = max(self.connection1[0], self.connection2[0]) min_x = min(self.connection1[0], self.connection2[0]) coeff_x = 1 if max_x > connection_part[0] + self.jj_params[ 'indent'] * np.cos(self.orientation + np.pi / 2) > min_x else -1 self.jj_params['x'] = connection_part[0] + coeff_x * self.jj_params[ 'indent'] * np.cos(self.orientation + np.pi / 2) max_y = max(self.connection1[1], self.connection2[1]) min_y = min(self.connection1[1], self.connection2[1]) if max_y != min_y: coeff_y = 1 if max_y > connection_part[1] + ( (self.core + self.ground) / 2 + self.jj_params['indent'] ) * np.sin(self.orientation + np.pi / 2) > min_y else -1 self.jj_params['y'] = connection_part[1] + coeff_y * ( -coeff_y * JJ_part_length / 2 + self.jj_params['indent'] ) * np.sin(self.orientation + np.pi / 2) if max_y == min_y: self.jj_params['y'] = connection_part[1] + JJ_part_length / 2 JJ = JJ4q.JJ_1( self.jj_params['x'], self.jj_params['y'], self.jj_params['a1'], self.jj_params['a2'], ) result = JJ.generate_jj() result = gdspy.boolean(result, result, 'or', layer=self.layer_configuration.jj_layer) angle = self.jj_params['angle'] result.rotate(angle, (self.jj_params['x'], self.jj_params['y'])) indent = 1 # overlap between the JJ's layer and the ground layer rect1 = gdspy.Rectangle( (self.jj_params['x'] - JJ.contact_pad_a / 2, self.jj_params['y'] + indent), (self.jj_params['x'] + JJ.contact_pad_a / 2, self.jj_params['y'] - JJ.contact_pad_b + indent), layer=6) rect2 = gdspy.Rectangle( (JJ.x_end - JJ.contact_pad_a / 2, JJ.y_end - 1), (JJ.x_end + JJ.contact_pad_a / 2, JJ.y_end - JJ.contact_pad_b - indent), layer=6) if self.connection1[0] != self.connection2[ 0]: # for horizontal based couplers poly1 = gdspy.Polygon([ (self.jj_params['x'] - JJ.contact_pad_a / 2, self.jj_params['y'] + indent), (self.jj_params['x'] - JJ.contact_pad_a / 2, self.jj_params['y'] + indent - JJ.contact_pad_b), (self.jj_params['x'] - JJ.contact_pad_a - indent, self.connection1[1] - self.core / 2), (self.jj_params['x'] - JJ.contact_pad_a - indent, self.connection1[1] + self.core / 2) ]) poly2 = gdspy.Polygon([(JJ.x_end + JJ.contact_pad_a / 2, JJ.y_end - indent - JJ.contact_pad_b), (JJ.x_end + JJ.contact_pad_a / 2, JJ.y_end - indent), (JJ.x_end + JJ.contact_pad_a + indent, self.connection1[1] + self.core / 2), (JJ.x_end + JJ.contact_pad_a + indent, self.connection1[1] - self.core / 2)]) else: poly1, poly2 = [], [] rect = gdspy.boolean(rect1, [rect2, poly1, poly2], 'or') rect.rotate(angle, (self.jj_params['x'], self.jj_params['y'])) to_remove = gdspy.Polygon( JJ.points_to_remove, layer=self.layer_configuration.layer_to_remove) to_remove.rotate(angle, (self.jj_params['x'], self.jj_params['y'])) return result, rect, to_remove
def generate_jj(self): #parametrs contact_pad1_a = 16 contact_pad1_b = 10 self.contact_pad_a = contact_pad1_a self.contact_pad_b = contact_pad1_b arm1_a = 1 arm1_b = 5 delta1 = arm1_a * 3 hand1_a = 2 hand1_b = self._parametr1 h = 2 contact_pad2_a = 16 contact_pad2_b = 10 arm2_a = 1 arm2_b = 5 hand2_a = self._parametr2 hand2_b = 7 x1 = self._x0 - delta1 y1 = self._y0 - contact_pad1_b x2 = x1 + arm1_a / 2 y2 = y1 - arm1_b x3 = self._x0 y3 = self._y0 - contact_pad1_b - arm1_b - arm2_b - hand2_b - h x4 = x3 y4 = y3 + arm2_b # contact pad 1 points0 = [(self._x0 - contact_pad1_a / 2, self._y0), (self._x0 + contact_pad1_a / 2, self._y0), (self._x0 + contact_pad1_a / 2, self._y0 - contact_pad1_b), (self._x0 - contact_pad1_a / 2, self._y0 - contact_pad1_b)] points1 = [(x1 - arm1_a / 2, y1), (x1 + arm1_a / 2, y1), (x1 + arm1_a / 2, y1 - arm1_b), (x1 - arm1_a / 2, y1 - arm1_b)] points2 = [(x2, y2), (x2, y2 + hand1_b), (x2 + hand1_a, y2 + hand1_b), (x2 + hand1_a, y2)] # contact pad 2 # print(x3, y3) points3 = [(x3 - contact_pad1_a / 2, y3), (x3 + contact_pad1_a / 2, y3), (x3 + contact_pad1_a / 2, y3 - contact_pad2_b), (x3 - contact_pad1_a / 2, y3 - contact_pad2_b)] points4 = [(x3 - arm2_a / 2, y3), (x3 - arm2_a / 2, y3 + arm2_b), (x3 + arm2_a / 2, y3 + arm2_b), (x3 + arm2_a / 2, y3)] points5 = [(x4 - hand2_a / 2, y4), (x4 - hand2_a / 2, y4 + hand2_b), (x4 + hand2_a / 2, y4 + hand2_b), (x4 + hand2_a / 2, y4)] p0 = gdspy.Polygon(points0) p1 = gdspy.Polygon(points1) p2 = gdspy.Polygon(points2) p3 = gdspy.Polygon(points3) p4 = gdspy.Polygon(points4) p5 = gdspy.Polygon(points5) self.x_end = x3 self.y_end = y3 indent = 1 self.points_to_remove = [(self._x0 - contact_pad1_a - indent, self._y0 - contact_pad1_b / 2 - indent), (self._x0 + contact_pad1_a + indent, self._y0 - contact_pad1_b / 2 - indent), (x3 + contact_pad1_a + indent, y3 - indent), (x3 - contact_pad1_a - indent, y3 - indent)] return [p0, p1, p2, p3, p4, p4, p5]
# Antidot array [layer 1] layout = LayoutComponents(poly_cell, sub_x, sub_y,layer=1) layout.make_antidot_array(0,0,5,15,0) # marker = [rs.rect(100,100,100,500)] marker = [rs.circ_arc(50, 200, 500, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 350, 500, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 500, 500, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 650, 500, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 800, 500, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 200, 300, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 350, 300, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 500, 300, n=50, theta0=0, thetaf=2*np.pi)] marker += [rs.circ_arc(50, 650, 300, n=50, theta0=0, thetaf=2*np.pi)] for i in range(0,len(marker)): mkr = gdspy.Polygon(marker[i],4) poly_cell.add(mkr) highZ = bragg.Bragg(whigh, ghigh, lhigh, poly_cell, radius=rhigh, layer=2) lowZ = bragg.Bragg(wlow, glow, llow, poly_cell, radius=rlow, layer=2) cavity = bragg.Bragg(wcav, gcav, lcav/2, poly_cell, radius=rlow, layer=2) no_periods = 12 n_left = 5 n_cav = 2 n_right = 5 arr_l = np.repeat(np.arange(0,int(no_periods)),2*np.ones(int(no_periods),dtype=int)) arr_h = np.append(arr_l[1:],[int(no_periods)], axis=0)
def _get_glyph(font, letter): """ Get a block reference to the given letter """ if not isinstance(letter, six.string_types) and len(letter) == 1: raise TypeError("Letter must be a string of length 1. Got: (%s)." % (letter)) if not isinstance(font, freetype.Face): raise TypeError( ("font %r must be a freetype font face. " "Load a font using _get_font_by_name first.") % (font)) if getattr(font, "gds_glyphs", None) is None: font.gds_glyphs = {} if letter in font.gds_glyphs: return font.gds_glyphs[letter] # Get the font name font_name = font.get_sfnt_name( freetype.TT_NAME_IDS['TT_NAME_ID_PS_NAME']).string.decode() if not font_name: # If there is no postscript name, use the family name font_name = font.family_name.replace(" ", "_") block_name = "*char_%s_0x%2X" % (font_name, ord(letter)) # Load control points from font file font.load_char(letter, freetype.FT_LOAD_FLAGS['FT_LOAD_NO_BITMAP']) glyph = font.glyph outline = glyph.outline points = np.array(outline.points, dtype=float) / font.size.ascender tags = outline.tags # Add polylines start, end = 0, -1 polylines = [] for contour in outline.contours: start = end + 1 end = contour # Build up the letter as a curve cpoint = start curve = gdspy.Curve(*points[cpoint], tolerance=0.001) while cpoint <= end: # Figure out what sort of point we are looking at if tags[cpoint] & 1: # We are at an on-curve control point. The next point may be # another on-curve point, in which case we create a straight # line interpolation, or it may be a quadratic or cubic # bezier curve. But first we check if we are at the end of the array if cpoint == end: ntag = tags[start] npoint = points[start] else: ntag = tags[cpoint + 1] npoint = points[cpoint + 1] # Then add the control points if ntag & 1: curve.L(*npoint) cpoint += 1 elif ntag & 2: # We are at a cubic bezier curve point if cpoint + 3 <= end: curve.C(*points[cpoint + 1:cpoint + 4].flatten()) elif cpoint + 2 <= end: plist = list(points[cpoint + 1:cpoint + 3].flatten()) plist.extend(points[start]) curve.C(*plist) else: raise ValueError( "Missing bezier control points. We require at least" " two control points to get a cubic curve.") cpoint += 3 else: # Otherwise we're at a quadratic bezier curve point if cpoint + 2 > end: cpoint_2 = start end_tag = tags[start] else: cpoint_2 = cpoint + 2 end_tag = tags[cpoint_2] p1 = points[cpoint + 1] p2 = points[cpoint_2] # Check if we are at a sequential control point. In that case, # p2 is actually the midpoint of p1 and p2. if end_tag & 1 == 0: p2 = (p1 + p2) / 2 # Add the curve curve.Q(p1[0], p1[1], p2[0], p2[1]) cpoint += 2 else: # We are looking at a control point if not tags[cpoint] & 2: # We are at a quadratic sequential control point. # Check if we're at the end of the segment if cpoint == end: cpoint_1 = start end_tag = tags[start] else: cpoint_1 = cpoint + 1 end_tag = tags[cpoint_1] # If we are at the beginning, this is a special case, # we need to reset the starting position if cpoint == start: p0 = points[end] p1 = points[cpoint] p2 = points[cpoint_1] if tags[end] & 1 == 0: # If the last point is also a control point, then the end is actually # halfway between here and the last point p0 = (p0 + p1) / 2 # And reset the starting position of the spline curve = gdspy.Curve(*p0, tolerance=0.001) else: # The first control point is at the midpoint of this control point and the # previous control point p0 = points[cpoint - 1] p1 = points[cpoint] p2 = points[cpoint_1] p0 = (p0 + p1) / 2 # Check if we are at a sequential control point again if end_tag & 1 == 0: p2 = (p1 + p2) / 2 # And add the segment curve.Q(p1[0], p1[1], p2[0], p2[1]) cpoint += 1 else: raise ValueError( "Sequential control points not valid for cubic splines." ) polylines.append(gdspy.Polygon(curve.get_points())) # Construct the device device = Device(block_name) if polylines: letter_polyline = polylines[0] for polyline in polylines[1:]: letter_polyline = gdspy.boolean(letter_polyline, polyline, "xor") device.add_polygon(letter_polyline) # Cache the return value and return it font.gds_glyphs[letter] = (device, glyph.advance.x / font.size.ascender) return font.gds_glyphs[letter]
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()
cond_layer = 2 remove_layer = 3 conductor = [] removes = [] # Setup gds cell and gds object poly_cell = gdspy.Cell('POLYGONS') rs = Shapes(poly_cell) # SUBSTRATE ######################################################################### sub = [rs.rect(sub_x, sub_y, 0, 0)] for i in range(0, len(sub)): sub = gdspy.Polygon(sub[i], sub_layer) # ANTI-DOTS ######################################################################### layout = LayoutComponents(poly_cell, sub_x, sub_y, layer=dot_layer) dots = layout.antidot_array(0, 0, 10, 30, 0) # FEEDLINE ######################################################################### feedwidth = 3000 lbond = 300 lfeed1 = 600 bondpad = feedbond(x0, y0, wfeed,
import gdspy print('Using gdspy module version ' + gdspy.__version__) # ------------------------------------------------------------------ # # POLYGONS # ------------------------------------------------------------------ # # First we need a cell to add the polygons to. poly_cell = gdspy.Cell('POLYGONS') # We define the polygon through its vertices. points = [(0, 0), (2, 2), (2, 6), (-6, 6), (-6, -6), (-4, -4), (-4, 4), (0, 4)] # Create the polygon on layer 1. poly1 = gdspy.Polygon(points, 1) # Add the new polygon to the cell. poly_cell.add(poly1) # Create another polygon from the same set of points, but rotate it # 180 degrees and add it to the cell. poly2 = gdspy.Polygon(points, 1).rotate(numpy.pi) poly_cell.add(poly2) # To create rectangles we don't need to give the 4 corners, only 2. # Note that we don't need to create a variable if we are not going to # use it, just add the rectangle directly to the cell. Create a # rectangle in layer 2. poly_cell.add(gdspy.Rectangle((18, 1), (22, 2), 2))
def DrawFourJJgroundedQubit ( FourJJqubitCellName = '4JJqubit', FourJJloopLength = 10.5, FourJJloopWidth = 0, #Square loop, unless width is specified LineWidth = 2, #width of the loop wire Spacing = 10, #Spacing between plates and grounding plane, also half the spacing between plates RectangleLength = 100, RectangleWidth = 100, JJparameters= {'FingerWidth': 0.36, #Dictionary with the Josephson junction parameters 'FingerLength': 1, # 'TaperWidth': 0.5, # 'BridgeWidth': 0.14}, JJRelations = [1,1,1,1], #Relations between Josephson junction sizes CircuitLayer = 2, #Layer for photolithography mask eBeamLayer = 5): #Layer for eBeam deposition """ This function returns a four-Josephson-junctions loop cell that contains references to the 4JJ (not necesserily identical) loop cell, a shunting capacitor cell placed above the qubit and the connection to it and to the ground from below the loop. It separately returns the capacitor cell to be added to the resist mask. Three junctions (usually the bigger ones) are on one branch of the loop, and the fourth is on the other. The cell origin is defined at the center of the capacitor. """ if (FourJJloopWidth==0): FourJJloopWidth = FourJJloopLength #If width is not specifically defined make a square loop '''Four JJ loop''' FourJJqubit = DrawFourJJgroundedLoop(FourJJloopCellName = FourJJqubitCellName, FourJJloopLength = FourJJloopLength, FourJJloopWidth = FourJJloopWidth, LineWidth = LineWidth, #width of the RFsquid line JJparameters=JJparameters, #Dictionary with the Josephson junction parameters JJRelations = JJRelations, #Relations between Josephson junction sizes eBeamLayer = eBeamLayer) #Layer for eBeam deposition '''Shunting capcitor and qubit background''' qubit_origin = (0,0) # print("qubit origin with respect to the capacitor center:", qubit_origin) #Uncomment to know qubit location FourJJBackground = gds.Cell(FourJJqubitCellName+'Capacitor', exclude_from_current=True) Cross = gds.Rectangle((-RectangleWidth/2,Spacing),(RectangleWidth/2,Spacing+RectangleLength)).fillet(Spacing/2) CapacitorBackground = gds.Rectangle((-RectangleWidth/2-Spacing,-0*Spacing),(Spacing+RectangleWidth/2,2*Spacing+RectangleLength)).fillet(Spacing/2) QubitBackground = gds.Rectangle((qubit_origin[0]-FourJJloopWidth/2-Spacing,qubit_origin[1]-FourJJloopLength/2-0*Spacing),(qubit_origin[0]+FourJJloopWidth/2+Spacing,qubit_origin[1]+FourJJloopLength/2+Spacing)).fillet(Spacing/2) FourJJBackground.add(gds.boolean([QubitBackground,CapacitorBackground], [Cross], 'not', layer=CircuitLayer)) '''Connection lines and pads''' FourJJconnectionLine = gds.Cell(FourJJqubitCellName+'ConnectionLine', exclude_from_current=True) ConnectionLineLength = Spacing PadLength = 5*LineWidth #Add square pad ConnectionCurve = gds.Curve(1.5*LineWidth, 0).L( LineWidth, 0.5*LineWidth, LineWidth, ConnectionLineLength-0.5*LineWidth, 1.5*LineWidth, ConnectionLineLength, -1.5*LineWidth, ConnectionLineLength, -LineWidth, ConnectionLineLength-0.5*LineWidth, -LineWidth, 0.5*LineWidth, -1.5*LineWidth, 0) FourJJconnectionLine.add(gds.Polygon(ConnectionCurve.get_points(),layer=eBeamLayer).translate(0,FourJJloopLength/2+LineWidth/2)) #Upper pad - connection to (cross) capacitor FourJJconnectionLine.add(create_pad(PadOrigin=(0,FourJJloopLength/2+LineWidth/2+ConnectionLineLength+PadLength/2), PadLength=PadLength, layer=eBeamLayer)) #Two pads at the bottom - connection to ground FourJJconnectionLine.add(create_pad(PadOrigin=(-FourJJloopWidth/2,-FourJJloopLength/2-PadLength/4), PadLength=PadLength/2, layer=eBeamLayer)) FourJJconnectionLine.add(create_pad(PadOrigin=(FourJJloopWidth/2,-FourJJloopLength/2-PadLength/4), PadLength=PadLength/2, layer=eBeamLayer)) FourJJqubit.add(gds.CellReference(FourJJconnectionLine, origin=qubit_origin)) FourJJqubit.add(gds.CellReference(FourJJBackground,origin=tuple(-1*np.asarray(qubit_origin)))) return [FourJJqubit, FourJJBackground, qubit_origin]
def area(self): return gdspy.Polygon(self.shape.points).area()
def DrawFourJJqubit( FourJJqubitCellName='4JJqubit', FourJJloopLength=10.5, FourJJloopWidth=0, LineWidth=2, #width of the RFsquid line JJparameters={ 'FingerWidth': 0.36, #Dictionary with the Josephson junction parameters 'FingerLength': 1.36, # 'TaperWidth': 0.5, # 'BridgeWidth': 0.14 }, JJRelations=[1, 1, 1, 1], #Relations between Josephson junction sizes CircuitLayer=2, #Layer for photolithography mask eBeamLayer=5): #Layer for eBeam deposition """ This function returns a Four Josephson-junctions loop cell that contains references to the 4JJ (not necesserily identical) loop cell, a shunting capacitor cell and the connection to it. It separately returns the capacitor cell (two rectangles enclosing the loop) to be added to the resist mask. Three junction (usually the bigger ones) are on one branch of the loop, and the fourth is on the other. The cell origin is defined at the center of the loop. """ '''Four JJ loop''' FourJJloop = DrawFourJJloop( FourJJloopCellName=FourJJqubitCellName, FourJJloopLength=FourJJloopLength, FourJJloopWidth=FourJJloopWidth, LineWidth=LineWidth, #width of the RFsquid line JJparameters= JJparameters, #Dictionary with the Josephson junction parameters JJRelations=JJRelations, #Relations between Josephson junction sizes eBeamLayer=eBeamLayer) #Layer for eBeam deposition '''Connection lines and pads''' FourJJconnectionLine = gds.Cell(FourJJqubitCellName + 'ConnectionLine', exclude_from_current=True) ConnectionCurve = gds.Curve(1.5 * LineWidth, 0).L( LineWidth, 0.5 * LineWidth, LineWidth, 18 * LineWidth, 1.5 * LineWidth, 18.5 * LineWidth, -1.5 * LineWidth, 18.5 * LineWidth, -LineWidth, 18 * LineWidth, -LineWidth, 0.5 * LineWidth, -1.5 * LineWidth, 0) FourJJconnectionLine.add( gds.Polygon(ConnectionCurve.get_points(), layer=eBeamLayer)) FourJJconnectionLine.add( gds.Rectangle((-6.5 * LineWidth, 18.5 * LineWidth), (6.5 * LineWidth, 25 * LineWidth), layer=eBeamLayer)) '''Shunting capcitor and qubit background''' RectangleLength = 100 RectangleWidth = 100 Spacing = 20 #Spacing between rectangles and grounding plane, also half the spacing between rectangles FourJJCapacitor = gds.Cell(FourJJqubitCellName + 'Capacitor', exclude_from_current=True) Rectangle1 = gds.Rectangle( (-RectangleWidth / 2, Spacing), (RectangleWidth / 2, Spacing + RectangleLength)).fillet(Spacing / 2) Rectangle2 = gds.Rectangle( (-RectangleWidth / 2, -Spacing - RectangleLength), (RectangleWidth / 2, -Spacing)).fillet(Spacing / 2) Circle = gds.Round((0, 0), 2 * Spacing) Background = gds.Rectangle( (-RectangleWidth / 2 - Spacing, -2 * Spacing - RectangleLength), (Spacing + RectangleWidth / 2, 2 * Spacing + RectangleLength)).fillet( Spacing / 2) FourJJCapacitor.add( gds.boolean([Background, Circle], [Rectangle1, Rectangle2], 'not', layer=CircuitLayer)) FourJJloop.add( gds.CellReference(FourJJconnectionLine, origin=(0, FourJJloopLength / 2 + LineWidth / 2))) FourJJloop.add( gds.CellReference(FourJJconnectionLine, origin=(0, -FourJJloopLength / 2 - LineWidth / 2), rotation=180)) FourJJloop.add(gds.CellReference(FourJJCapacitor, origin=(0, 0))) return [FourJJloop, FourJJCapacitor]
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # then add it to the Cell angle_x_dist = 2 * self.wgt.bend_radius * np.sin(self.angle) angle_y_dist = 2 * self.wgt.bend_radius * (1 - np.cos(self.angle)) path1 = gdspy.Path(self.wgt.wg_width, self.port) path1.segment(self.taper_length, direction='+x', final_width=self.taper_width, **self.wg_spec) path2 = gdspy.Path(self.width, (path1.x, path1.y)) path2.segment(self.length, direction='+x', **self.wg_spec) path3 = gdspy.Path(self.taper_width, (path2.x, path2.y + self.wg_sep / 2.0)) path3.turn(self.wgt.bend_radius, self.angle, number_of_points=0.1, final_width=self.wgt.wg_width, **self.wg_spec) path3.turn(self.wgt.bend_radius, -self.angle, number_of_points=0.1, **self.wg_spec) path4 = gdspy.Path(self.taper_width, (path2.x, path2.y - self.wg_sep / 2.0)) path4.turn(self.wgt.bend_radius, -self.angle, number_of_points=0.1, final_width=self.wgt.wg_width, **self.wg_spec) path4.turn(self.wgt.bend_radius, self.angle, number_of_points=0.1, **self.wg_spec) clad_pts = [ (self.port[0], self.port[1] - self.wgt.wg_width / 2.0 - self.wgt.clad_width), (self.port[0] + self.taper_length, self.port[1] - self.width / 2.0 - self.wgt.clad_width), (self.port[0] + self.taper_length + self.length, self.port[1] - self.width / 2.0 - self.wgt.clad_width), (self.port[0] + 2 * self.taper_length + self.length, self.port[1] - self.wg_sep / 2.0 - self.wgt.wg_width / 2.0 - self.wgt.clad_width), (self.port[0] + 2 * self.taper_length + self.length, self.port[1] + self.wg_sep / 2.0 + self.wgt.wg_width / 2.0 + self.wgt.clad_width), (self.port[0] + self.taper_length + self.length, self.port[1] + self.width / 2.0 + self.wgt.clad_width), (self.port[0] + self.taper_length, self.port[1] + self.width / 2.0 + self.wgt.clad_width), (self.port[0], self.port[1] + self.wgt.wg_width / 2.0 + self.wgt.clad_width) ] clad = gdspy.Polygon(clad_pts, **self.clad_spec) clad_path3 = gdspy.Path(self.taper_width + 2 * self.wgt.clad_width, (path2.x, path2.y + self.wg_sep / 2.0)) clad_path3.turn(self.wgt.bend_radius, self.angle, number_of_points=0.1, final_width=self.wgt.wg_width + 2 * self.wgt.clad_width, **self.clad_spec) clad_path3.turn(self.wgt.bend_radius, -self.angle, number_of_points=0.1, **self.clad_spec) clad_path4 = gdspy.Path(self.taper_width + 2 * self.wgt.clad_width, (path2.x, path2.y - self.wg_sep / 2.0)) clad_path4.turn(self.wgt.bend_radius, -self.angle, number_of_points=0.1, final_width=self.wgt.wg_width + 2 * self.wgt.clad_width, **self.clad_spec) clad_path4.turn(self.wgt.bend_radius, +self.angle, number_of_points=0.1, **self.clad_spec) angle = 0 totlength = self.length + angle_x_dist + self.taper_length #2*self.taper_length+self.length ylength = self.wg_sep / 2.0 + angle_y_dist if self.direction == "EAST": self.output_port_top = (self.port[0] + totlength, self.port[1] + ylength) self.output_port_bot = (self.port[0] + totlength, self.port[1] - ylength) elif self.direction == "NORTH": self.output_port_top = (self.port[0] - ylength, self.port[1] + totlength) self.output_port_bot = (self.port[0] + ylength, self.port[1] + totlength) angle = np.pi / 2.0 elif self.direction == "WEST": self.output_port_top = (self.port[0] - totlength, self.port[1] - ylength) self.output_port_bot = (self.port[0] - totlength, self.port[1] + ylength) angle = np.pi elif self.direction == "SOUTH": self.output_port_top = (self.port[0] + ylength, self.port[1] - totlength) self.output_port_bot = (self.port[0] - ylength, self.port[1] - totlength) angle = -np.pi / 2.0 elif isinstance(self.direction, float) or isinstance( self.direction, int): angle = float(self.direction) x1, y1 = totlength, ylength x1r, y1r = np.cos(angle) * x1 - np.sin(angle) * y1, np.sin( angle) * x1 + np.cos(angle) * y1 x2, y2 = totlength, -ylength x2r, y2r = np.cos(angle) * x2 - np.sin(angle) * y2, np.sin( angle) * x2 + np.cos(angle) * y2 self.output_port_top = (self.port[0] + x1r, self.port[1] + y1r) self.output_port_bot = (self.port[0] + x2r, self.port[1] + y2r) path1.rotate(angle, self.port) path2.rotate(angle, self.port) path3.rotate(angle, self.port) path4.rotate(angle, self.port) clad_path3.rotate(angle, self.port) clad_path4.rotate(angle, self.port) clad.rotate(angle, self.port) self.add(path1) self.add(path2) self.add(path3) self.add(path4) self.add(clad_path3) self.add(clad_path4) self.add(clad)
def test_hobby1(target): cell = gdspy.Cell('test', True) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)]) cell.add(gdspy.Polygon(c.get_points(), layer=1)) c = gdspy.Curve(2, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, None]) cell.add(gdspy.Polygon(c.get_points(), layer=3)) c = gdspy.Curve(4, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, None, None, 2 / 3.0 * numpy.pi]) cell.add(gdspy.Polygon(c.get_points(), layer=5)) c = gdspy.Curve(0, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, 3 / 4.0 * numpy.pi]) cell.add(gdspy.Polygon(c.get_points(), layer=7)) c = gdspy.Curve(2, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, None, numpy.pi / 2, None]) cell.add(gdspy.Polygon(c.get_points(), layer=9)) c = gdspy.Curve(4, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, None]) cell.add(gdspy.Polygon(c.get_points(), layer=11)) c = gdspy.Curve(0, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, -numpy.pi / 2]) cell.add(gdspy.Polygon(c.get_points(), layer=13)) c = gdspy.Curve(2, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, -numpy.pi, -numpy.pi / 2]) cell.add(gdspy.Polygon(c.get_points(), layer=15)) c = gdspy.Curve(4, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[-numpy.pi / 4, 0, numpy.pi / 2, -numpy.pi]) cell.add(gdspy.Polygon(c.get_points(), layer=17)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=2)) c = gdspy.Curve(2, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, None], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=4)) c = gdspy.Curve(4, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, None, None, 2 / 3.0 * numpy.pi], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=6)) c = gdspy.Curve(0, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, 3 / 4.0 * numpy.pi], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=8)) c = gdspy.Curve(2, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, None, numpy.pi / 2, None], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=10)) c = gdspy.Curve(4, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, None], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=12)) c = gdspy.Curve(0, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, -numpy.pi / 2], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=14)) c = gdspy.Curve(2, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, -numpy.pi, -numpy.pi / 2], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=16)) c = gdspy.Curve(4, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[-numpy.pi / 4, 0, numpy.pi / 2, -numpy.pi], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=18)) assertsame(target['Hobby1'], cell)
def make(self, x0, y0, layer=0): rectangle = self.__rs.rect(self.__w, self.__l, x0, y0) rec = gdspy.Polygon(rectangle, layer) self.__cell.add(rec) return rectangle
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), ] p0 = gdspy.Polygon(points0) p1 = gdspy.Polygon(points1) p2 = gdspy.Polygon(points2) p3 = gdspy.Polygon(points3) p4 = gdspy.Polygon(points4) p5 = gdspy.Polygon(points5_for_pad1) p6 = gdspy.Polygon(points6_for_pad2) p7 = gdspy.Polygon(points7) p8 = gdspy.Polygon(points8_for_pad3) p9 = gdspy.Polygon(points9_for_pad4) p10 = gdspy.Polygon(points10) p11 = gdspy.Polygon(points11) p12 = gdspy.Polygon(points12) p13 = gdspy.Polygon(points13) return p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13
rext, rlow, rhigh = [0, 55, 55] # radii lext1, lext2 = [400, 1200] # Extrude lengths lext3 = llow - lext1 - lext2 - 500 * np.pi - 150 * np.pi # Start making resonator geometry ############################################################################ # # Setup gds cell and gds object poly_cell = gdspy.Cell('POLYGONS') rs = Shapes(poly_cell) # Substrate coordinate list sub = rs.rect(sub_x, sub_y, 0, 0) substrate = gdspy.Polygon(sub, layer=0) # Cavity sections # coords = lambda x, dx=0: x + dx xb_strt, yb_strt = [coords(1250), coords(sub_y / 2) - lext2 - lext3 - 140] lcav1, lcav2, lcav3 = [1000, 5500, 100] taper_length = 100 cav_x0, cav_y0 = [coords(xb_strt), coords(yb_strt, -lcav1)] cav_cond = [rs.rect(wc, lcav1, cav_x0, cav_y0)] cav_x1, cav_y1 = [coords(xb_strt, -rlow), coords(yb_strt, -lcav1)] cav_cond += [rs.halfarc(rlow, wc, cav_x1, cav_y1, orientation='S', npoints=40)] cav_x2, cav_y2 = [coords(xb_strt, -2 * rlow - wc), coords(yb_strt, -lcav1)]
def gc_focusing_PC(lib, filename0 ="GC", xp=14, theta=25, a=0.23, D=0.150, d=0.665, period_num=29, w_wg=0.5, w_etch=3): """ cell: cell in Gdspy \n pa: parameters for grating coupler \n xp: the start position of pa \n theta: the angle of GC \n w_gc: width of grating coupler \n w_wg: width of waveguide\n w_etch: width of etch """ # xp is the length of taper GC_theta = (theta+3)/180*np.pi GC_theta2 = theta/180*np.pi i = 0 D_hole = 0.165 a_hole = a # create the main body of phtonic crystal grating coupler d_all = np.ones(period_num)*d D_all = np.ones(period_num)*D # name the cell that include the grating filename = filename0 + "_a"+str(int(a*1e3)) +"_D"+str(int(D*1e3)) +"_d"+str(np.around(d*1e3,0).astype(int)) +"_wg"+ str(int(w_wg*1000)) grating = lib.new_cell(filename) for ii in range(period_num): # this is for a variable period if ii == 0: x_start = -xp else: x_start += -d_all[ii] # create the cell for reference D_temp = D_all[ii] name_cell = "D"+str(int(D_temp*1e3)) if name_cell not in lib.cells: circles = lib.new_cell(name_cell) circle = gdspy.Round((0, 0), D_temp/2, tolerance=0.0001, **ld_grating) circles.add(circle) else: Cell_all = lib.cells circles = Cell_all[name_cell] theta_delta = (a_hole*np.sqrt(3))/abs(x_start) num_y = np.floor(GC_theta2/theta_delta)*2 if num_y % 2 == 0: num_y += 1 # create the 3 column of hole for x_index in range(3): if x_index == 1: num_y = num_y + 1 for y_index in range(int(num_y)): grating.add(gdspy.CellReference(circles, ((x_start + x_index*a/2)*np.cos(theta_delta*(y_index-(num_y - 1)/2)), (x_start + x_index*a/2)*np.sin(theta_delta*(y_index-(num_y - 1)/2))))) if x_index == 1: num_y = num_y - 1 xp = abs(x_start) GC_theta = GC_theta2 points = [(0, w_wg/2), (-xp*np.cos(GC_theta), xp*np.sin(GC_theta)), (-xp*np.cos(GC_theta), xp*np.sin(GC_theta) + w_etch), (0, w_wg/2 + w_etch)] poly = gdspy.Polygon(points, **ld_fulletch) grating.add(poly) poly = gdspy.Polygon(points, **ld_fulletch).mirror((0,0), (1,0)) grating.add(poly) return grating
def _generate_section_structures(self, distance, radius, structure=PILLARS, section=1): """Generates the desired structures in the selected section. Args: distance: In the case of pillars is the distance between their centers and in the case of grid is the distance between the middle oftwo parallel "walls". radius: In the case of pillars is the distance between the center and the edge. In the case of grid is the distance between each edge. structure: Structure that is going to be generated. (default Pillars) section: Section where the structures are going to be generated. Raise: ValueError: If the selected section is out of range. """ if section > self.num_sections: raise ValueError("Selected Section has to be less or equal than {0}".format(self.num_sections)); row = int((section - 1) / self.cols) col = int((section - 1) % self.cols) # Calculating starting coordinates of the section x = self.drawing_x + col * self.drawing_x_step y = self.drawing_y - row * self.drawing_y_step # Correcting width and height to respect the gap width = self.drawing_x_step - self.GAP_BETWEEN_SECTIONS/2 height = self.drawing_y_step - self.GAP_BETWEEN_SECTIONS/2 polygons = [] if structure == self.PILLARS: pillars = Pillar.generate_pilars_region(distance, radius, x, y, width, height) for pillar in pillars: poly = gdspy.Polygon(pillar, self.STRUCTURES_LAYER) polygons.append(poly) else: horizontal, vertical = Grid.generate_grid_region(distance, radius, x, y, width, height) if structure == self.GRID: for h in horizontal: poly = gdspy.Rectangle(h[0], h[1], self.STRUCTURES_LAYER ) polygons.append(poly) for v in vertical: poly = gdspy.Rectangle(v[0], v[1], self.STRUCTURES_LAYER ) polygons.append(poly) elif structure == self.LINES_H: for v in vertical: poly = gdspy.Rectangle(v[0], v[1], self.STRUCTURES_LAYER) polygons.append(poly) elif structure == self.LINES_V: for h in horizontal: poly = gdspy.Rectangle(h[0], h[1], self.STRUCTURES_LAYER) polygons.append(poly) self.setups[section] = {'radius': radius, 'distance': distance, 'structure': structure} # The fitting the generated rectangular section in the Margin area merged = gdspy.fast_boolean(polygons, self.margin_polygon, 'and', layer=self.STRUCTURES_LAYER,max_points=3000) self.cell.add(merged)
rext, rlow, rhigh = [0, 55, 55] # radii lext1, lext2 = [400, 1200] # Extrude lengths lext3 = llow - lext1 - lext2 - 500 * np.pi - 150 * np.pi # Start making resonator geometry ############################################################################ # # Setup gds cell and gds object poly_cell = gdspy.Cell('POLYGONS') rs = Shapes(poly_cell) # Substrate coordinate list sub = rs.rect(sub_x, sub_y, 0, 0) substrate = gdspy.Polygon(sub, layer=0) # Cavity sections # coords = lambda x, dx=0: x + dx # xb_strt,yb_strt = [coords(1250),coords(sub_y/2)- lext2 - lext3 - 140] xb_strt, yb_strt = [755, 1300] lcav1, lcav2, lcav3 = [1000, 5500, 100] taper_length = 100 cav_x0, cav_y0 = [coords(xb_strt, -rlow), coords(yb_strt, -lcav1 - rlow - wc)] cav_cond = [rs.rect(lcav1, wc, cav_x0, cav_y0)] cav_x1, cav_y1 = [coords(xb_strt, -rlow), coords(yb_strt, -lcav1)] cav_cond += [ rs.quarterarc(rlow, wc, cav_x1, cav_y1, orientation='SW', npoints=40)
r = 500 lcap = 100 lstart = 100 c_gap = 1 #resonator - 3 element list [coarse res elements, fine res elements, stuff to remove from ground plane] #res poly_cell.elements = [] cc = ccs[0] gap = gaps[4] res = rs.hw_sim(cc, gap, r, lcap, lstart, c_gap) print(res[0]) for i in res[0]: poly_cell.add(gdspy.Polygon(i, 2)) grnd = rs.rect(res[2], res[3] + 1000, 0, -(res[3] + 1000) / 2) grnd_poly = gdspy.Polygon(grnd, 0) ps = [] for i in res[1]: ps.append(gdspy.Polygon(i, 1)) for i in ps: grnd_poly = gdspy.fast_boolean(grnd_poly, i, 'not', precision=1e-9, max_points=1000, layer=0)
def gdsgen_part(self, part_id, layer=1, dbu=0.001, n_points_for_circle=128, input_params={}): ## if isinstance(n_points_for_circle, float): n_points_for_circle = int(n_points_for_circle / dbu) ## export_obj_ids = [] export_kl_obj_ids = [] gds_objs = {} kl_objs = {} skipped_obj_ids = [] if part_id in self.two_dim_part_dict: part = self.two_dim_part_dict[part_id] is_wp = False elif part_id in self.two_dim_wp_dict: part = self.two_dim_wp_dict[part_id] is_wp = True else: raise Exception('Could not find the corresponding parts or wp.') eval_g_params = func_dict.copy() eval_g_params.update(self.g_params_evaluated) if_skip_flag = False for obj_id in part.obj_order: local_params = None obj = part.objs[obj_id] if input_params: local_params = part.get_local_params(input_params) local_params.update(input_params) else: local_params = part.get_local_params() local_params.update(part.input_params) obj.eval_params(eval_g_params, local_params) if obj.is_active == False: pass elif obj.type == 'EndIf': if_skip_flag = False elif if_skip_flag == True: skipped_obj_ids.append(obj.id) elif obj.type == 'If': if obj.params_evaluated['condition'] == False: if_skip_flag = True else: if_skip_flag = False elif obj.type == 'Circle': r = obj.params_evaluated['r'] angle_i = 0. angle_f = 2 * np.pi r_i = 0. if 'angle' in obj.params_evaluated: angle_f = obj.params_evaluated['angle'] * np.pi / 180.0 if 'layer' in obj.params_evaluated: if len(obj.params_evaluated['layer']) > 1: print( 'Warning: Circle with more than 1 layer is not supported ({}).' .format(obj.id), file=sys.stderr) r_i = r - obj.params_evaluated['layer'][0] gds_obj = gdspy.Round((0, 0), r, initial_angle=angle_i, final_angle=angle_f, inner_radius=r_i, number_of_points=n_points_for_circle, layer=layer) if 'rot' in obj.params_evaluated: gds_obj.rotate(obj.params_evaluated['rot'] * np.pi / 180.0) if 'pos' in obj.params_evaluated: gds_obj.translate(*obj.params_evaluated['pos']) gds_objs[obj_id] = gds_obj export_obj_ids.append(obj_id) elif obj.type == 'Rectangle': size = np.array(obj.params_evaluated['size']) if 'base' in obj.params_evaluated and obj.params_evaluated[ 'base'] == 'center': gds_obj = gdspy.Rectangle(-size / 2.0, size / 2.0, layer=layer) else: gds_obj = gdspy.Rectangle((0, 0), size, layer=layer) if 'rot' in obj.params_evaluated: gds_obj.rotate(obj.params_evaluated['rot'] * np.pi / 180.0) if 'pos' in obj.params_evaluated: gds_obj.translate(*obj.params_evaluated['pos']) gds_objs[obj_id] = gds_obj export_obj_ids.append(obj_id) elif obj.type == 'Polygon': if 'source' in obj.params_evaluated: if obj.params_evaluated['source'] == 'table': gds_obj = gdspy.Polygon(obj.params_evaluated['table'], layer=layer) gds_objs[obj_id] = gds_obj export_obj_ids.append(obj_id) else: print('Unsupported source ({0}) in {1}'.format( params_evaluated['source'], obj.id, file=sys.stderr)) else: print('Source not specified in {}'.format(obj.id), file=sys.stderr) elif obj.type == 'Union': sel = obj.selections['input'] union_list = [] for sel_obj_id_org in sel: if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections[ 'input'][0] else: sel_obj_id = sel_obj_id_org union_list.append(sel_obj_id) if sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) if union_list: union_obj = None for sel_obj_id in union_list: union_obj = gdspy.boolean(union_obj, gds_objs[sel_obj_id], 'or', precision=dbu, layer=layer) gds_objs[obj_id] = union_obj export_obj_ids.append(obj_id) ### from here elif obj.type == 'Difference': selA = obj.selections['input'] selB = obj.selections['input2'] objA_list = [] objB_list = [] for sel_obj_id_org in selA: if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections[ 'input'][0] else: sel_obj_id = sel_obj_id_org objA_list.append(sel_obj_id) if sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) for sel_obj_id_org in selB: if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections[ 'input'][0] else: sel_obj_id = sel_obj_id_org objB_list.append(sel_obj_id) if sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) if objA_list: objA = None for sel_obj_id in objA_list: objA = gdspy.boolean(objA, gds_objs[sel_obj_id], 'or', precision=dbu, layer=layer) if objB_list: objB = None for sel_obj_id in objB_list: objB = gdspy.boolean(objB, gds_objs[sel_obj_id], 'or', precision=dbu, layer=layer) diff_obj = gdspy.boolean(objA, objB, 'not', precision=dbu, layer=layer) gds_objs[obj_id] = diff_obj export_obj_ids.append(obj_id) elif obj.type == 'Move': if 'displx' in obj.params_evaluated: displx = obj.params_evaluated['displx'] else: displx = 0 if 'disply' in obj.params_evaluated: disply = obj.params_evaluated['disply'] else: disply = 0 sel = obj.selections['input'] # for single slection if len(sel) > 1: print( 'Warning: {} of more than 1 object is not supported.'. format(obj.type), file=sys.stderr) sel_obj_id_org = sel[0] if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections['input'][ 0] else: sel_obj_id = sel_obj_id_org sel_obj = gds_objs[sel_obj_id] move_obj = gdspy.copy(sel_obj, displx, disply) gds_objs[obj_id] = move_obj export_obj_ids.append(obj_id) if 'keep' in obj.params_evaluated and obj.params_evaluated[ 'keep'] == True: pass elif sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) elif obj.type == 'Mirror': if 'pos' in obj.params_evaluated: pos = np.array(obj.params_evaluated['pos']) else: pos = np.array([0., 0.]) if 'axis' in obj.params_evaluated: axis = np.array(obj.params_evaluated['axis']) else: axis = np.array([1., 0.]) sel = obj.selections['input'] # for single selection if len(sel) > 1: print( 'Warning: {} of more than 1 object is not supported.'. format(obj.type), file=sys.stderr) sel_obj_id_org = sel[0] if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections['input'][ 0] else: sel_obj_id = sel_obj_id_org sel_obj = gds_objs[sel_obj_id] mirror_obj = gdspy.copy(sel_obj).mirror( pos, pos + np.array([-axis[1], axis[0]])) gds_objs[obj_id] = mirror_obj export_obj_ids.append(obj_id) if 'keep' in obj.params_evaluated and obj.params_evaluated[ 'keep'] == True: pass elif sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) elif obj.type == 'Rotate': if 'rot' in obj.params_evaluated: if isinstance( obj.params_evaluated['rot'], (list, tuple, np.ndarray)): # can be ndarray when use range rot = np.array( obj.params_evaluated['rot'] ) * np.pi / 180 # rot can be the list of angle else: rot = np.array([obj.params_evaluated['rot'] ]) * np.pi / 180 else: rot = np.array([0.]) if 'pos' in obj.params_evaluated: pos = np.round(np.array(obj.params_evaluated['pos'])) else: pos = np.array([0., 0.]) sel = obj.selections['input'] if len(sel) > 1: print( 'Warning: {} of more than 1 object is not supported.'. format(obj.type), file=sys.stderr) sel_obj_id_org = sel[0] if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections['input'][ 0] else: sel_obj_id = sel_obj_id_org sel_obj = gds_objs[sel_obj_id] rot_obj = gdspy.copy(sel_obj).rotate(rot[0], center=pos) for angle in rot[1:]: rot_obj = gdspy.boolean(rot_obj, gdspy.copy(sel_obj).rotate( angle, center=pos), 'or', precision=dbu, layer=layer) gds_objs[obj_id] = rot_obj export_obj_ids.append(obj_id) if 'keep' in obj.params_evaluated and obj.params_evaluated[ 'keep'] == True: pass elif sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) elif obj.type == 'Array': if 'type' in obj.params_evaluated and obj.params_evaluated[ 'type'] == 'linear': linearsize = obj.params_evaluated['linearsize'] displ = np.array(obj.params_evaluated['displ']) sel = obj.selections['input'] if len(sel) > 1: print( 'Warning: {} of more than 1 object is not supported.' .format(obj.type), file=sys.stderr) sel_obj_id_org = sel[0] if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections[ 'input'][0] else: sel_obj_id = sel_obj_id_org sel_obj = gds_objs[sel_obj_id] arr_obj = gdspy.copy(sel_obj) for i in range(1, int(linearsize)): displ_i = displ * i arr_obj = gdspy.boolean( arr_obj, gdspy.copy(sel_obj).translate(*displ_i), 'or', precision=dbu, layer=layer) if sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) gds_objs[obj_id] = arr_obj export_obj_ids.append(obj_id) else: fullsize = obj.params_evaluated['fullsize'] displ = np.array(obj.params_evaluated['displ']) sel = obj.selections['input'] if len(sel) > 1: print( 'Warning: {} of more than 1 object is not supported.' .format(obj.type), file=sys.stderr) sel_obj_id_org = sel[0] if sel_obj_id_org in skipped_obj_ids: sel_obj_id = part.objs[sel_obj_id_org].selections[ 'input'][0] else: sel_obj_id = sel_obj_id_org sel_obj = gds_objs[sel_obj_id] arr_obj = gdspy.copy(sel_obj) for i in range(int(fullsize[0])): for j in range(int(fullsize[1])): if (i, j) is (0, 0): continue displ_ij = np.array([i, j]) * displ arr_obj = gdspy.boolean( arr_obj, gdspy.copy(sel_obj).translate(*displ_ij), 'or', precision=dbu, layer=layer) if sel_obj_id in export_obj_ids: export_obj_ids.remove(sel_obj_id) gds_objs[obj_id] = arr_obj export_obj_ids.append(obj_id) elif obj.type == 'PartInstance': if 'part' in obj.params_evaluated: pi_part_id = obj.params_evaluated['part'] else: if is_wp == True: pi_part_id = self.default_part_id_wp else: pi_part_id = self.default_part_id if isinstance(obj.params_evaluated['inputexpr'][0], list): # 3.5a pi_params = dict(obj.params_evaluated['inputexpr']) else: pi_param_keys = self.two_dim_part_dict[ pi_part_id].input_param_names pi_param_vals = obj.params_evaluated['inputexpr'] pi_params = dict(zip(pi_param_keys, pi_param_vals)) pi_objs, pi_export_obj_ids = self.gdsgen_part( pi_part_id, layer=layer, dbu=dbu, n_points_for_circle=n_points_for_circle, input_params=pi_params) if len(pi_export_obj_ids) > 1: print( 'Warning: PartInstance with more than 1 final objects is not supported ({}).' .format(pi_part_id), file=sys.stderr) print( ' Take union in the definition of Geometry Parts', file=sys.stderr) pi_obj = pi_objs[pi_export_obj_ids[0]] if 'rot' in obj.params_evaluated: angle = obj.params_evaluated['rot'] * np.pi / 180 pi_obj = pi_obj.rotate(angle) if 'displ' in obj.params_evaluated: displ = np.array(obj.params_evaluated['displ']) pi_obj = pi_obj.translate(*displ) gds_objs[obj_id] = pi_obj export_obj_ids.append(obj_id) else: print('Warning: object({}) was skipped.'.format(obj_id), file=sys.stderr) return (gds_objs, export_obj_ids)
dst = np.uint8(dst) # find centroids ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst) # define the criteria to stop and refine the corners criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001) corners = cv2.cornerSubPix(gray, np.float32(centroids), (5, 5), (-1, -1), criteria) # Now draw them # res = np.hstack((centroids,corners)) # res = np.int0(res) # img[res[:,1],res[:,0]]=[0,0,255] # img[res[:,3],res[:,2]] = [0,255,0] # cv2.imwrite('subpixel.png',img) poly_cell = gdspy.Cell('tmp') points = corners[1:, :] print(points) poly1 = gdspy.Polygon(points, 1) poly_cell.add(poly1) gdspy.write_gds('square.gds', unit=1.0e-6, precision=1.0e-9) # gdsii=gdspy.GdsLibrary() # gdsii.read_gds('test.gds') # gdsii.extract('tmp') # gdspy.LayoutViewer()
resonatorarray.flatten() end = N * unitcellsize + (N - 1) * intercell * 1e6 - width * 1e6 / 2, snake1[-1][1] Sr = 2e-6 A = Cpw_meandered(snake1, snakedim, end, Sr, w=10e-6, Lc=215e-6, Lline=470e-6, T=50e-6, s=7.1e-6) #Generating polygons from the previous function LCpw = gdspy.Polygon(A[0]) HeadLeft = gdspy.FlexPath(A[1], width * 1e6, **carac).rotate(np.pi, A[2]) RCpw = gdspy.Polygon(A[3]) HeadRight = gdspy.FlexPath(A[4], width * 1e6, **carac) TGround = gdspy.Polygon(A[5]) BGround = gdspy.Polygon(A[6]) #add everything to cell cpw cpw = gdspy.Cell("cpw") cpw.add([LCpw, HeadLeft, RCpw, HeadRight, TGround, BGround]) cpw.add(resonatorarray) lib = gdspy.GdsLibrary() lib.add(cpw) lib.write_gds('meandered_test_array.gds')
def X(W, S, tl=37, bl=33, ext=None): ''' Generate X 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) WdSqr2 = W / np.sqrt(2) WpSd2 = W + S / 2 ########################################################################### # If 'ext' = None, then the natural width of the crossover is used. # # When 'ext' = 'XX' for example, the 'X' width is extended to 'XX' width. # ########################################################################### if ext == None: edge_x = Stanz + WpSd2 + WdSqr2 else: CO = gdspy.CellReference(ext) edge_x = CO.get_bounding_box()[1][0] ############################ # Points for 'X' structure # ############################ A2x = WpSd2 - WdSqr2 A2y = WpSd2 B2x = edge_x B2y = A2y C2x = B2x C2y = S / 2 D2x = S / 2 + WdSqr2 D2y = C2y ##################################################### # Collect points of 'X' into list of list of tuples # ##################################################### ############################################### # Top of the 'X' structure # # The upper right to lower left crossover _/- # ############################################### x2top = [] x2top.append((A2x, A2y)) x2top.append((B2x, B2y)) x2top.append((C2x, C2y)) x2top.append((D2x, D2y)) x2top.append((-A2x, -A2y)) x2top.append((-B2x, -B2y)) x2top.append((-C2x, -C2y)) x2top.append((-D2x, -D2y)) ############################################### # Bottom of the 'X' structure # # The lower right to upper left crossover -\_ # ############################################### x2bot = [] x2bot.append((-A2x, A2y)) x2bot.append((-B2x, B2y)) x2bot.append((-C2x, C2y)) x2bot.append((-D2x, D2y)) x2bot.append((A2x, -A2y)) x2bot.append((B2x, -B2y)) x2bot.append((C2x, -C2y)) x2bot.append((D2x, -D2y)) ################################## # Generate 'X' crossover polygon # ################################## X_Shapes = [] X_Shapes.append(gdspy.Polygon(x2top, tl)) X_Shapes.append(gdspy.Polygon(x2bot, bl)) ##################################### # Create GDS cell for 'X' crossover # ##################################### X = gdspy.Cell('X', exclude_from_current=False) ########################################## # Add the 'X' polygons into the GDS cell # ########################################## for shape in X_Shapes: X.add(shape) ######################## # Add via to crossover # ######################## ####################################################################### # Use cell 'VIA_ARR' generated by function 'VIA' as the via structure # ####################################################################### #via locations via_2l = [(edge_x - W / 2, -0.5 * (W + S)), (-(edge_x - W / 2), 0.5 * (W + S))] for v_loc in via_2l: VIA = gdspy.CellReference('VIA_ARR') VIA.translate(v_loc[0], v_loc[1]) X.add(VIA) #End of adding via X.flatten() #End of 'X' crossover generation ################################################## # Generate a mirrored version of 'X' called 'XM' # ################################################## XM = gdspy.Cell('XM', exclude_from_current=False) X_ref = gdspy.CellReference('X', (0, 0), x_reflection=True) XM.add(X_ref).flatten()
def __build_cell(self): # Sequentially build all the geometric shapes using polygons # Add strip waveguide taper for region 1 x0, y0 = (0, 0) pts = [ (x0, y0 - self.wgt_strip.wg_width / 2.0), (x0, y0 + self.wgt_strip.wg_width / 2.0), ( x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0 + self.end_strip_width, ), (x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0), ] strip1 = gdspy.Polygon(pts, layer=self.wgt_strip.wg_layer, datatype=self.wgt_strip.wg_datatype) # Add the thin side waveguide for region 1 pts = [ (x0, y0 + self.wgt_strip.wg_width / 2.0 + self.d), (x0, y0 + self.wgt_strip.wg_width / 2.0 + self.d + self.start_rail_width), ( x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0 + self.end_strip_width + self.wgt_slot.slot + self.start_rail_width, ), ( x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0 + self.end_strip_width + self.wgt_slot.slot, ), ] thin_strip = gdspy.Polygon(pts, layer=self.wgt_strip.wg_layer, datatype=self.wgt_strip.wg_datatype) # Add the bottom rail for region 2 pts = [ ( x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0 + self.end_strip_width, ), (x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0), (x0 + self.length1 + self.length2, y0 - self.wgt_slot.wg_width / 2.0), ( x0 + self.length1 + self.length2, y0 - self.wgt_slot.wg_width / 2.0 + self.wgt_slot.rail, ), ] rail1 = gdspy.Polygon(pts, layer=self.wgt_strip.wg_layer, datatype=self.wgt_strip.wg_datatype) # Add the top rail for region 2 pts = [ ( x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0 + self.end_strip_width + self.wgt_slot.slot + self.start_rail_width, ), ( x0 + self.length1, y0 - self.wgt_strip.wg_width / 2.0 + self.end_strip_width + self.wgt_slot.slot, ), ( x0 + self.length1 + self.length2, y0 + self.wgt_slot.wg_width / 2.0 - self.wgt_slot.rail, ), (x0 + self.length1 + self.length2, y0 + self.wgt_slot.wg_width / 2.0), ] rail2 = gdspy.Polygon(pts, layer=self.wgt_strip.wg_layer, datatype=self.wgt_strip.wg_datatype) # Add a cladding polygon pts = [ (x0, y0 + self.wgt_strip.clad_width + self.wgt_strip.wg_width / 2.0), ( x0 + self.length1 + self.length2, y0 + self.wgt_slot.clad_width + self.wgt_slot.wg_width / 2.0, ), ( x0 + self.length1 + self.length2, y0 - self.wgt_slot.clad_width - self.wgt_slot.wg_width / 2.0, ), (x0, y0 - self.wgt_strip.clad_width - self.wgt_strip.wg_width / 2.0), ] clad = gdspy.Polygon(pts, layer=self.wgt_strip.clad_layer, datatype=self.wgt_strip.clad_datatype) self.add(strip1) self.add(thin_strip) self.add(rail1) self.add(rail2) self.add(clad)
dr.text((x, y), l.text, font=font, fill=color[(l.layer, l.texttype)]) img = img.resize((width, height), Image.ANTIALIAS) name = "docs/_static/" + (cell.name if name is None else name) + ".png" print("Saving", name) img.save(name) if __name__ == "__main__": # Polygons # Create a polygon from a list of vertices points = [(0, 0), (2, 2), (2, 6), (-6, 6), (-6, -6), (-4, -4), (-4, 4), (0, 4)] poly = gdspy.Polygon(points) draw(gdspy.Cell("polygons").add(poly)) # Holes # Manually connect the hole to the outer boundary cutout = gdspy.Polygon([(0, 0), (5, 0), (5, 5), (0, 5), (0, 0), (2, 2), (2, 3), (3, 3), (3, 2), (2, 2)]) draw(gdspy.Cell("holes").add(cutout)) # Circles # Circle centered at (0, 0), with radius 2 and tolerance 0.1 circle = gdspy.Round((0, 0), 2, tolerance=0.01) # To create an ellipse, simply pass a list with 2 radii. # Because the tolerance is small (resulting a large number of # vertices), the ellipse is fractured in 2 polygons.
def test_add_element(): p = gdspy.Polygon(((0, 0), (1, 0), (0, 1))) c = gdspy.Cell('c_add_element') assert c.add(p) is c assert c.add([p, p]) is c assert c.elements == [p, p, p]
# STEP 2: # creat the gdslibrary lib = gdspy.GdsLibrary(precision=1e-10) # Geometry must be placed in cells. device = lib.new_cell('GC') ld_fulletch = {"layer": 1, "datatype": 1} ld_grating = {"layer": 1, "datatype": 2} # create the cell: waveguides wg = lib.new_cell('waveguides') points = [(0, w_wg / 2), (-l_wg, w_wg / 2), (-l_wg, w_wg / 2 + w_etch), (0, w_wg / 2 + w_etch)] poly = gdspy.Polygon(points, **ld_fulletch) wg.add(poly) poly = gdspy.Polygon(points, **ld_fulletch).mirror((0, 0), (1, 0)) wg.add(poly) # define the size of hole: D # define the length of period: d_goal D_all = np.linspace(145, 160, 4) * 1e-3 d_goal_all = np.linspace(650, 680, 7) * 1e-3 filename0 = "GC" num_GC = 0 num_block = 0 for index_D in D_all: D_temp = index_D D = np.ones(period_num) * D_temp
# layers sub_layer = 0 dot_layer = 1 cond_layer = 2 rem_layer = 3 # Start making resonator geometry ############################################################################ # # Setup gds cell and gds object poly_cell = gdspy.Cell('POLYGONS') rs = Shapes(poly_cell) # Substrate coordinate list sub = rs.rect(sub_x, sub_y, wrhead_xoff, wrhead_yoff) substrate = gdspy.Polygon(sub, layer=sub_layer) # Dots layout = LayoutComponents(poly_cell, sub_x, sub_y, layer=dot_layer) dots = layout.antidot_array(wrhead_xoff, wrhead_yoff, 10, 30, 0) coords = lambda x, dx=0: x + dx # CAVITY SECTION #################### lcav1, lcav2, arcc = cavlengths(lc, rcav) xb_strt, yb_strt = [ coords(sub_x / 2 - arcc) + xoff + wrhead_xoff, coords(sub_y / 2, wrhead_yoff)
def import_gds( gdspath: Union[str, Path], cellname: Optional[str] = None, flatten: bool = False, snap_to_grid_nm: Optional[int] = None, name: Optional[str] = None, decorator: Optional[Callable] = None, gdsdir: Optional[Union[str, Path]] = None, **kwargs, ) -> Component: """Returns a Componenent from a GDS file. Adapted from phidl/geometry.py if any cell names are found on the component CACHE we append a $ with a number to the name Args: gdspath: path of GDS file. cellname: cell of the name to import (None) imports top cell. flatten: if True returns flattened (no hierarchy) snap_to_grid_nm: snap to different nm grid (does not snap if False) name: Optional name. Over-rides the default imported name. decorator: function to apply over the imported gds. gdsdir: optional GDS directory. kwargs: settings for the imported component (polarization, wavelength ...). """ gdspath = Path(gdsdir) / Path(gdspath) if gdsdir else Path(gdspath) if not gdspath.exists(): raise FileNotFoundError(f"No file {gdspath!r} found") metadata_filepath = gdspath.with_suffix(".yml") gdsii_lib = gdspy.GdsLibrary() gdsii_lib.read_gds(str(gdspath)) top_level_cells = gdsii_lib.top_level() cellnames = [c.name for c in top_level_cells] if cellname is not None: if cellname not in gdsii_lib.cells: raise ValueError( f"cell {cellname} is not in file {gdspath} with cells {cellnames}" ) topcell = gdsii_lib.cells[cellname] elif cellname is None and len(top_level_cells) == 1: topcell = top_level_cells[0] elif cellname is None and len(top_level_cells) > 1: raise ValueError( f"import_gds() There are multiple top-level cells in {gdspath!r}, " f"you must specify `cellname` to select of one of them among {cellnames}" ) if name: if name in CACHE or name in CACHE_IMPORTED_CELLS: raise ValueError( f"name = {name!r} already on cache. " "Please, choose a different name or set name = None. ") else: topcell.name = name if flatten: component = Component(name=name or cellname or cellnames[0]) polygons = topcell.get_polygons(by_spec=True) for layer_in_gds, polys in polygons.items(): component.add_polygon(polys, layer=layer_in_gds) component = avoid_duplicated_cells(component) else: D_list = [] cell_to_device = {} for c in gdsii_lib.cells.values(): D = Component(name=c.name) D.polygons = c.polygons D.references = c.references D.name = c.name for label in c.labels: rotation = label.rotation if rotation is None: rotation = 0 label_ref = D.add_label( text=label.text, position=np.asfarray(label.position), magnification=label.magnification, rotation=rotation * 180 / np.pi, layer=(label.layer, label.texttype), ) label_ref.anchor = label.anchor D = avoid_duplicated_cells(D) D.unlock() cell_to_device.update({c: D}) D_list += [D] for D in D_list: # First convert each reference so it points to the right Device converted_references = [] for e in D.references: ref_device = cell_to_device[e.ref_cell] if isinstance(e, gdspy.CellReference): dr = DeviceReference( device=ref_device, origin=e.origin, rotation=e.rotation, magnification=e.magnification, x_reflection=e.x_reflection, ) dr.owner = D converted_references.append(dr) elif isinstance(e, gdspy.CellArray): dr = CellArray( device=ref_device, columns=e.columns, rows=e.rows, spacing=e.spacing, origin=e.origin, rotation=e.rotation, magnification=e.magnification, x_reflection=e.x_reflection, ) dr.owner = D converted_references.append(dr) D.references = converted_references # Next convert each Polygon # temp_polygons = list(D.polygons) # D.polygons = [] # for p in temp_polygons: # D.add_polygon(p) # Next convert each Polygon temp_polygons = list(D.polygons) D.polygons = [] for p in temp_polygons: if snap_to_grid_nm: points_on_grid = snap_to_grid(p.polygons[0], nm=snap_to_grid_nm) p = gdspy.Polygon(points_on_grid, layer=p.layers[0], datatype=p.datatypes[0]) D.add_polygon(p) component = cell_to_device[topcell] cast(Component, component) name = name or component.name component.name = name if metadata_filepath.exists(): logger.info(f"Read YAML metadata from {metadata_filepath}") metadata = OmegaConf.load(metadata_filepath) for port_name, port in metadata.ports.items(): if port_name not in component.ports: component.add_port( name=port_name, midpoint=port.midpoint, width=port.width, orientation=port.orientation, layer=port.layer, port_type=port.port_type, ) component.info = metadata.info component.info.update(**kwargs) component.name = name component.info.name = name if decorator: component_new = decorator(component) component = component_new or component if flatten: component.flatten() component.lock() return component
def bench_gdspy(output=None): p = gdspy.Polygon(pts()).fracture(10) if output: c = gdspy.Cell("MAIN", exclude_from_current=True) c.add(p) c.write_svg(output, 50)