def make_inner_star(self): """This function creates the coordinates for the pins """ p = self.p # Extracting coordinated from the user input values coords = self.make_coordinates_trap() coords1 = self.make_resonator_coordinates() trap_0 = draw.Polygon(coords) traps = self.make_rotation(trap_0, 5) # Define the final structure based on use input if (p.number_of_connectors) == 0: traps = traps[2] elif (p.number_of_connectors) == 1: traps = draw.union(traps[0], traps[2]) elif (p.number_of_connectors) == 2: traps = draw.union(traps[0], traps[1], traps[2]) elif (p.number_of_connectors) == 3: traps = draw.union(traps[0], traps[1], traps[2], traps[3]) elif (p.number_of_connectors) == 4: traps = draw.union(traps[0], traps[1], traps[2], traps[3], traps[4]) # Subtract from circle circle = self.make_circle() total1 = draw.subtract(circle, traps) # create rectangular connectors to junction pockets = self.make_pockets() rect1 = draw.rectangle(pockets[2], pockets[3]) rect1 = draw.translate(rect1, xoff=coords1[0][0] * 1.1, yoff=p.radius) rect1 = draw.rotate(rect1, p.rotation_cpl1, origin=(0, 0)) rect2 = draw.rectangle(pockets[2], pockets[3]) rect2 = draw.translate(rect2, xoff=coords1[1][0] * 1.1, yoff=p.radius) rect2 = draw.rotate(rect2, p.rotation_cpl1, origin=(0, 0)) #junction jjunction = draw.LineString([[0, 0], [0, coords[1][0]]]) jjunction = draw.translate(jjunction, yoff=(1.15 * (p.radius))) jjunction = draw.rotate(jjunction, p.rotation_cpl1, origin=(0, 0)) # Add connection to the junction total = draw.union(total1, rect1, rect2) objects = [total, jjunction] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [total, jjunction] = objects self.add_qgeometry('poly', {'circle_inner': total}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip) self.add_qgeometry('junction', {'poly': jjunction}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, width=p.junc_h)
def make(self): """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # draw the lower pad as a rectangle JJ_pad_lower = draw.rectangle(p.JJ_pad_lower_width, p.JJ_pad_lower_height, p.JJ_pad_lower_pos_x, p.JJ_pad_lower_pos_y) finger_lower = draw.rectangle( p.finger_lower_width, p.finger_lower_height, p.JJ_pad_lower_pos_x, 0.5 * (p.JJ_pad_lower_height + p.finger_lower_height)) # merge the lower pad and the finger into a single object design = draw.union(JJ_pad_lower, finger_lower) # copy the pad/finger and rotate it by 90 degrees design2 = draw.rotate(design, 90.0) # translate the second pad/finger to achieve the desired extension # for a Manhattan-like configuration design2 = draw.translate( design2, 0.5 * (p.JJ_pad_lower_height + p.finger_lower_height) - 0.5 * p.finger_lower_width - p.extension, 0.5 * (p.JJ_pad_lower_height + p.finger_lower_height) - 0.5 * p.finger_lower_width - p.extension) # now translate the second pad/finger to achieve the desired offset # from the first pad/finger design2 = draw.translate(design2, p.extension + p.finger_lower_width + p.offset) final_design = draw.union(design, design2) second_metal = draw.rectangle( p.second_metal_width, p.second_metal_length, p.JJ_pad_lower_pos_x + p.offset + 0.5 * p.finger_lower_width, 0.5 * p.JJ_pad_lower_height + p.finger_lower_height - 0.5 * p.second_metal_length) # translate everything so that the bottom left corner of the lower # pad is at the origin final_design = draw.translate(final_design, 0.5 * p.JJ_pad_lower_width, 0.5 * p.JJ_pad_lower_height) second_metal = draw.translate(second_metal, 0.5 * p.JJ_pad_lower_width, 0.5 * p.JJ_pad_lower_height) # now translate so that the bottom left corner is at the # user-defined coordinates (pos_x, pos_y) final_design = draw.translate(final_design, p.pos_x, p.pos_y) second_metal = draw.translate(second_metal, p.pos_x, p.pos_y) geom1 = {'design': final_design} self.add_qgeometry('poly', geom1, layer=p.layer, subtract=False) geom2 = {'design': second_metal} self.add_qgeometry('poly', geom2, layer=2.0, subtract=False)
def test_qgeometry_q_element_delete_component_id(self): """Test delete_component_id in QGeometryTables class in element_handler.py.""" design = designs.DesignPlanar() qgt = QGeometryTables(design) qgt.clear_all_tables() transmon_pocket = TransmonPocket(design, 'my_id') transmon_pocket.make() transmon_pocket.get_template_options(design) a_linestring = draw.LineString([[0, 0], [0, 1]]) a_poly = draw.rectangle(2, 2, 0, 0) qgt.add_qgeometry('path', 'my_id', {'n_sprial': a_linestring}, width=4000) qgt.add_qgeometry('poly', 'my_id', {'n_spira_etch': a_poly}, subtract=True) self.assertEqual(len(qgt.tables['path']), 1) self.assertEqual(len(qgt.tables['poly']), 1) qgt.delete_component_id('my_id') self.assertEqual(len(qgt.tables['path']), 0) self.assertEqual(len(qgt.tables['poly']), 0)
def test_qgeometry_q_element_get_component(self): """Test get_component in QGeometryTables class in element_handler.py.""" design = designs.DesignPlanar() qgt = QGeometryTables(design) qgt.clear_all_tables() TransmonPocket(design, 'Q1') rect = draw.rectangle(500, 300, 0, 0) geom = {'my_polygon': rect} qgt.add_qgeometry('poly', 'Q1', geom) # success results actual = qgt.get_component('Q1') self.assertEqual(len(actual), 3) self.assertTrue(isinstance(actual['path'], GeoDataFrame)) self.assertTrue(isinstance(actual['poly'], GeoDataFrame)) self.assertTrue(isinstance(actual['junction'], GeoDataFrame)) # failure results actual = qgt.get_component('not-real') self.assertEqual(len(actual), 3) self.assertEqual(actual['path'], None) self.assertEqual(actual['poly'], None) self.assertEqual(actual['junction'], None)
def make(self): """calculates the geometries of the QComponent""" rect = draw.rectangle(0.5, 0.1, 0, 0) #width, height, pos_x, pos_y # add_geometry() expects shapely, thus the use of drawn module above self.add_qgeometry('poly', {'my_polygon': rect}, layer=1, subtract=False) self.add_pin('in', rect.exterior.coords[:-3:-1], 0.1) #name, tangent, width
def make(self): """calculates the geometries of the QComponent""" p = self.parse_options() # short-handle alias. Options interpreter rect = draw.rectangle(p.width, p.height, p.pos_x, p.pos_y) self.add_qgeometry('poly', {'my_polygon': rect}, layer=p.layer, subtract=False) self.add_pin('in', rect.exterior.coords[:-3:-1], p.height)
def make(self): """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # draw the lower pad as a rectangle JJ_pad_lower = draw.rectangle(p.JJ_pad_lower_width, p.JJ_pad_lower_height, p.JJ_pad_lower_pos_x, p.JJ_pad_lower_pos_y) finger_lower = draw.rectangle( p.finger_lower_width, p.finger_lower_height, p.JJ_pad_lower_pos_x, 0.5 * (p.JJ_pad_lower_height + p.finger_lower_height)) # fudge factor to merge the two options finger_lower = draw.translate(finger_lower, 0.0, -0.0001) # merge the lower pad and the finger into a single object design = draw.union(JJ_pad_lower, finger_lower) # copy the pad/finger and rotate it by 90 degrees design2 = draw.rotate(design, 90.0) # translate the second pad/finger to achieve the desired extension design2 = draw.translate( design2, 0.5 * (p.JJ_pad_lower_height + p.finger_lower_height) - 0.5 * p.finger_lower_width - p.extension, 0.5 * (p.JJ_pad_lower_height + p.finger_lower_height) - 0.5 * p.finger_lower_width - p.extension) final_design = draw.union(design, design2) # translate the final design so that the bottom left # corner of the lower pad is at the origin final_design = draw.translate(final_design, 0.5 * p.JJ_pad_lower_width, 0.5 * p.JJ_pad_lower_height) # now translate so that the design is centered on the # user-defined coordinates (x_pos, y_pos) final_design = draw.translate(final_design, p.x_pos, p.y_pos) geom = {'design': final_design} self.add_qgeometry('poly', geom, layer=p.layer, subtract=False)
def make(self): """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # EDIT HERE - Replace the following with your code # Create some raw geometry # Use autocompletion for the `draw.` module (use tab key) rect = draw.rectangle(p.width, p.height, p.pos_x, p.pos_y) rect = draw.rotate(rect, p.rotation) geom = {'my_polygon': rect} self.add_qgeometry('poly', geom, layer=p.layer, subtract=False)
def test_qgeometry_q_element_clear_all_tables(self): """Test clear_all_tables in QGeometryTables class in element_handler.py.""" design = designs.DesignPlanar() qgt = QGeometryTables(design) qgt.clear_all_tables() # add something to the tables to check for after clear a_poly = draw.rectangle(2, 2, 0, 0) qgt.add_qgeometry('poly', 'my_id', dict(cl_metal=a_poly)) qgt.clear_all_tables() self.assertEqual(len(qgt.tables['poly'].geometry), 0)
def make_pocket(self): """Makes standard transmon in a pocket.""" # self.p allows us to directly access parsed values (string -> numbers) form the user option p = self.p # since we will reuse these options, parse them once and define them as variables pad_width = p.pad_width pad_height = p.pad_height pad_gap = p.pad_gap # make the pads as rectangles (shapely polygons) pad = draw.rectangle(pad_width, pad_height) pad_top = draw.translate(pad, 0, +(pad_height + pad_gap) / 2.) pad_bot = draw.translate(pad, 0, -(pad_height + pad_gap) / 2.) rect_jj = draw.LineString([(0, -pad_gap / 2), (0, +pad_gap / 2)]) # the draw.rectangle representing the josephson junction # rect_jj = draw.rectangle(p.inductor_width, pad_gap) rect_pk = draw.rectangle(p.pocket_width, p.pocket_height) # Rotate and translate all qgeometry as needed. # Done with utility functions in Metal 'draw_utility' for easy rotation/translation # NOTE: Should modify so rotate/translate accepts qgeometry, would allow for # smoother implementation. polys = [rect_jj, pad_top, pad_bot, rect_pk] polys = draw.rotate(polys, p.orientation, origin=(0, 0)) polys = draw.translate(polys, p.pos_x, p.pos_y) [rect_jj, pad_top, pad_bot, rect_pk] = polys # Use the geometry to create Metal qgeometry self.add_qgeometry('poly', dict(pad_top=pad_top, pad_bot=pad_bot)) self.add_qgeometry('poly', dict(rect_pk=rect_pk), subtract=True) # self.add_qgeometry('poly', dict( # rect_jj=rect_jj), helper=True) self.add_qgeometry('junction', dict(rect_jj=rect_jj), width=p.inductor_width)
def make(self): """The make function implements the logic that creates the geoemtry (poly, path, etc.) from the qcomponent.options dictionary of parameters, and the adds them to the design, using qcomponent.add_qgeometry(...), adding in extra needed information, such as layer, subtract, etc.""" p = self.p # p for parsed parameters. Access to the parsed options. # create the geometry rect = draw.rectangle(p.width, p.height, p.pos_x, p.pos_y) rec1 = draw.rectangle(p.inner.width, p.inner.height, p.pos_x + p.inner.offset_x, p.pos_y + p.inner.offset_y) rec1 = draw.rotate(rec1, p.inner.orientation) rect = draw.subtract(rect, rec1) rect = draw.rotate(rect, p.orientation) # add qgeometry self.add_qgeometry('poly', {'rect': rect}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip)
def make_outer_circle(self): """This function draws the outer circle. """ p = self.p coords = self.make_coordinates_trap() circle_outer = draw.Point(0, 0).buffer( p.radius * (1 + (p.connector_length / p.radius)), resolution=int(p.resolution), cap_style=getattr(CAP_STYLE, p.cap_style)) #Connectors for the ground plane pockets = self.make_pockets() pocket_z = draw.rectangle(pockets[0] * 1.4, pockets[1]) pocket_z = draw.translate(pocket_z, xoff=0, yoff=(coords[2][1])) pockets_ground = self.make_rotation(pocket_z, 5) if (p.number_of_connectors) == 0: circle_outer = draw.union(circle_outer, pockets_ground[2]) elif (p.number_of_connectors) == 1: circle_outer = draw.union(circle_outer, pockets_ground[0], pockets_ground[2]) elif (p.number_of_connectors) == 2: circle_outer = draw.union(circle_outer, pockets_ground[0], pockets_ground[1], pockets_ground[2]) elif (p.number_of_connectors) == 3: circle_outer = draw.union(circle_outer, pockets_ground[0], pockets_ground[1], pockets_ground[2], pockets_ground[3]) elif (p.number_of_connectors) == 4: circle_outer = draw.union(circle_outer, pockets_ground[0], pockets_ground[1], pockets_ground[2], pockets_ground[3], pockets_ground[4]) ################################################################## # Add geometry and Qpin connections objects = [circle_outer] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [circle_outer] = objects self.add_qgeometry('poly', {'circle_outer': circle_outer}, subtract=True, helper=p.helper, layer=p.layer, chip=p.chip)
def make_readout_resonator(self): """This function draws the readout resonator. Adds pins. And adds the drawn geometry to qgeomtery table. """ p = self.p coords_readout = self.make_readout_coordinates() circle = self.make_circle() pockets = self.make_pockets() coords = self.make_coordinates_trap() # Make the readout resonator with the pocket contact_rdout = draw.Polygon(coords_readout) contact_rdout = draw.subtract(circle, contact_rdout) contact_rdout = self.make_rotation(contact_rdout, 1) # Define contacts pocket0 = draw.rectangle(pockets[0], pockets[1]) pocket0 = draw.translate(pocket0, xoff=0, yoff=(coords[3][1])) pocket0 = self.make_rotation(pocket0, 1) # Join the coupler and contact contact_rdout = draw.union(contact_rdout[0], pocket0[0]) pins = self.make_pin_coordinates() pins_rdout = self.make_rotation(pins, 2) objects = [contact_rdout, pins_rdout] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [contact_rdout, pins_rdout] = objects ################################################################## # Add geometry and Qpin connections self.add_qgeometry('poly', {'contact_rdout': contact_rdout}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip) self.add_pin('pin_rdout', pins_rdout[0].coords, width=p.cpw_width, input_as_norm=True)
def make(self): """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # draw the lower pad as a rectangle plate1 = draw.rectangle(p.plate1_width, p.plate1_height, p.plate1_pos_x, p.plate1_pos_y) segment_a = draw.rectangle(p.segment_a_length, p.segment_a_width, 0.5 * (p.plate1_width + p.segment_a_length), 0.5 * (p.squid_gap + p.segment_a_width)) segment_a_lower = draw.translate( segment_a, 0.0, -1.0 * (p.squid_gap + p.segment_a_width)) segment_b = draw.rectangle( p.segment_b_length, p.segment_b_width, 0.5 * (p.plate1_width + p.segment_b_length) + p.JJ_gap + p.segment_a_length, 0.5 * (p.squid_gap + p.segment_b_width)) segment_b_lower = draw.translate( segment_b, 0.0, -1.0 * (p.squid_gap + p.segment_b_width)) segment_c = draw.rectangle( p.segment_c_width, p.squid_gap + p.segment_a_width + p.segment_b_width, 0.5 * (p.plate1_width + p.segment_c_width) + p.segment_a_length + p.segment_b_length + p.JJ_gap, p.plate1_pos_y) segment_d = draw.rectangle( p.segment_d_length, p.segment_d_width, 0.5 * (p.plate1_width + p.segment_d_length) + p.segment_a_length + p.segment_b_length + p.JJ_gap + p.segment_c_width, p.plate1_pos_y) plate2 = draw.rectangle( p.plate2_width, p.plate2_height, 0.5 * (p.plate1_width + p.plate2_width) + p.segment_a_length + p.JJ_gap + p.segment_b_length + p.segment_c_width + p.segment_d_length, p.plate1_pos_y) design1 = draw.union(plate1, segment_a, segment_a_lower, segment_b, segment_b_lower, segment_c, segment_d, plate2) # now translate and rotate the final structure design1 = draw.rotate(design1, p.orientation, origin=(0, 0)) design1 = draw.translate(design1, p.pos_x, p.pos_y) geom = {'design': design1} self.add_qgeometry('poly', geom, layer=p.layer, subtract=False)
def test_qgeometry_q_element_add_qgeometry(self): """Test add_qgeometry in QGeometryTables class in element_handler.py.""" design = designs.DesignPlanar() qgt = QGeometryTables(design) qgt.clear_all_tables() a_poly = draw.rectangle(2, 2, 0, 0) qgt.add_qgeometry('poly', 'my_id', dict(cl_metal=a_poly)) table = qgt.tables self.assertTrue('poly' in table) self.assertEqual(table['poly']['component'][0], 'my_id') self.assertEqual(table['poly']['name'][0], 'cl_metal') self.assertEqual(table['poly']['geometry'][0], a_poly) self.assertEqual(table['poly']['layer'][0], 1) self.assertEqual(table['poly']['subtract'][0], False) self.assertEqual(table['poly']['helper'][0], False) self.assertEqual(table['poly']['chip'][0], 'main') self.assertEqual(str(table['poly']['fillet'][0]), str(np.nan))
def test_qgeometry_get_all_unique_layers(self): """Test get_all_unique_layers functionality in elment_handler.py.""" design = designs.DesignPlanar() qgt = QGeometryTables(design) qgt.clear_all_tables() transmon_pocket = TransmonPocket(design, 'my_id') transmon_pocket.make() transmon_pocket.get_template_options(design) a_linestring = draw.LineString([[0, 0], [0, 1]]) a_poly = draw.rectangle(2, 2, 0, 0) qgt.add_qgeometry('path', 'my_id', {'n_sprial': a_linestring}, width=4000) qgt.add_qgeometry('poly', 'my_id', {'n_spira_etch': a_poly}, subtract=True) self.assertEqual(qgt.get_all_unique_layers('main'), [1]) self.assertEqual(qgt.get_all_unique_layers('fake'), [])
def test_renderer_get_chip_names(self): """Test functionality of get_chip_names in gds_renderer.py.""" design = designs.DesignPlanar() renderer = QGDSRenderer(design) qgt = QGeometryTables(design) qgt.clear_all_tables() transmon_pocket_1 = TransmonPocket(design, 'my_id') transmon_pocket_1.make() transmon_pocket_1.get_template_options(design) a_linestring = draw.LineString([[0, 0], [0, 1]]) a_poly = draw.rectangle(2, 2, 0, 0) qgt.add_qgeometry('path', 'my_id', {'n_sprial': a_linestring}, width=4000) qgt.add_qgeometry('poly', 'my_id', {'n_spira_etch': a_poly}, subtract=True) result = renderer._get_chip_names() self.assertEqual(result, {'main': {}})
def make_connection_pad(self, name: str): """Makes n individual connector. Args: name (str) : Name of the connector """ # self.p allows us to directly access parsed values (string -> numbers) form the user option p = self.p pc = self.p.connection_pads[name] # parser on connector options # define commonly used variables once cpw_width = pc.cpw_width cpw_extend = pc.cpw_extend pad_width = pc.pad_width pad_height = pc.pad_height pad_cpw_shift = pc.pad_cpw_shift pocket_rise = pc.pocket_rise pocket_extent = pc.pocket_extent loc_W = float(pc.loc_W) loc_W, loc_H = float(pc.loc_W), float(pc.loc_H) if float(loc_W) not in [-1., +1., 0] or float(loc_H) not in [-1., +1.]: self.logger.info( 'Warning: Did you mean to define a transmon qubit with loc_W and' ' loc_H that are not +1, -1, or 0? Are you sure you want to do this?' ) # Define the geometry # Connector pad if float(loc_W) != 0: connector_pad = draw.rectangle(pad_width, pad_height, -pad_width / 2, pad_height / 2) # Connector CPW wire connector_wire_path = draw.wkt.loads(f"""LINESTRING (\ 0 {pad_cpw_shift+cpw_width/2}, \ {pc.pad_cpw_extent} {pad_cpw_shift+cpw_width/2}, \ {(p.pocket_width-p.pad_width)/2-pocket_extent} {pad_cpw_shift+cpw_width/2+pocket_rise}, \ {(p.pocket_width-p.pad_width)/2+cpw_extend} {pad_cpw_shift+cpw_width/2+pocket_rise}\ )""") else: connector_pad = draw.rectangle(pad_width, pad_height, 0, pad_height / 2) connector_wire_path = draw.LineString( [[0, pad_height], [ 0, (p.pocket_width / 2 - p.pad_height - p.pad_gap / 2 - pc.pad_gap) + cpw_extend ]]) # Position the connector, rotate and translate objects = [connector_pad, connector_wire_path] if loc_W == 0: loc_Woff = 1 else: loc_Woff = loc_W objects = draw.scale(objects, loc_Woff, loc_H, origin=(0, 0)) objects = draw.translate( objects, loc_W * (p.pad_width) / 2., loc_H * (p.pad_height + p.pad_gap / 2 + pc.pad_gap)) objects = draw.rotate_position(objects, p.orientation, [p.pos_x, p.pos_y]) [connector_pad, connector_wire_path] = objects self.add_qgeometry('poly', {f'{name}_connector_pad': connector_pad}) self.add_qgeometry('path', {f'{name}_wire': connector_wire_path}, width=cpw_width) self.add_qgeometry('path', {f'{name}_wire_sub': connector_wire_path}, width=cpw_width + 2 * pc.cpw_gap, subtract=True) ############################################################ # add pins points = np.array(connector_wire_path.coords) self.add_pin(name, points=points[-2:], width=cpw_width, input_as_norm=True)
def make(self): """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # draw the lower pad as a rectangle pad_lower = draw.rectangle(p.pad_width, p.pad_height, p.pad_pos_x, p.pad_pos_y) # draw the lower finger as a rectangle finger_lower = draw.rectangle( p.finger_width, p.finger_height, p.pad_pos_x, p.pad_pos_y + 0.49999 * (p.pad_height) + 0.49999 * (p.finger_height)) # draw the Josephson Junction rect_jj = draw.rectangle( p.jj_width, p.finger_space, p.pad_pos_x, 0.5 * (p.pad_height) + p.finger_height + 0.5 * (p.finger_space)) # draw the first comb to the right of the lower finger as a rectangle comb1_lower = draw.rectangle( p.comb_width, (2 * p.finger_height + p.finger_space - p.comb_space_vert), (0.5 * p.finger_width + p.comb_space_hor + 0.5 * p.comb_width), (0.5 * p.pad_height + 0.5 * (p.pad_pos_y + 0.5 * (p.pad_height) + 0.5 * (p.finger_height)))) # draw the second comb to the right of the lower finger by translating the first comb comb2_lower = draw.translate(comb1_lower, 2.0 * (p.comb_space_hor + p.comb_width), 0.0) # draw the first comb to the left of the lower finger comb3_lower = draw.rectangle( p.comb_width, (2 * p.finger_height + p.finger_space - p.comb_space_vert), (-0.5 * p.finger_width - 2.0 * p.comb_space_hor - 1.5 * p.comb_width), (0.5 * p.pad_height + 0.5 * (p.pad_pos_y + 0.5 * (p.pad_height) + 0.5 * (p.finger_height)))) # draw the second comb to the left of the lower finger comb4_lower = draw.translate(comb3_lower, -2.0 * (p.comb_space_hor + p.comb_width), 0.0) coupling_capacitor = draw.rectangle( p.cc_width, p.cc_height, p.pad_pos_x, p.pad_pos_y - 0.5 * (p.pad_height) - p.cc_space - 0.5 * p.cc_height) cc_topleft = draw.rectangle( p.cc_topleft_width, p.cc_topleft_height, p.pad_pos_x - 0.5 * p.pad_width + 0.5 * p.cc_topleft_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height) cc_topright = draw.translate( cc_topleft, p.pad_width - 0.5 * p.cc_topleft_width - 0.5 * p.cc_topright_width, 0.0) # merge the bottom elements bottom = draw.union(pad_lower, finger_lower, comb1_lower, comb2_lower, comb3_lower, comb4_lower) # create the top portion of the comb by translating and rotating # the bottom portion of the comb top = draw.translate(bottom, 0.0, p.pad_height + p.finger_space) top = draw.rotate(top, p.rotation_top_pad) # merge everything into a single design design = draw.union(bottom, top, rect_jj, coupling_capacitor, cc_topleft, cc_topright) # draw the transmon pocket bounding box pocket = draw.rectangle(1.5 * p.pad_width, 5.0 * p.pad_height) # the origin is originally set to the middle of the lower pad. # Let's move it to the center of the JJ. design = draw.translate( design, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) # now translate the final structure according to the user input design = draw.rotate(design, p.rotation, origin=(0, 0)) design = draw.translate(design, p.position_x, p.position_y) pocket = draw.rotate(pocket, p.rotation, origin=(0, 0)) pocket = draw.translate(pocket, p.position_x, p.position_y) geom = {'design': design} geom_pocket = {'pocket': pocket} self.add_qgeometry('poly', geom, layer=p.layer, subtract=False) self.add_qgeometry('poly', geom_pocket, layer=p.layer, subtract=True) ################################################################### # Add Qpin connections for coupling capacitors # define a function that both rotates and translates the # qpin coordinates def qpin_rotate_translate(x): """ This function rotates the coordinates of the three qpins according to the user inputs for "position_x", "position_y" and "rotation". """ y = list(x) z = [0.0, 0.0] z[0] = y[0] * cos(p.rotation * 3.14159 / 180) - y[1] * sin( p.rotation * 3.14159 / 180) z[1] = y[0] * sin(p.rotation * 3.14159 / 180) + y[1] * cos( p.rotation * 3.14159 / 180) z[0] = z[0] + p.position_x z[1] = z[1] + p.position_y x = (z[0], z[1]) return x # Add Qpin connections for the bottom coupling capacitor qp1a = (0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp1b = (0.0, -0.5 * p.pad_height - p.cc_space - p.cc_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) # rotate and translate the qpin coordinates qp1a = qpin_rotate_translate(qp1a) qp1b = qpin_rotate_translate(qp1b) self.add_pin('pin1', points=np.array([qp1a, qp1b]), width=0.01, input_as_norm=True) # Add Qpin connections for top left coupling capacitor qp2a = (p.pad_pos_x - 0.5 * p.pad_width + 0.5 * p.cc_topleft_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp2b = (p.pad_pos_x - 0.5 * p.pad_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp2a = qpin_rotate_translate(qp2a) qp2b = qpin_rotate_translate(qp2b) self.add_pin('pin2', points=np.array([qp2a, qp2b]), width=0.01, input_as_norm=True) # Add Qpin connections for top right coupling capacitor qp3a = (p.pad_pos_x + 0.5 * p.pad_width - 0.5 * p.cc_topleft_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp3b = (p.pad_pos_x + 0.5 * p.pad_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp3a = qpin_rotate_translate(qp3a) qp3b = qpin_rotate_translate(qp3b) self.add_pin('pin3', points=np.array([qp3a, qp3b]), width=0.01, input_as_norm=True)
def make(self): """Build the component.""" p = self.p N = int(p.finger_count) prime_cpw_length = p.cap_width * 2 * N #Primary CPW prime_cpw = draw.LineString([[-prime_cpw_length / 2, 0], [prime_cpw_length / 2, 0]]) #Finger Capacitor cap_box = draw.rectangle(N * p.cap_width + (N - 1) * p.cap_gap, p.cap_gap + 2 * p.cap_width + p.finger_length, 0, 0) make_cut_list = [] make_cut_list.append([0, (p.finger_length) / 2]) make_cut_list.append([(p.cap_width) + (p.cap_gap / 2), (p.finger_length) / 2]) flip = -1 for i in range(1, N): make_cut_list.append([ i * (p.cap_width) + (2 * i - 1) * (p.cap_gap / 2), flip * (p.finger_length) / 2 ]) make_cut_list.append([ (i + 1) * (p.cap_width) + (2 * i + 1) * (p.cap_gap / 2), flip * (p.finger_length) / 2 ]) flip = flip * -1 cap_cut = draw.LineString(make_cut_list).buffer(p.cap_gap / 2, cap_style=2, join_style=2) cap_cut = draw.translate(cap_cut, -(N * p.cap_width + (N - 1) * p.cap_gap) / 2, 0) cap_body = draw.subtract(cap_box, cap_cut) cap_body = draw.translate( cap_body, 0, -p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) / 2) cap_etch = draw.rectangle( N * p.cap_width + (N - 1) * p.cap_gap + 2 * p.second_gap, p.cap_gap + 2 * p.cap_width + p.finger_length + 2 * p.second_gap, 0, -p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) / 2) #Secondary CPW second_cpw_top = draw.LineString([[0, -p.prime_width / 2], [0, -p.cap_distance]]) second_cpw_bottom = draw.LineString( [[ 0, -p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) ], [ 0, -2 * p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) ]]) #Rotate and Translate c_items = [ prime_cpw, second_cpw_top, second_cpw_bottom, cap_body, cap_etch ] c_items = draw.rotate(c_items, p.orientation, origin=(0, 0)) c_items = draw.translate(c_items, p.pos_x, p.pos_y) [prime_cpw, second_cpw_top, second_cpw_bottom, cap_body, cap_etch] = c_items #Add to qgeometry tables self.add_qgeometry('path', {'prime_cpw': prime_cpw}, width=p.prime_width, layer=p.layer) self.add_qgeometry('path', {'prime_cpw_sub': prime_cpw}, width=p.prime_width + 2 * p.prime_gap, subtract=True, layer=p.layer) self.add_qgeometry('path', { 'second_cpw_top': second_cpw_top, 'second_cpw_bottom': second_cpw_bottom }, width=p.second_width, layer=p.layer) self.add_qgeometry('path', { 'second_cpw_top_sub': second_cpw_top, 'second_cpw_bottom_sub': second_cpw_bottom }, width=p.second_width + 2 * p.second_gap, subtract=True, layer=p.layer) self.add_qgeometry('poly', {'cap_body': cap_body}, layer=p.layer) self.add_qgeometry('poly', {'cap_etch': cap_etch}, layer=p.layer, subtract=True) #Add pins prime_pin_list = prime_cpw.coords second_pin_list = second_cpw_bottom.coords self.add_pin('prime_start', points=np.array(prime_pin_list[::-1]), width=p.prime_width, input_as_norm=True) self.add_pin('prime_end', points=np.array(prime_pin_list), width=p.prime_width, input_as_norm=True) self.add_pin('second_end', points=np.array(second_pin_list), width=p.second_width, input_as_norm=True)
def make_pocket(self): """Makes standard transmon in a pocket.""" # self.p allows us to directly access parsed values (string -> numbers) form the user option p = self.p # pcop = self.p.coupled_pads[name] # parser on connector options # since we will reuse these options, parse them once and define them as variables pad_width = p.pad_width pad_height = p.pad_height pad_gap = p.pad_gap coupled_pad_height = p.coupled_pad_height coupled_pad_width = p.coupled_pad_width coupled_pad_gap = p.coupled_pad_gap # make the pads as rectangles (shapely polygons) pad = draw.rectangle(pad_width, pad_height) pad_top = draw.translate(pad, 0, +(pad_height + pad_gap) / 2.) # Here, you make your pads round. Not sharp shape on the left and right sides and also this should be the same for the bottom pad as the top pad. circ_left_top = draw.Point(-pad_width / 2., +(pad_height + pad_gap) / 2.).buffer(pad_height / 2, resolution=16, cap_style=CAP_STYLE.round) circ_right_top = draw.Point(pad_width / 2., +(pad_height + pad_gap) / 2.).buffer(pad_height / 2, resolution=16, cap_style=CAP_STYLE.round) # In here you create the teeth part and then you union them as one with the pad. Teeth only belong to top pad. coupled_pad = draw.rectangle(coupled_pad_width, coupled_pad_height + pad_height) coupler_pad_round = draw.Point(0., (coupled_pad_height + pad_height) / 2).buffer(coupled_pad_width / 2, resolution=16, cap_style=CAP_STYLE.round) coupled_pad = draw.union(coupled_pad, coupler_pad_round) coupled_pad_left = draw.translate( coupled_pad, -(coupled_pad_width / 2. + coupled_pad_gap / 2.), +coupled_pad_height / 2. + pad_height + pad_gap / 2. - pad_height / 2) coupled_pad_right = draw.translate( coupled_pad, (coupled_pad_width / 2. + coupled_pad_gap / 2.), +coupled_pad_height / 2. + pad_height + pad_gap / 2. - pad_height / 2) pad_top_tmp = draw.union([circ_left_top, pad_top, circ_right_top]) # The coupler pads are only created if low_W=0 and low_H=+1 for name in self.options.connection_pads: if self.options.connection_pads[name][ 'loc_W'] == 0 and self.options.connection_pads[name][ 'loc_H'] == +1: pad_top_tmp = draw.union([ circ_left_top, coupled_pad_left, pad_top, coupled_pad_right, circ_right_top ]) pad_top = pad_top_tmp # Round part for the bottom pad. And again you should unite all of them. pad_bot = draw.translate(pad, 0, -(pad_height + pad_gap) / 2.) circ_left_bot = draw.Point(-pad_width / 2, -(pad_height + pad_gap) / 2.).buffer(pad_height / 2, resolution=16, cap_style=CAP_STYLE.round) circ_right_bot = draw.Point(pad_width / 2, -(pad_height + pad_gap) / 2.).buffer(pad_height / 2, resolution=16, cap_style=CAP_STYLE.round) pad_bot = draw.union([pad_bot, circ_left_bot, circ_right_bot]) rect_jj = draw.LineString([(0, -pad_gap / 2), (0, +pad_gap / 2)]) # the draw.rectangle representing the josephson junction # rect_jj = draw.rectangle(p.inductor_width, pad_gap) rect_pk = draw.rectangle(p.pocket_width, p.pocket_height) # Rotate and translate all qgeometry as needed. # Done with utility functions in Metal 'draw_utility' for easy rotation/translation # NOTE: Should modify so rotate/translate accepts qgeometry, would allow for # smoother implementation. polys = [rect_jj, pad_top, pad_bot, rect_pk] polys = draw.rotate(polys, p.orientation, origin=(0, 0)) polys = draw.translate(polys, p.pos_x, p.pos_y) [rect_jj, pad_top, pad_bot, rect_pk] = polys # Use the geometry to create Metal qgeometry self.add_qgeometry('poly', dict(pad_top=pad_top, pad_bot=pad_bot)) self.add_qgeometry('poly', dict(rect_pk=rect_pk), subtract=True) # self.add_qgeometry('poly', dict( # rect_jj=rect_jj), helper=True) self.add_qgeometry('junction', dict(rect_jj=rect_jj), width=p.inductor_width)
def make_coupling_resonators(self, num): """This function draws the coulping resonators. Adds pins. And adds the drawn geometry to qgeomtery table. """ p = self.p # rotate these trapezoids to form the contacts coords = self.make_coordinates_trap() coords1 = self.make_resonator_coordinates() trap_z = draw.Polygon(coords1) traps_connection = self.make_rotation(trap_z, 4) # Define contacts pockets = self.make_pockets() pocket0 = draw.rectangle(pockets[0], pockets[1]) pocket0 = draw.translate(pocket0, xoff=0, yoff=(coords[3][1])) pockets = self.make_rotation(pocket0, 4) # Define the connectors circle = self.make_circle() contacts = [0] * num for i in range(num): contacts[i] = draw.subtract(circle, traps_connection[i]) contacts[i] = draw.union(contacts[i], pockets[i]) pins = self.make_pin_coordinates() pins_cpl = self.make_rotation(pins, 3) objects = [contacts, pins_cpl] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [contacts, pins_cpl] = objects ################################################################## # Add geometry and Qpin connections if (p.number_of_connectors) >= 1: self.add_qgeometry('poly', {'contact_cpl1': contacts[0]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip) # Add pin connections self.add_pin('pin_cpl1', pins_cpl[0].coords, width=p.cpw_width, input_as_norm=True) if (p.number_of_connectors) >= 2: self.add_qgeometry('poly', {'contact_cpl2': contacts[1]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip) # Add pin connections self.add_pin('pin_cpl2', pins_cpl[1].coords, width=p.cpw_width, input_as_norm=True) if (p.number_of_connectors) >= 3: self.add_qgeometry('poly', {'contact_cpl3': contacts[2]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip) # Add pin connections self.add_pin('pin_cpl3', pins_cpl[2].coords, width=p.cpw_width, input_as_norm=True) if (p.number_of_connectors) >= 4: self.add_qgeometry('poly', {'contact_cpl4': contacts[3]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip) # Add pin connections self.add_pin('pin_cpl4', pins_cpl[3].coords, width=p.cpw_width, input_as_norm=True)
def make(self): """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # draw the lower pad as a rectangle pad_lower = draw.rectangle(p.pad_width, p.pad_height, p.pad_pos_x, p.pad_pos_y) # draw the lower finger as a rectangle finger_lower = draw.rectangle( p.finger_width, p.finger_height, p.pad_pos_x, p.pad_pos_y + 0.49999 * (p.pad_height) + 0.49999 * (p.finger_height)) # draw the Josephson Junction as a LineString rect_jj = draw.LineString([ (0, 0.5 * p.pad_height + p.finger_height), (0, 0.5 * p.pad_height + p.finger_height + p.finger_space) ]) # draw the first comb to the right of the lower finger as a rectangle comb1_lower = draw.rectangle( p.comb_width, (2 * p.finger_height), (0.5 * p.finger_width + p.comb_space_hor + 0.5 * p.comb_width), (p.pad_pos_y + 0.5 * p.pad_height + 1.0 * p.finger_height)) # draw the second comb to the right of the lower finger by translating the first comb comb2_lower = draw.translate(comb1_lower, 2.0 * (p.comb_space_hor + p.comb_width), 0.0) # draw the first comb to the left of the lower finger comb3_lower = draw.rectangle( p.comb_width, (2 * p.finger_height), (-0.5 * p.finger_width - 2.0 * p.comb_space_hor - 1.5 * p.comb_width), (p.pad_pos_y + 0.5 * p.pad_height + 1.0 * p.finger_height)) # draw the second comb to the left of the lower finger comb4_lower = draw.translate(comb3_lower, -2.0 * (p.comb_space_hor + p.comb_width), 0.0) coupling_capacitor = draw.rectangle( p.cc_width, p.cc_height, p.pad_pos_x, p.pad_pos_y - 0.5 * (p.pad_height) - p.cc_space - 0.5 * p.cc_height) cc_topleft = draw.rectangle( p.cc_topleft_width, p.cc_topleft_height, p.pad_pos_x - 0.5 * p.pad_width + 0.5 * p.cc_topleft_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height) cc_topright = draw.translate( cc_topleft, p.pad_width - 0.5 * p.cc_topleft_width - 0.5 * p.cc_topright_width, 0.0) # merge the bottom elements bottom = draw.union(pad_lower, finger_lower, comb1_lower, comb2_lower, comb3_lower, comb4_lower) # create the top portion of the comb by translating and rotating # the bottom portion of the comb top = draw.translate(bottom, 0.0, p.pad_height + p.finger_space) top = draw.rotate(top, p.rotation_top_pad) # draw the transmon pocket bounding box pocket = draw.rectangle(1.5 * p.pad_width, 5.0 * p.pad_height) # the origin is originally set to the middle of the lower pad. # Let's move it to the center of the JJ. bottom = draw.translate( bottom, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) top = draw.translate( top, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) coupling_capacitor = draw.translate( coupling_capacitor, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) cc_topleft = draw.translate( cc_topleft, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) cc_topright = draw.translate( cc_topright, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) rect_jj = draw.translate( rect_jj, 0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) # now translate the final structure according to the user input bottom = draw.rotate(bottom, p.orientation, origin=(0, 0)) bottom = draw.translate(bottom, p.pos_x, p.pos_y) top = draw.rotate(top, p.orientation, origin=(0, 0)) top = draw.translate(top, p.pos_x, p.pos_y) coupling_capacitor = draw.rotate(coupling_capacitor, p.orientation, origin=(0, 0)) coupling_capacitor = draw.translate(coupling_capacitor, p.pos_x, p.pos_y) cc_topleft = draw.rotate(cc_topleft, p.orientation, origin=(0, 0)) cc_topleft = draw.translate(cc_topleft, p.pos_x, p.pos_y) cc_topright = draw.rotate(cc_topright, p.orientation, origin=(0, 0)) cc_topright = draw.translate(cc_topright, p.pos_x, p.pos_y) rect_jj = draw.rotate(rect_jj, p.orientation, origin=(0, 0)) rect_jj = draw.translate(rect_jj, p.pos_x, p.pos_y) pocket = draw.rotate(pocket, p.orientation, origin=(0, 0)) pocket = draw.translate(pocket, p.pos_x, p.pos_y) # add each shape separately geom1 = {'pad_bot': bottom} geom2 = {'pad_top': top} geom3 = {'readout': coupling_capacitor} geom4 = {'bus1': cc_topleft} geom5 = {'bus2': cc_topright} geom_pocket = {'pocket': pocket} geom_jj = {'design': rect_jj} # add to qgeometry self.add_qgeometry('poly', geom1, layer=p.layer, subtract=False) self.add_qgeometry('poly', geom2, layer=p.layer, subtract=False) self.add_qgeometry('poly', geom3, layer=p.layer, subtract=False) self.add_qgeometry('poly', geom4, layer=p.layer, subtract=False) self.add_qgeometry('poly', geom5, layer=p.layer, subtract=False) self.add_qgeometry('poly', geom_pocket, layer=p.layer, subtract=True) self.add_qgeometry('junction', geom_jj, layer=p.layer, subtract=False, width=p.inductor_width) ################################################################### # Add Qpin connections for coupling capacitors # define a function that both rotates and translates the # qpin coordinates def qpin_rotate_translate(x): """ This function rotates the coordinates of the three qpins according to the user inputs for "pos_x", "pos_y" and "orientation". """ y = list(x) z = [0.0, 0.0] z[0] = y[0] * cos(p.orientation * 3.14159 / 180) - y[1] * sin( p.orientation * 3.14159 / 180) z[1] = y[0] * sin(p.orientation * 3.14159 / 180) + y[1] * cos( p.orientation * 3.14159 / 180) z[0] = z[0] + p.pos_x z[1] = z[1] + p.pos_y x = (z[0], z[1]) return x # Add Qpin connections for the bottom coupling capacitor qp1a = (0.0, -0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp1b = (0.0, -0.5 * p.pad_height - p.cc_space - p.cc_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) # rotate and translate the qpin coordinates qp1a = qpin_rotate_translate(qp1a) qp1b = qpin_rotate_translate(qp1b) self.add_pin('readout', points=np.array([qp1a, qp1b]), width=0.01, input_as_norm=True) # Add Qpin connections for top left coupling capacitor qp2a = (p.pad_pos_x - 0.5 * p.pad_width + 0.5 * p.cc_topleft_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp2b = (p.pad_pos_x - 0.5 * p.pad_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp2a = qpin_rotate_translate(qp2a) qp2b = qpin_rotate_translate(qp2b) self.add_pin('bus1', points=np.array([qp2a, qp2b]), width=0.01, input_as_norm=True) # Add Qpin connections for top right coupling capacitor qp3a = (p.pad_pos_x + 0.5 * p.pad_width - 0.5 * p.cc_topleft_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp3b = (p.pad_pos_x + 0.5 * p.pad_width, p.pad_pos_y + 1.5 * p.pad_height + 2.0 * p.finger_height + p.finger_space + p.cc_topleft_space + 0.5 * p.cc_topleft_height - 0.5 * p.pad_height - p.finger_height - 0.5 * p.finger_space) qp3a = qpin_rotate_translate(qp3a) qp3b = qpin_rotate_translate(qp3b) self.add_pin('bus2', points=np.array([qp3a, qp3b]), width=0.01, input_as_norm=True)
def make(self): """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # draw the concentric pad regions outer_pad = draw.Point(0, 0).buffer(p.rad_o) space = draw.Point(0, 0).buffer((p.gap + p.rad_i)) outer_pad = draw.subtract(outer_pad, space) inner_pad = draw.Point(0, 0).buffer(p.rad_i) #gap = draw.subtract(space, inner_pad) #pads = draw.union(outer_pad, inner_pad) # draw the top Josephson Junction jj_t = draw.LineString([(0.0, p.rad_i), (0.0, p.rad_i + p.gap)]) # draw the bottom Josephson Junction jj_b = draw.LineString([(0.0, -1.0 * p.rad_i), (0.0, -1.0 * p.rad_i - 1.0 * p.gap)]) # draw the readout resonator qp1a = (-0.5 * p.pocket_w, p.rad_o + p.res_s ) # the first (x,y) coordinate is qpin #1 qp1b = (p.res_ext, p.rad_o + p.res_s ) # the second (x,y) coordinate is qpin #1 rr = draw.LineString([qp1a, qp1b]) # draw the flux bias line a = (0.5 * p.pocket_w, -0.5 * p.fbl_gap) b = (0.5 * p.pocket_w - p.fbl_ext, -0.5 * p.fbl_gap) c = (p.rad_o + p.fbl_sp + p.fbl_rad, -1.0 * p.fbl_rad) d = (p.rad_o + p.fbl_sp + 0.2929 * p.fbl_rad, 0.0 - 0.7071 * p.fbl_rad) e = (p.rad_o + p.fbl_sp, 0.0) f = (p.rad_o + p.fbl_sp + 0.2929 * p.fbl_rad, 0.0 + 0.7071 * p.fbl_rad) g = (p.rad_o + p.fbl_sp + p.fbl_rad, p.fbl_rad) h = (0.5 * p.pocket_w - p.fbl_ext, 0.5 * p.fbl_gap) i = (0.5 * p.pocket_w, 0.5 * p.fbl_gap) fbl = draw.LineString([a, b, c, d, e, f, g, h, i]) # draw the transmon pocket bounding box pocket = draw.rectangle(p.pocket_w, p.pocket_h) # Translate and rotate all shapes objects = [outer_pad, inner_pad, jj_t, jj_b, pocket, rr, fbl] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, xoff=p.pos_x, yoff=p.pos_y) [outer_pad, inner_pad, jj_t, jj_b, pocket, rr, fbl] = objects # define a function that both rotates and translates the qpin coordinates def qpin_rotate_translate(x): y = list(x) z = [0.0, 0.0] z[0] = y[0] * cos(p.orientation * 3.14159 / 180) - y[1] * sin( p.orientation * 3.14159 / 180) z[1] = y[0] * sin(p.orientation * 3.14159 / 180) + y[1] * cos( p.orientation * 3.14159 / 180) z[0] = z[0] + p.pos_x z[1] = z[1] + p.pos_y x = (z[0], z[1]) return x # rotate and translate the qpin coordinates qp1a = qpin_rotate_translate(qp1a) qp1b = qpin_rotate_translate(qp1b) a = qpin_rotate_translate(a) b = qpin_rotate_translate(b) h = qpin_rotate_translate(h) i = qpin_rotate_translate(i) ############################################################## # Use the geometry to create Metal QGeometry geom_rr = {'path1': rr} geom_fbl = {'path2': fbl} geom_outer = {'poly1': outer_pad} geom_inner = {'poly2': inner_pad} geom_jjt = {'poly4': jj_t} geom_jjb = {'poly5': jj_b} geom_pocket = {'poly6': pocket} self.add_qgeometry('path', geom_rr, layer=1, subtract=False, width=p.cpw_width) self.add_qgeometry('path', geom_fbl, layer=1, subtract=False, width=p.cpw_width) self.add_qgeometry('poly', geom_outer, layer=1, subtract=False) self.add_qgeometry('poly', geom_inner, layer=1, subtract=False) self.add_qgeometry('junction', geom_jjt, layer=1, subtract=False, width=p.inductor_width) self.add_qgeometry('junction', geom_jjb, layer=1, subtract=False, width=p.inductor_width) self.add_qgeometry('poly', geom_pocket, layer=1, subtract=True) ########################################################################### # Add Qpin connections self.add_pin('pin1', points=np.array([qp1b, qp1a]), width=0.01, input_as_norm=True) self.add_pin('pin2', points=np.array([b, a]), width=0.01, input_as_norm=True) self.add_pin('pin3', points=np.array([h, i]), width=0.01, input_as_norm=True)
def make(self): """Build the component.""" p = self.p N = int(p.finger_count) #Finger Capacitor cap_box = draw.rectangle(N * p.cap_width + (N - 1) * p.cap_gap, p.cap_gap + 2 * p.cap_width + p.finger_length, 0, 0) make_cut_list = [] make_cut_list.append([0, (p.finger_length) / 2]) make_cut_list.append([(p.cap_width) + (p.cap_gap / 2), (p.finger_length) / 2]) flip = -1 for i in range(1, N): make_cut_list.append([ i * (p.cap_width) + (2 * i - 1) * (p.cap_gap / 2), flip * (p.finger_length) / 2 ]) make_cut_list.append([ (i + 1) * (p.cap_width) + (2 * i + 1) * (p.cap_gap / 2), flip * (p.finger_length) / 2 ]) flip = flip * -1 cap_cut = draw.LineString(make_cut_list).buffer(p.cap_gap / 2, cap_style=2, join_style=2) cap_cut = draw.translate(cap_cut, -(N * p.cap_width + (N - 1) * p.cap_gap) / 2, 0) cap_body = draw.subtract(cap_box, cap_cut) cap_body = draw.translate( cap_body, 0, -p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) / 2) cap_etch = draw.rectangle( N * p.cap_width + (N - 1) * p.cap_gap + 2 * p.cap_gap_ground, p.cap_gap + 2 * p.cap_width + p.finger_length + 2 * p.cap_gap_ground, 0, -p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) / 2) #CPW north_cpw = draw.LineString([[0, 0], [0, -p.cap_distance]]) south_cpw = draw.LineString( [[ 0, -p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) ], [ 0, -2 * p.cap_distance - (p.cap_gap + 2 * p.cap_width + p.finger_length) ]]) #Rotate and Translate c_items = [north_cpw, south_cpw, cap_body, cap_etch] c_items = draw.rotate(c_items, p.orientation, origin=(0, 0)) c_items = draw.translate(c_items, p.pos_x, p.pos_y) [north_cpw, south_cpw, cap_body, cap_etch] = c_items #Add to qgeometry tables self.add_qgeometry('path', {'north_cpw': north_cpw}, width=p.north_width, layer=p.layer) self.add_qgeometry('path', {'north_cpw_sub': north_cpw}, width=p.north_width + 2 * p.north_gap, layer=p.layer, subtract=True) self.add_qgeometry('path', {'south_cpw': south_cpw}, width=p.south_width, layer=p.layer) self.add_qgeometry('path', {'south_cpw_sub': south_cpw}, width=p.south_width + 2 * p.south_gap, layer=p.layer, subtract=True) self.add_qgeometry('poly', {'cap_body': cap_body}, layer=p.layer) self.add_qgeometry('poly', {'cap_etch': cap_etch}, layer=p.layer, subtract=True) #Add pins north_pin_list = north_cpw.coords south_pin_list = south_cpw.coords self.add_pin('north_end', points=np.array(north_pin_list[::-1]), width=p.north_width, input_as_norm=True) self.add_pin('south_end', points=np.array(south_pin_list), width=p.south_width, input_as_norm=True)
def make(self): """This is executed by the user to generate the qgeometry for the component.""" p = self.p ######################################################### # Make the shapely polygons for the main cap structure pad = draw.rectangle(p.trace_width * 5, p.trace_width) pad_top = draw.translate(pad, 0, +(p.trace_width * 2 + p.finger_length) / 2) pad_bot = draw.translate(pad, 0, -(p.trace_width * 2 + p.finger_length) / 2) finger = draw.rectangle(p.trace_width, p.finger_length) cent_finger = draw.translate(finger, 0, +(p.trace_width) / 2) left_finger = draw.translate(finger, -(p.trace_width * 2), -(p.trace_width) / 2) right_finger = draw.translate(finger, +(p.trace_width * 2), -(p.trace_width) / 2) # Make the shapely polygons for the leads in the pocket (length=pocket_buffer_width_y) trace_temp_1 = draw.rectangle(p.trace_width, p.pocket_buffer_width_y) trace_top = draw.translate( trace_temp_1, 0, +(p.finger_length + p.trace_width * 3 + p.pocket_buffer_width_y * 2) / 2 - p.pocket_buffer_width_y / 2) trace_bot = draw.translate( trace_temp_1, 0, -(p.finger_length + p.trace_width * 3 + p.pocket_buffer_width_y * 2) / 2 + p.pocket_buffer_width_y / 2) # Make the shapely polygons for pocket ground plane cuttout pocket = draw.rectangle( p.trace_width * 5 + p.pocket_buffer_width_x * 2, p.finger_length + p.trace_width * 3 + p.pocket_buffer_width_y * 2) # These variables are used to graphically locate the pin locations top_pin_line = draw.LineString([ (-p.trace_width / 2, (p.finger_length + p.trace_width * 3 + p.pocket_buffer_width_y * 2) / 2), (+p.trace_width / 2, (p.finger_length + p.trace_width * 3 + p.pocket_buffer_width_y * 2) / 2) ]) bot_pin_line = draw.LineString([( -p.trace_width / 2, -(p.finger_length + p.trace_width * 3 + p.pocket_buffer_width_y * 2) / 2), (+p.trace_width / 2, -(p.finger_length + p.trace_width * 3 + p.pocket_buffer_width_y * 2) / 2)]) # Create polygon object list polys1 = [ top_pin_line, bot_pin_line, pad_top, pad_bot, cent_finger, left_finger, right_finger, pocket, trace_top, trace_bot ] # Rotates and translates all the objects as requested. Uses package functions # in 'draw_utility' for easy rotation/translation polys1 = draw.rotate(polys1, p.orientation, origin=(0, 0)) polys1 = draw.translate(polys1, xoff=p.pos_x, yoff=p.pos_y) [ top_pin_line, bot_pin_line, pad_top, pad_bot, cent_finger, left_finger, right_finger, pocket, trace_top, trace_bot ] = polys1 # Adds the object to the qgeometry table self.add_qgeometry('poly', dict(pad_top=pad_top, pad_bot=pad_bot, cent_finger=cent_finger, left_finger=left_finger, right_finger=right_finger, trace_top=trace_top, trace_bot=trace_bot), layer=p.layer) #subtracts out ground plane on the layer its on self.add_qgeometry('poly', dict(pocket=pocket), subtract=True, layer=p.layer) # Generates its own pins self.add_pin('a', top_pin_line.coords, p.trace_width) self.add_pin('b', bot_pin_line.coords[::-1], p.trace_width)