def test_hobby4(target): cell = gdspy.Cell('test', True) c = gdspy.Curve(0, 3, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=10)) c = gdspy.Curve(0, 3, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], t_in=[2, 1, 1, 1, 1], t_out=[1, 1, 1, 1, 2], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=11)) c = gdspy.Curve(0, 3, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], t_in=[1, 1, 2, 1, 1], t_out=[1, 2, 1, 1, 1], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=12)) c = gdspy.Curve(0, 3, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], angles=[numpy.pi * 3 / 4.0, None, None, None, -numpy.pi * 3 / 4.0], t_in=[2, 1, 1, 1, 1], t_out=[1, 1, 1, 1, 2], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=13)) c = gdspy.Curve(0, 3, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], angles=[numpy.pi * 3 / 4.0, None, None, None, -numpy.pi * 3 / 4.0], t_in=[1, 1, 1, 1, 1], t_out=[1, 1, 1, 1, 1], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=14)) assertsame(target['Hobby4'], cell)
def bench_gdspy(output=None): r = 0.15 c1 = gdspy.Curve(1 / 2 - r, -(3**0.5) / 6, 1e-3) c1.arc(r, numpy.pi, numpy.pi * 2 / 3) c1.l((1 - 2 * r) * numpy.exp(1j * numpy.pi * 2 / 3)) c1.arc(r, -numpy.pi / 3, -numpy.pi * 2 / 3) c1.l((1 - 2 * r) * numpy.exp(-1j * numpy.pi * 2 / 3)) c1.arc(r, numpy.pi / 3, 0) p1 = gdspy.Polygon(c1.get_points()) z0 = 2 * r * numpy.exp(-1j * numpy.pi / 6) z1 = r * numpy.exp(1j * numpy.pi / 6) z2 = r * numpy.exp(1j * numpy.pi * 5 / 6) z3 = 2 * r * numpy.exp(-1j * numpy.pi * 5 / 6) c2 = gdspy.Curve(0, -r, 1e-3) c2.I( [ (z0.real, z0.imag), (z1.real, z1.imag), (0, 2 * r), (z2.real, z2.imag), (z3.real, z3.imag), ], cycle=True, ) p2 = gdspy.Polygon(c2.get_points(), layer=1) if output: cell = gdspy.Cell("MAIN", exclude_from_current=True) cell.add([p1, p2]) cell.write_svg(output, 300)
def test_hobby3(target): cell = gdspy.Cell("test", True) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)]) cell.add(gdspy.Polygon(c.get_points(), layer=1)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], t_in=2) cell.add(gdspy.Polygon(c.get_points(), layer=2)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], t_out=2) cell.add(gdspy.Polygon(c.get_points(), layer=3)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], t_in=2, t_out=2) cell.add(gdspy.Polygon(c.get_points(), layer=4)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], t_in=[2, 1, 1, 1, 1], t_out=[1, 1, 1, 1, 2]) cell.add(gdspy.Polygon(c.get_points(), layer=5)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], t_in=[1, 1, 2, 1, 1], t_out=[1, 2, 1, 1, 1]) cell.add(gdspy.Polygon(c.get_points(), layer=6)) assertsame(target["Hobby3"], cell)
def test_hobby2(target): cell = gdspy.Cell("test", True) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)]) cell.add(gdspy.Polygon(c.get_points(), layer=1)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], curl_start=0) cell.add(gdspy.Polygon(c.get_points(), layer=2)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], curl_end=0) cell.add(gdspy.Polygon(c.get_points(), layer=3)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 2), (2, 1), (3, 2), (4, 0)], curl_start=0, curl_end=0) cell.add(gdspy.Polygon(c.get_points(), layer=4)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i( [(1, 2), (2, 1), (3, 2), (4, 0)], angles=[numpy.pi / 2, None, None, None, -numpy.pi / 2], curl_start=0, curl_end=0, ) cell.add(gdspy.Polygon(c.get_points(), layer=5)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i( [(1, 2), (2, 1), (3, 2), (4, 0)], angles=[None, 0, None, 0, None], curl_start=0, curl_end=1, ) cell.add(gdspy.Polygon(c.get_points(), layer=6)) assertsame(target["Hobby2"], cell)
def _render_text(text, size=None, position=(0, 0), font_prop=None, tolerance=0.1): """This function is copied from https://gdspy.readthedocs.io/en/stable/gettingstarted.html#using-system-fonts""" path = TextPath(position, text, size=size, prop=font_prop) polys = [] xmax = position[0] for points, code in path.iter_segments(): if code == path.MOVETO: c = gdspy.Curve(*points, tolerance=tolerance) elif code == path.LINETO: c.L(*points) elif code == path.CURVE3: c.Q(*points) elif code == path.CURVE4: c.C(*points) elif code == path.CLOSEPOLY: poly = c.get_points() if poly.size > 0: if poly[:, 0].min() < xmax: i = len(polys) - 1 while i >= 0: if gdspy.inside(poly[:1], [polys[i]], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean( [p], [poly], "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
def render_text(text, size=None, position=(0, 0), font_prop=None, tolerance=0.1): path = TextPath(position, text, size=size, prop=font_prop) polys = [] xmax = position[0] for points, code in path.iter_segments(): if code == path.MOVETO: c = gdspy.Curve(*points, tolerance=tolerance) elif code == path.LINETO: c.L(*points) elif code == path.CURVE3: c.Q(*points) elif code == path.CURVE4: c.C(*points) elif code == path.CLOSEPOLY: poly = c.get_points() if poly.size > 0: if poly[:, 0].min() < xmax: i = len(polys) - 1 while i >= 0: if gdspy.inside(poly[:1], [polys[i]], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean( [p], [poly], "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
def DrawLauncher( LauncherCellName = 'IndependentLauncher', LineWidth = 10, #resonator line width (resist spacing) SpaceWidth = 6, #spacing between resonator and grounding plane (resist) BigWidth = 96, #maximum launcher-ground spacing LauncherWidth = 352, #total launcher width (pad+spacings) layer = 2): """ This function returns a launcher cell, e.g. for feedlines and biadlines. The cell origin is defined at the connection with the line element. """ Launcher = gds.Cell(LauncherCellName, exclude_from_current=True) LauncherCurve = gds.Curve(0,LineWidth/2).L( 0, SpaceWidth+(LineWidth/2), -2*BigWidth, LauncherWidth/2, -5*BigWidth, LauncherWidth/2, -5*BigWidth, -LauncherWidth/2, -2*BigWidth, -LauncherWidth/2, 0, -SpaceWidth-(LineWidth/2), 0, -LineWidth/2, -2*BigWidth, -(LauncherWidth/2) + BigWidth, -2*BigWidth, -(LauncherWidth/2) + BigWidth, -4*BigWidth, -(LauncherWidth/2) + BigWidth, -4*BigWidth, (LauncherWidth/2) - BigWidth, -2*BigWidth, (LauncherWidth/2) - BigWidth) Launcher.add(gds.Polygon(LauncherCurve.get_points(),layer=layer)) return Launcher
def DrawJosephsonJunction( JosephsonJunctionCellName = 'IndependentJosephsonJunction', LineWidth = 2, #width of line connected to the junction (i.e. basis' length) FingerWidth = 0.36, # FingerLength = 1, # TaperWidth = 0.5, #Width of the basis BridgeWidth = 0.14, #Spacing left intentionally after the finger. layer = 2): """ This function returns a Josephson junction cell. The cell origin is defined at the connection with the line. |\__ | __| |/ """ JosephsonJunction = gds.Cell(JosephsonJunctionCellName, exclude_from_current=True) JosephsonJunctionCurve = gds.Curve(0, LineWidth/2).L( TaperWidth, FingerWidth/2, TaperWidth+FingerLength, FingerWidth/2, TaperWidth+FingerLength, -FingerWidth/2, TaperWidth, -FingerWidth/2, 0, -LineWidth/2) JosephsonJunction.add(gds.Polygon(JosephsonJunctionCurve.get_points(),layer=layer)) return JosephsonJunction
def qubitLead(conf: DefaultConfig, test=False): sizes = conf.qubitLeadSizes if test: sizes[2][1] = conf.qubitTestSize gaps = conf.qubitLeadGaps layers = conf.qubitLeadLayers curve = gdspy.Curve(0) for i, size in enumerate(sizes): w1, h1 = size if i == 0: dx = dy = w1 / 2 curve.c(dx, 0, dx, 0, dx, dy).v(h1 - dy) else: dx, dy = (w1 - sizes[i - 1][0]) / 2, gaps[i - 1] curve.c(0, dy / 2, dx, dy / 2, dx, dy).v(h1) curve.h(-sizes[-1][0] / 2) halfLead = gdspy.Polygon(curve.get_points()) lead = join([halfLead, copy(halfLead).mirror([0, 1])]) slice1 = sizes[0][1] + gaps[0] slice2 = slice1 + conf.qubitLeadOverlap coarseLead = gdspy.slice(lead, slice1, 1, layer=layers)[1] fineLead = gdspy.slice(lead, slice2, 1, layer=layers)[0] return coarseLead, fineLead
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]
ellipse = gdspy.Round((4, 0), [1, 2], tolerance=1e-4) # Circular arc example arc = gdspy.Round( (2, 4), 2, inner_radius=1, initial_angle=-0.2 * numpy.pi, final_angle=1.2 * numpy.pi, tolerance=0.01, ) draw(gdspy.Cell("circles").add([circle, ellipse, arc])) # Curves # Construct a curve made of a sequence of line segments c1 = gdspy.Curve(0, 0).L(1, 0, 2, 1, 2, 2, 0, 2) p1 = gdspy.Polygon(c1.get_points()) # Construct another curve using relative coordinates c2 = gdspy.Curve(3, 1).l(1, 0, 2, 1, 2, 2, 0, 2) p2 = gdspy.Polygon(c2.get_points()) draw(gdspy.Cell("curves").add([p1, p2])) # Curves 1 # Use complex numbers to facilitate writing polar coordinates c3 = gdspy.Curve(0, 2).l(4 * numpy.exp(1j * numpy.pi / 6)) # Elliptical arcs have syntax similar to gdspy.Round c3.arc((4, 2), 0.5 * numpy.pi, -0.5 * numpy.pi) p3 = gdspy.Polygon(c3.get_points()) draw(gdspy.Cell("curves_1").add(p3))
def get_glyph(lib, letter, layer=0): """ Get a block reference to the given letter """ if not isinstance(letter, str) and len(letter) == 1: raise TypeError( f"Letter must be a string of length 1. Got: ({letter}).") if getattr(get_glyph, "cache", None) is None or get_glyph.doc is not lib: get_glyph.cache = {} get_glyph.doc = lib if (letter, layer) in get_glyph.cache: return get_glyph.cache[(letter, layer)] name = f"char_{layer}_0x{ord(letter):02x}" block = lib.new_cell(name) # Load control points from font file font = get_font() font.load_char(letter, FT_LOAD_FLAGS['FT_LOAD_NO_BITMAP']) glyph = font.glyph outline = glyph.outline points = np.array(outline.points, dtype=float) / font.height 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: curve.C(*points[cpoint + 1:cpoint + 3].flatten(), *points[start]) 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 = Vector(*points[cpoint + 1]) p2 = Vector(*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, *p2) 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 = Vector(*points[end]) p1 = Vector(*points[cpoint]) p2 = Vector(*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 = Vector(*points[cpoint - 1]) p1 = Vector(*points[cpoint]) p2 = Vector(*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, *p2) cpoint += 1 else: raise ValueError( "Sequential control points not valid for cubic splines." ) polylines.append(gdspy.Polygon(curve.get_points(), layer=layer)) # Construct the letter letter_polyline = polylines[0] for polyline in polylines[1:]: letter_polyline = gdspy.boolean(letter_polyline, polyline, "xor", layer=layer) block.add(letter_polyline) # Cache the return value and return it get_glyph.cache[(letter, layer)] = (block, glyph.advance.x / font.height) return get_glyph.cache[(letter, layer)]
rp.segment((15, 20)) rp.scale(0.7) rp.turn(10, "r") rp.transform((10, 0), -1.5, 1.5, x_reflection=True) rp.segment((10, -10), relative=True) rp.rotate(-0.7) rp.translate(50, 30) rp.segment((-10, 0)) cell.add(rp) ### Curve cell = lib.new_cell("Hobby1") 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))
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 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 draw_wafer(lib, diameter=150_000, flat_size=57_500, layer=0): # First we need to calculate the properties of the chord chord_angle = 2 * math.asin(flat_size / diameter) center = Vector((diameter / 2, diameter / 2, 0)) # Then, calculate the start and stop angles for an arc initial_angle = -chord_angle / 2 + 3 * math.pi / 2 final_angle = chord_angle / 2 - math.pi / 2 # Find the positions of the start and the end start_vect = Vector((diameter, diameter / 2, 0)) start_vect = gen_rotate_matrix(math.degrees(initial_angle), center) @ start_vect curve = gdspy.Curve(*start_vect.xy, tolerance=10) curve.arc(diameter / 2, initial_angle, final_angle) return gdspy.Polygon(curve.get_points(), layer=layer) if __name__ == "__main__": doc = gdspy.GdsLibrary() mark = elionix_mark(doc) elionix_4block(doc, mark) render_text.render_to_block(doc, "NW200311_0001") arrow_cell = gdspy.Cell("arrow") arrow_cell.add(arrow(Vector((0, 0, 0)))) doc.add(arrow_cell) die_marker(doc, name="die_marker") wire_section(doc, "a") draw_wafer(doc)
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]