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. n = int(p.n) # Create the geometry spiral_list = [] #Formulat to determine the size of the spiral based on inputed length. x_n = (p.length / (2 * n)) - (p.height + 2 * (p.gap + p.line_width) * (2 * n - 1)) if x_n <= p.gap + p.line_width: self._error_message = f'Inputted values results in the width of the spiral being too small.' self.logger.warning(self._error_message) return for step in range(n): x_point = x_n / 2 + step * (p.line_width + p.gap) y_point = p.height / 2 + step * (p.line_width + p.gap) spiral_list.append((-x_point, -y_point)) spiral_list.append((x_point, -y_point)) spiral_list.append((x_point, y_point)) spiral_list.append((-x_point - (p.line_width + p.gap), y_point)) x_point = (x_n / 2 + (step + 1) * (p.line_width + p.gap)) y_point = (p.height / 2 + (step + 1) * (p.line_width + p.gap) - p.line_width / 2) spiral_list.append((-x_point, -y_point)) spiral_list = draw.LineString(spiral_list) spiral_etch = draw.shapely.geometry.box( -(x_point + p.line_width / 2 + p.gap), -y_point, x_point - p.line_width / 2, y_point) #Generates a linestring to track port location points = draw.LineString([ (-x_point + p.line_width / 2, -y_point + p.coupler_distance), (-x_point - p.line_width / 2, -y_point + p.coupler_distance) ]) c_items = [spiral_list, spiral_etch, points] c_items = draw.rotate(c_items, p.orientation, origin=(0, 0)) c_items = draw.translate(c_items, p.pos_x, p.pos_y) [spiral_list, spiral_etch, points] = c_items ############################################## # add elements self.add_qgeometry('path', {'n_spiral': spiral_list}, width=p.line_width) self.add_qgeometry('poly', {'n_spira_etch': spiral_etch}, subtract=True) # NEW PIN SPOT self.add_pin('spiralPin', points=np.array(points.coords), width=p.line_width, input_as_norm=True)
def make(self): """Build the component.""" p = self.p prime_cpw_length = p.t_length * 2 #Primary CPW prime_cpw = draw.LineString([[-prime_cpw_length / 2, 0], [prime_cpw_length / 2, 0]]) #Secondary CPW second_cpw = draw.LineString([[0, -p.prime_width / 2], [0, -p.t_length]]) #Rotate and Translate c_items = [prime_cpw, second_cpw] 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] = 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': second_cpw}, width=p.second_width, layer=p.layer) self.add_qgeometry('path', {'second_cpw_sub': second_cpw}, width=p.second_width + 2 * p.second_gap, subtract=True, layer=p.layer) #Add pins prime_pin_list = prime_cpw.coords second_pin_list = second_cpw.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_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_elements(self, pts: np.ndarray): """Turns the CPW points into design elements, and add them to the design object. Arguments: pts (np.ndarray): Array of points """ # prepare the routing track line = draw.LineString(pts) # compute actual final length p = self.p self.options._actual_length = str( line.length - self.length_excess_corner_rounding(line.coords) ) + ' ' + self.design.get_units() # expand the routing track to form the substrate core of the cpw self.add_qgeometry('path', {'trace': line}, width=p.trace_width, fillet=p.fillet, layer=p.layer) if self.type == "CPW": # expand the routing track to form the two gaps in the substrate # final gap will be form by this minus the trace above self.add_qgeometry('path', {'cut': line}, width=p.trace_width + 2 * p.trace_gap, fillet=p.fillet, layer=p.layer, subtract=True)
def generate_spiral_list(x: int, y: int): """Helper function to generate a sprital list. Args: x (int): x-coordinate y (int): y-coordinate Returns: list: A list of points """ spiral_list = [] for step in range(3): point_value = 20 + step * 5 spiral_list.append((-point_value, -point_value)) spiral_list.append((point_value, -point_value)) spiral_list.append((point_value, point_value)) spiral_list.append((-point_value - (1 + 4), point_value)) point_value = 20 + (step + 1) * 5 spiral_list.append((-point_value, -point_value)) spiral_list = draw.LineString(spiral_list) spiral_list = draw.rotate(spiral_list, 0, origin=(x, y)) spiral_list = draw.translate(spiral_list, x, y) return spiral_list
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 make_flux_line(self): """Creates the charge line if the user has charge line option to TRUE """ # Grab option values pf = self.p.fl_options p = self.p #Make the T flux line h_line = draw.LineString([(-pf.t_top / 2, 0), (pf.t_top / 2, 0)]) v_line = draw.LineString([(pf.t_offset, 0), (pf.t_offset, -0.03)]) parts = [h_line, v_line] # Move the flux line down to the SQUID parts = draw.translate( parts, 0, -(p.cross_length + p.cross_gap + pf.t_inductive_gap + pf.t_width / 2 + pf.t_gap)) # Rotate and translate based on crossmon location parts = draw.rotate(parts, p.orientation, origin=(0, 0)) parts = draw.translate(parts, p.pos_x, p.pos_y) [h_line, v_line] = parts # Adding to qgeometry table self.add_qgeometry('path', { 'h_line': h_line, 'v_line': v_line }, width=pf.t_width, layer=p.layer) self.add_qgeometry('path', { 'h_line_sub': h_line, 'v_line_sub': v_line }, width=pf.t_width + 2 * pf.t_gap, subtract=True, layer=p.layer) # Generating pin pin_line = v_line.coords self.add_pin("flux_line", points=pin_line, width=pf.t_width, gap=pf.t_gap, input_as_norm=True)
def make_pocket(self): """Makes a basic Crossmon, 4 arm cross.""" # self.p allows us to directly access parsed values (string -> numbers) form the user option p = self.p cross_width = p.cross_width cross_length = p.cross_length cross_gap = p.cross_gap # access to chip name chip = p.chip # Creates the cross and the etch equivalent. cross_line = draw.shapely.ops.unary_union([ draw.LineString([(0, cross_length), (0, -cross_length)]), draw.LineString([(cross_length, 0), (-cross_length, 0)]) ]) cross = cross_line.buffer(cross_width / 2, cap_style=2) cross_etch = cross.buffer(cross_gap, cap_style=3, join_style=2) # The junction/SQUID #rect_jj = draw.rectangle(cross_width, cross_gap) #rect_jj = draw.translate(rect_jj, 0, -cross_length-cross_gap/2) rect_jj = draw.LineString([(0, -cross_length), (0, -cross_length - cross_gap)]) #rotate and translate polys = [cross, cross_etch, rect_jj] polys = draw.rotate(polys, p.orientation, origin=(0, 0)) polys = draw.translate(polys, p.pos_x, p.pos_y) [cross, cross_etch, rect_jj] = polys # generate qgeometry self.add_qgeometry('poly', dict(cross=cross), chip=chip) self.add_qgeometry('poly', dict(cross_etch=cross_etch), subtract=True, chip=chip) self.add_qgeometry('junction', dict(rect_jj=rect_jj), width=cross_width, chip=chip)
def make(self): """calculates the geometries of the QComponent""" p = self.parse_options() line = draw.LineString([(-p.width / 2, 0), (p.width / 2, 0)]) line = draw.translate(line, p.pos_x, p.pos_y) self.add_qgeometry('path', {'trace': line}, width=p.height, layer=p.layer, subtract=False) line2 = draw.LineString([((-p.width / 2) - 2 * p.gap, 0), ((p.width / 2) + 2 * p.gap, 0)]) line2 = draw.translate(line2, p.pos_x, p.pos_y) self.add_qgeometry('path', {'cut': line2}, width=p.height + 2 * p.gap, layer=p.layer, subtract=True) self.add_pin('in', line.coords[::-1], p.height, input_as_norm=True)
def make_pin_coordinates(self): """This function creates the coordinates for the pins """ p = self.p p_in = (0, p.radius) p_out = (0, 1.25 * (p.radius)) pins = draw.LineString([p_in, p_out]) return pins
def make(self): """This is executed by the user to generate the qgeometry for the component.""" p = self.p trace_width = p.trace_width trace_width_half = trace_width / 2 lead_length = p.lead_length trace_gap = p.trace_gap ######################################################### # Geometry of main launch structure launch_pad = draw.Polygon([(0, trace_width_half), (-.122, trace_width_half + .035), (-.202, trace_width_half + .035), (-.202, -trace_width_half - .035), (-.122, -trace_width_half - .035), (0, -trace_width_half), (lead_length, -trace_width_half), (lead_length, +trace_width_half), (0, trace_width_half)]) # Geometry pocket (gap) pocket = draw.Polygon([(0, trace_width_half + trace_gap), (-.122, trace_width_half + trace_gap + .087), (-.25, trace_width_half + trace_gap + .087), (-.25, -trace_width_half - trace_gap - .087), (-.122, -trace_width_half - trace_gap - .087), (0, -trace_width_half - trace_gap), (lead_length, -trace_width_half - trace_gap), (lead_length, +trace_width_half + trace_gap), (0, trace_width_half + trace_gap)]) # These variables are used to graphically locate the pin locations main_pin_line = draw.LineString([(lead_length, trace_width_half), (lead_length, -trace_width_half)]) # Create polygon object list polys1 = [main_pin_line, launch_pad, pocket] # 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) [main_pin_line, launch_pad, pocket] = polys1 # Adds the object to the qgeometry table self.add_qgeometry('poly', dict(launch_pad=launch_pad), 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 the pins self.add_pin('tie', main_pin_line.coords, trace_width)
def make_charge_line(self): """Creates the charge line if the user has charge line option to TRUE. """ # Grab option values name = 'Charge_Line' p = self.p cl_arm = draw.box(0, 0, -p.cl_width, p.cl_length) cl_cpw = draw.box(0, 0, -8 * p.cl_width, p.cl_width) cl_metal = draw.cascaded_union([cl_arm, cl_cpw]) cl_etcher = draw.buffer(cl_metal, p.cl_gap) port_line = draw.LineString([(-8 * p.cl_width, 0), (-8 * p.cl_width, p.cl_width)]) polys = [cl_metal, cl_etcher, port_line] # Move the charge line to the side user requested cl_rotate = 0 if (abs(p.cl_pocket_edge) > 135) or (abs(p.cl_pocket_edge) < 45): polys = draw.translate( polys, -(p.pocket_width / 2 + p.cl_ground_gap + p.cl_gap), p.cl_off_center) if (abs(p.cl_pocket_edge) > 135): cl_rotate = 180 else: polys = draw.translate( polys, -(p.pocket_height / 2 + p.cl_ground_gap + p.cl_gap), p.cl_off_center) cl_rotate = 90 if (p.cl_pocket_edge < 0): cl_rotate = -90 # Rotate it to the pockets orientation polys = draw.rotate(polys, p.orientation + cl_rotate, origin=(0, 0)) # Move to the final position polys = draw.translate(polys, p.pos_x, p.pos_y) [cl_metal, cl_etcher, port_line] = polys # Generating pins points = list(draw.shapely.geometry.shape(port_line).coords) self.add_pin(name, points, p.cl_width) # Adding to qgeometry table self.add_qgeometry('poly', dict(cl_metal=cl_metal)) self.add_qgeometry('poly', dict(cl_etcher=cl_etcher), subtract=True)
def make(self): """Build the component.""" p = self.p # p for parsed parameters. Access to the parsed options. port_line = draw.LineString([(0, -p.width / 2), (0, p.width / 2)]) # Rotates and translates the connector polygons (and temporary port_line) port_line = draw.rotate(port_line, p.orientation, origin=(0, 0)) port_line = draw.translate(port_line, p.pos_x, p.pos_y) port_points = list(draw.shapely.geometry.shape(port_line).coords) #Generates the pin self.add_pin('short', port_points, p.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. n = int(p.n) # Create the geometry spiral_list = [] for step in range(n): point_value = p.radius / 2 + step * (p.width + p.gap) spiral_list.append((-point_value, -point_value)) spiral_list.append((point_value, -point_value)) spiral_list.append((point_value, point_value)) spiral_list.append((-point_value - (p.width + p.gap), point_value)) point_value = p.radius / 2 + (step + 1) * (p.width + p.gap) spiral_list.append((-point_value, -point_value)) spiral_list = draw.LineString(spiral_list) spiral_list = draw.rotate(spiral_list, p.rotation, origin=(0, 0)) spiral_list = draw.translate(spiral_list, p.pos_x, p.pos_y) ############################################## # add qgeometry self.add_qgeometry('path', {'n_spiral': spiral_list}, width=p.width, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip) points = np.array(spiral_list.coords) # FIX POINTS, self.add_pin('spiralPin', points=points[-2:], width=p.width, input_as_norm=True)
def make(self): """Build the component.""" p = self.p # p for parsed parameters. Access to the parsed options. port_line = draw.LineString([(0, -p.width / 2), (0, p.width / 2)]) open_termination = draw.box(0, -(p.width / 2 + p.gap), p.termination_gap, (p.width / 2 + p.gap)) # Rotates and translates the connector polygons (and temporary port_line) polys = [open_termination, port_line] polys = draw.rotate(polys, p.orientation, origin=(0, 0)) polys = draw.translate(polys, p.pos_x, p.pos_y) [open_termination, port_line] = polys # Subtracts out ground plane on the layer its on self.add_qgeometry('poly', {'open_to_ground': open_termination}, subtract=True, layer=p.layer) # Generates the pins self.add_pin('open', port_line.coords, p.width)
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 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 arc(self, coord_init, coord_center, angle): ''' Generate x,y coordinates (in terms of shapely.geometry.Point()) of an arc with: a specified initial point, rotation center, and rotation direction (specified by angle in radian (float or integer), positive is ccw). coord_init, and coord_center should be shapely.geometry.Point object ''' # access to parse values from the user option p = self.p # local variable r = p.readout_cpw_turnradius step = p.arc_step # determine step number step_angle = step / r if angle >= 0 else -step / r step_N = abs(int(angle / step_angle)) #laststep_flag = True if angle % step_angle != 0 else False laststep_flag = bool(angle % step_angle != 0) # generate coordinate coord = [coord_init] point = coord_init for i in range(step_N): point = draw.rotate(point, step_angle, origin=coord_center, use_radians=True) coord.append(point) if laststep_flag: point = draw.rotate(coord_init, angle, origin=coord_center, use_radians=True) coord.append(point) coord = draw.LineString(coord) return coord
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): """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(self): """This is executed by the user to generate the qgeometry for the component.""" p = self.p pad_width = p.pad_width pad_height = p.pad_height pad_gap = p.pad_gap trace_width = p.trace_width trace_width_half = trace_width / 2. pad_width_half = pad_width / 2. lead_length = p.lead_length taper_height = p.taper_height trace_gap = p.trace_gap pad_gap = p.pad_gap ######################################################### # Geometry of main launch structure # The shape is a polygon and we prepare this point as orientation is 0 degree launch_pad = draw.Polygon([ (0, trace_width_half), (-taper_height, pad_width_half), (-(pad_height + taper_height), pad_width_half), (-(pad_height + taper_height), -pad_width_half), (-taper_height, -pad_width_half), (0, -trace_width_half), (lead_length, -trace_width_half), (lead_length, trace_width_half), (0, trace_width_half) ]) # Geometry pocket (gap) # Same way applied for pocket pocket = draw.Polygon([(0, trace_width_half + trace_gap), (-taper_height, pad_width_half + pad_gap), (-(pad_height + taper_height + pad_gap), pad_width_half + pad_gap), (-(pad_height + taper_height + pad_gap), -(pad_width_half + pad_gap)), (-taper_height, -(pad_width_half + pad_gap)), (0, -(trace_width_half + trace_gap)), (lead_length, -(trace_width_half + trace_gap)), (lead_length, trace_width_half + trace_gap), (0, trace_width_half + trace_gap)]) # These variables are used to graphically locate the pin locations main_pin_line = draw.LineString([(lead_length, trace_width_half), (lead_length, -trace_width_half)]) driven_pin_line = draw.LineString([ (-(pad_height + taper_height + pad_gap), pad_width_half), (-(pad_height + taper_height + pad_gap), -pad_width_half) ]) # Create polygon object list polys1 = [main_pin_line, driven_pin_line, launch_pad, pocket] # 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) [main_pin_line, driven_pin_line, launch_pad, pocket] = polys1 # Adds the object to the qgeometry table self.add_qgeometry('poly', dict(launch_pad=launch_pad), 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 the pins self.add_pin('tie', main_pin_line.coords, trace_width) self.add_pin('in', driven_pin_line.coords, pad_width, gap=pad_gap)
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_ro(self): ''' Create the head of the readout resonator. Contains: the circular patch for coupling, the 45 deg line, the 45 deg arc, a short straight segment (of length w) for smooth subtraction ''' # access to parsed values from the user option p = self.p # access to chip name chip = p.chip # local variables r = p.readout_radius w = p.readout_cpw_width g = p.readout_cpw_gap turnradius = p.readout_cpw_turnradius l_1 = p.readout_l1 l_2 = p.readout_l2 l_3 = p.readout_l3 l_4 = p.readout_l4 l_5 = p.readout_l5 # create the coupling patch in term of a circle cppatch = draw.Point(0, 0).buffer(r) # create the extended arm ## useful coordinates x_1, y_1 = l_1 * np.cos(np.pi / 4), -l_1 * np.sin(np.pi / 4) x_2, y_2 = x_1 + turnradius * ( 1 - np.cos(np.pi / 4)), y_1 - turnradius * np.sin(np.pi / 4) coord_init = draw.Point(x_1, y_1) coord_center = draw.Point(x_1 - turnradius * np.cos(np.pi / 4), y_1 - turnradius * np.sin(np.pi / 4)) x_3, y_3 = x_2, y_2 x_4, y_4 = x_3, y_3 - l_2 x_5, y_5 = x_4 + turnradius, y_4 coord_init1 = draw.Point(x_4, y_4) coord_center1 = draw.Point(x_5, y_5) x_6, y_6 = x_5, y_5 - turnradius x_7, y_7 = x_5 + l_3, y_6 x_8, y_8 = x_7, y_7 + turnradius coord_init2 = draw.Point((x_7, y_7)) coord_center2 = draw.Point((x_8, y_8)) x_9, y_9 = x_8, y_8 + turnradius x_10, y_10 = x_8 - l_4, y_9 x_11, y_11 = x_10, y_10 + turnradius coord_init3 = draw.Point((x_10, y_10)) coord_center3 = draw.Point((x_11, y_11)) arc3 = self.arc(coord_init3, coord_center3, -np.pi) x_12, y_12 = x_11, y_11 + turnradius x_13, y_13 = x_12 + l_5, y_12 line12 = draw.LineString([(x_12, y_12), (x_13, y_13)]) x_14, y_14 = x_13, y_13 + turnradius coord_init4 = draw.Point((x_13, y_13)) coord_center4 = draw.Point((x_14, y_14)) arc4 = self.arc(coord_init4, coord_center4, np.pi) ## line containing the 45deg line, 45 deg arc, ## and a short straight segment for smooth subtraction cparm_line = draw.shapely.ops.unary_union([ draw.LineString([(0, 0), coord_init]), self.arc(coord_init, coord_center, -np.pi / 4), draw.LineString([(x_3, y_3), (x_4, y_4)]), self.arc(coord_init1, coord_center1, np.pi / 2), draw.LineString([(x_6, y_6), (x_7, y_7)]), self.arc(coord_init2, coord_center2, np.pi), draw.LineString([(x_9, y_9), (x_10, y_10)]), arc3, line12, arc4, draw.translate(line12, 0, 2 * turnradius), draw.translate(arc3, 0, 4 * turnradius), draw.translate(line12, 0, 4 * turnradius), draw.translate(arc4, 0, 4 * turnradius), draw.translate(line12, 0, 6 * turnradius), draw.translate(arc3, 0, 8 * turnradius), draw.translate(line12, 0, 8 * turnradius) ]) cparm = cparm_line.buffer(w / 2, cap_style=2, join_style=1) ## fix the gap resulting from buffer eps = 1e-3 cparm = draw.Polygon(cparm.exterior) cparm = cparm.buffer(eps, join_style=2).buffer(-eps, join_style=2) # create combined objects for the signal line and the etch ro = draw.shapely.ops.unary_union([cppatch, cparm]) ro_etch = ro.buffer(g, cap_style=2, join_style=2) x_15, y_15 = x_14, y_14 + 7 * turnradius x_16, y_16 = x_15 + g / 2, y_15 port_line = draw.LineString([(x_15, y_15 + w / 2), (x_15, y_15 - w / 2)]) subtract_patch = draw.LineString([(x_16, y_16 - w / 2 - g - eps), (x_16, y_16 + w / 2 + g + eps) ]).buffer(g / 2, cap_style=2) ro_etch = ro_etch.difference(subtract_patch) # rotate and translate polys = [ro, ro_etch, port_line] polys = draw.rotate(polys, p.orientation, origin=(0, 0)) polys = draw.translate(polys, p.pos_x, p.pos_y) # update each object [ro, ro_etch, port_line] = polys # generate QGeometry self.add_qgeometry('poly', dict(ro=ro), chip=chip, layer=p.layer) self.add_qgeometry('poly', dict(ro_etch=ro_etch), chip=chip, layer=p.layer_subtract, subtract=p.subtract) # generate pins self.add_pin('readout', port_line.coords, width=w, gap=g, chip=chip)
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)
def make(self): """Build the component.""" p = self.p prime_cpw_length = p.coupling_length * 2 second_flip = 1 if p.mirror: second_flip = -1 #Primary CPW prime_cpw = draw.LineString([[-prime_cpw_length / 2, 0], [prime_cpw_length / 2, 0]]) #Secondary CPW second_down_length = p.down_length second_y = -p.prime_width / 2 - p.prime_gap - p.coupling_space - p.second_gap - p.second_width / 2 second_cpw = draw.LineString( [[second_flip * (-p.coupling_length / 2), second_y], [second_flip * (p.coupling_length / 2), second_y], [ second_flip * (p.coupling_length / 2), second_y - second_down_length ]]) second_termination = 0 if p.open_termination: second_termination = p.second_gap second_cpw_etch = draw.LineString( [[ second_flip * (-p.coupling_length / 2 - second_termination), second_y ], [second_flip * (p.coupling_length / 2), second_y], [ second_flip * (p.coupling_length / 2), second_y - second_down_length ]]) #Rotate and Translate c_items = [prime_cpw, second_cpw, second_cpw_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, second_cpw_etch] = c_items #Add to qgeometry tables self.add_qgeometry('path', {'prime_cpw': prime_cpw}, width=p.prime_width) self.add_qgeometry('path', {'prime_cpw_sub': prime_cpw}, width=p.prime_width + 2 * p.prime_gap, subtract=True) self.add_qgeometry('path', {'second_cpw': second_cpw}, width=p.second_width, fillet=p.fillet) self.add_qgeometry('path', {'second_cpw_sub': second_cpw_etch}, width=p.second_width + 2 * p.second_gap, subtract=True, fillet=p.fillet) #Add pins prime_pin_list = prime_cpw.coords second_pin_list = second_cpw.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[1:]), width=p.second_width, input_as_norm=True)
def make(self): """This is executed by the user to generate the qgeometry for the component.""" p = self.p lead_length = p.lead_length trace_width = p.trace_width trace_width_half = trace_width / 2 trace_gap = p.trace_gap inner_finger_width = .001 inner_finger_width_half = inner_finger_width / 2 inner_finger_offset = .015 finger_side_gap = .002 outer_finger_tip_gap = .0075 inner_finger_tip_gap = .05 + inner_finger_offset outer_finger_width = (trace_width - inner_finger_width - 2 * finger_side_gap) / 2 coupler_length = p.coupler_length lead_offset = coupler_length + outer_finger_tip_gap ######################################################### # Geometry of main launch structure launch_pad = draw.Polygon([ (0, trace_width_half), (-.122, trace_width_half + .035), (-.202, trace_width_half + .035), (-.202, -trace_width_half - .035), (-.122, -trace_width_half - .035), (0, -trace_width_half), (coupler_length, -trace_width_half), (coupler_length, -trace_width_half + outer_finger_width), (-inner_finger_tip_gap + inner_finger_offset, -trace_width_half + outer_finger_width), (-inner_finger_tip_gap + inner_finger_offset, trace_width_half - outer_finger_width), (coupler_length, trace_width_half - outer_finger_width), (coupler_length, trace_width_half), (0, trace_width / 2) ]) # Geometry of coupling structure ind_stub = draw.Polygon([ (inner_finger_offset, -inner_finger_width_half), (lead_offset, -inner_finger_width_half), (lead_offset, -trace_width_half), (lead_offset + lead_length, -trace_width_half), (lead_offset + lead_length, trace_width_half), (lead_offset, trace_width_half), (lead_offset, +inner_finger_width_half), (inner_finger_offset, +inner_finger_width_half), (inner_finger_offset, -inner_finger_width_half) ]) # Geometry pocket (gap) pocket = draw.Polygon([ (0, trace_width_half + trace_gap), (-.122, trace_width_half + trace_gap + .087), (-.25, trace_width_half + trace_gap + .087), (-.25, -trace_width_half - trace_gap - .087), (-.122, -trace_width_half - trace_gap - .087), (0, -trace_width_half - trace_gap), (lead_offset + lead_length, -trace_width_half - trace_gap), (lead_offset + lead_length, +trace_width_half + trace_gap), (0, trace_width_half + trace_gap) ]) # These variables are used to graphically locate the pin locations main_pin_line = draw.LineString([ (lead_offset + lead_length, trace_width_half), (lead_offset + lead_length, -trace_width_half) ]) # Create polygon object list polys1 = [main_pin_line, launch_pad, ind_stub, pocket] # 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) [main_pin_line, launch_pad, ind_stub, pocket] = polys1 # Adds the object to the qgeometry table self.add_qgeometry('poly', dict(launch_pad=launch_pad, ind_stub=ind_stub), 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 the pins self.add_pin('tie', main_pin_line.coords, trace_width)
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): """Builds the component.""" p = self.p #Draw the charge island btm = draw.shapely.geometry.box(-p.c_width / 2, -p.l_width / 2, 0, p.l_width / 2) x_spot = p.c_width / 2 - p.l_width / 2 arm1 = draw.shapely.geometry.box(-(x_spot + p.l_width / 2), p.l_width / 2, -(x_spot - p.l_width / 2), p.a_height) arm2 = draw.shapely.geometry.box(-((x_spot) * 3 / 5 + p.l_width / 2), p.l_width / 2, -((x_spot) * 3 / 5 - p.l_width / 2), p.a_height) arm3 = draw.shapely.geometry.box(-((x_spot) * 1 / 5 + p.l_width / 2), p.l_width / 2, -((x_spot) * 1 / 5 - p.l_width / 2), p.a_height) left_side = draw.shapely.ops.cascaded_union([btm, arm1, arm2, arm3]) cap_island = draw.shapely.ops.cascaded_union([ left_side, draw.shapely.affinity.scale(left_side, xfact=-1, yfact=1, origin=(0, 0)) ]) cap_subtract = cap_island.buffer(p.l_gap, cap_style=3, join_style=2) #Reference coordinates cpl_x = 1 / 5 * x_spot cpl_y = p.a_height + p.l_gap + p.cp_gap + p.cp_gspace fl_y = p.a_height + p.l_gap + p.fl_ground + p.fl_gap + p.fl_width / 2 #Draw the junction and flux line rect_jj = draw.LineString([(-cpl_x * 3, p.a_height), (-cpl_x * 3, p.a_height + p.l_gap)]) flux_line = draw.LineString([[-cpl_x * 3 - p.fl_length, fl_y], [-cpl_x * 3, fl_y], [-cpl_x * 3, fl_y + 0.01]]) #Draw the connector cpl_x = 1 / 5 * x_spot cpl_y = p.a_height + p.l_gap + p.cp_gap + p.cp_gspace con_pad = draw.shapely.geometry.box( cpl_x - 1 / 5 * x_spot - p.cp_arm_width / 2, cpl_y, cpl_x + 1 / 5 * x_spot + p.cp_arm_width / 2, cpl_y + p.cp_height) con_arm_l = draw.shapely.geometry.box( cpl_x - 1 / 5 * x_spot - p.cp_arm_width / 2, cpl_y - p.cp_arm_length, cpl_x - 1 / 5 * x_spot + p.cp_arm_width / 2, cpl_y) con_arm_r = draw.shapely.geometry.box( cpl_x + 1 / 5 * x_spot - p.cp_arm_width / 2, cpl_y - p.cp_arm_length, cpl_x + 1 / 5 * x_spot + p.cp_arm_width / 2, cpl_y) con_body = draw.shapely.ops.cascaded_union( [con_pad, con_arm_l, con_arm_r]) con_sub = con_body.buffer(p.cp_gap, cap_style=3, join_style=2) con_pin = draw.LineString([[cpl_x, cpl_y], [cpl_x, cpl_y + p.cp_height]]) #Rotate and translate. c_items = [ cap_island, cap_subtract, rect_jj, con_body, con_sub, flux_line, con_pin ] c_items = draw.rotate(c_items, p.orientation, origin=(0, 0)) c_items = draw.translate(c_items, p.pos_x, p.pos_y) [ cap_island, cap_subtract, rect_jj, con_body, con_sub, flux_line, con_pin ] = c_items #Add to qgeometry self.add_qgeometry('poly', { 'cap_island': cap_island, 'connector_body': con_body }, layer=p.layer) self.add_qgeometry('poly', { 'cap_subtract': cap_subtract, 'connector_sub': con_sub }, layer=p.layer, subtract=True) self.add_qgeometry('path', {'flux_line': flux_line}, width=p.fl_width, layer=p.layer) self.add_qgeometry('path', {'flux_line_sub': flux_line}, width=p.fl_width + 2 * p.fl_gap, subtract=True, layer=p.layer) self.add_qgeometry('junction', dict(rect_jj=rect_jj), width=p.l_width) #Add pin self.add_pin('Control', points=np.array(con_pin), width=p.l_width, input_as_norm=True) self.add_pin('Flux', points=np.array(flux_line.coords[-2:]), width=p.l_width, input_as_norm=True)