Exemple #1
0
 def generate_JJ(self):
     self.JJ_params['x'] = self.Coaxmon1.center[0] + (self.Coaxmon1.R4+self.JJ_params['indent'])*np.cos(self.angle)
     if self.Coaxmon1.center[0] != self.Coaxmon2.center[0]:
         self.JJ_params['y'] = self.Coaxmon1.center[1] + (self.Coaxmon1.R4+
                                                         self.JJ_params['indent'])*np.sin(self.angle)+(self.core/2+self.gap/2)
     else:
         self.JJ_params['y'] = self.Coaxmon1.center[1] + (self.Coaxmon1.R4 + self.JJ_params['indent']) * np.sin(self.angle)
     # print(self.angle)
     self.JJ = JJ4q.JJ_1(self.JJ_params['x'], self.JJ_params['y'],
                             self.JJ_params['a1'], self.JJ_params['a2'],
                             )
     result = self.JJ.generate_JJ()
     result = gdspy.boolean(result, result, 'or', layer=self.JJ_layer)
     angle = self.JJ_params['angle_JJ']
     result.rotate(angle, (self.JJ_params['x'], self.JJ_params['y']))
     indent = 1
     rect1 = gdspy.Rectangle((self.JJ_params['x'] - self.JJ.contact_pad_a / 2,
                             self.JJ_params['y'] +indent),
                            (self.JJ_params['x'] + self.JJ.contact_pad_a / 2,
                             self.JJ_params['y'] - self.JJ.contact_pad_b+indent), layer=6)
     rect2 = gdspy.Rectangle((self.JJ.x_end - self.JJ.contact_pad_a / 2,
                             self.JJ.y_end - 1),
                            (self.JJ.x_end + self.JJ.contact_pad_a /2 ,
                             self.JJ.y_end - self.JJ.contact_pad_b - indent), layer=6)
     if self.Coaxmon1.center[0] != self.Coaxmon2.center[0]:
         poly1 = gdspy.Polygon([(self.JJ_params['x'] - self.JJ.contact_pad_a / 2,
                                 self.JJ_params['y'] +indent),
                                (self.JJ_params['x'] - self.JJ.contact_pad_a / 2,
                                 self.JJ_params['y'] + indent-self.JJ.contact_pad_b),
                                (self.JJ_params['x'] - self.JJ.contact_pad_a-indent,self.Coaxmon1.center[1]-self.core/2),
                                (self.JJ_params['x'] - self.JJ.contact_pad_a-indent,self.Coaxmon1.center[1]+self.core/2)
                                ])
         poly2 = gdspy.Polygon([(self.JJ.x_end + self.JJ.contact_pad_a / 2,
                                 self.JJ.y_end -indent-self.JJ.contact_pad_b),
                                (self.JJ.x_end + self.JJ.contact_pad_a / 2,
                                 self.JJ.y_end - indent ),
                                (self.JJ.x_end + self.JJ.contact_pad_a + indent,
                                 self.Coaxmon1.center[1] + self.core / 2),
                                (self.JJ.x_end + self.JJ.contact_pad_a + indent,
                                 self.Coaxmon1.center[1] - self.core / 2)
                                ])
     else:
         poly1 = []
         poly2 = []
     rect = gdspy.boolean(rect1,[rect2,poly1,poly2], 'or', layer=6)
     rect.rotate(angle, (self.JJ_params['x'], self.JJ_params['y']))
     to_remove = gdspy.Polygon(self.JJ.points_to_remove,layer=self.layer_to_remove)
     to_remove.rotate(angle, (self.JJ_params['x'], self.JJ_params['y']))
     return result, rect , to_remove
 def finish_him(self):
     self.result.add(
         gdspy.boolean(
             self.total_cell.get_polygons(by_spec=True)[(self.total_layer,
                                                         0)],
             self.cell_to_remove.get_polygons(by_spec=True)[(2, 0)],
             'not',
             layer=self.total_layer))
     self.result.add(
         gdspy.boolean(
             self.total_cell.get_polygons(by_spec=True)[(self.total_layer,
                                                         0)],
             self.cell_to_remove.get_polygons(by_spec=True)[(2, 0)],
             'not',
             layer=self.total_layer))
    def generate_JJ(self):
        #cheap Manhatten style
        reach = 32
        result = gdspy.Rectangle((self.center[0]-self.b_g/2,self.center[1]+self.h/2-self.b_w/3+self.JJ_params['a1']/2),(self.center[0]-self.b_g/2+reach,self.center[1]+self.h/2-self.b_w/3-self.JJ_params['a1']/2))

        result = gdspy.boolean(result,gdspy.Rectangle((self.center[0]-self.b_g/2,self.center[1]+self.h/2-2*self.b_w/3+self.JJ_params['a1']/2),(self.center[0]-self.b_g/2+reach,self.center[1]+self.h/2-2*self.b_w/3-self.JJ_params['a1']/2))
,'or')

        result = gdspy.boolean(result,gdspy.Rectangle((self.center[0]+self.b_g/2,self.center[1]+self.h/2-2*self.b_w),(self.center[0]+self.b_g/2+self.JJ_params['a2'],self.center[1]+self.h/2-2*self.b_w+reach)), 'or')
        result = gdspy.boolean(result, result, 'or', layer=self.layer_configuration.jj_layer)

        angle = self.JJ_params['angle_JJ']
        result.rotate(angle, (self.JJ_coordinates[0], self.JJ_coordinates[1]))

        return result
Exemple #4
0
def render_text(text,
                size=None,
                position=(0, 0),
                font_prop=None,
                tolerance=0.1):
    path = TextPath(position, text, size=size, prop=font_prop)
    polys = []
    xmax = position[0]
    for points, code in path.iter_segments():
        if code == path.MOVETO:
            c = gdspy.Curve(*points, tolerance=tolerance)
        elif code == path.LINETO:
            c.L(*points)
        elif code == path.CURVE3:
            c.Q(*points)
        elif code == path.CURVE4:
            c.C(*points)
        elif code == path.CLOSEPOLY:
            poly = c.get_points()
            if poly.size > 0:
                if poly[:, 0].min() < xmax:
                    i = len(polys) - 1
                    while i >= 0:
                        if gdspy.inside(poly[:1], [polys[i]],
                                        precision=0.1 * tolerance)[0]:
                            p = polys.pop(i)
                            poly = gdspy.boolean(
                                [p],
                                [poly],
                                "xor",
                                precision=0.1 * tolerance,
                                max_points=0,
                            ).polygons[0]
                            break
                        elif gdspy.inside(polys[i][:1], [poly],
                                          precision=0.1 * tolerance)[0]:
                            p = polys.pop(i)
                            poly = gdspy.boolean(
                                [p],
                                [poly],
                                "xor",
                                precision=0.1 * tolerance,
                                max_points=0,
                            ).polygons[0]
                        i -= 1
                xmax = max(xmax, poly[:, 0].max())
                polys.append(poly)
    return polys
Exemple #5
0
 def ten(self, X=0, Y=0):
     points2 = [(X - 36, Y - 20.5),
                (X - 36, Y - 160.5), (X - 124, Y - 160.5),
                (X - 124, Y - 148.5), (X - 182, Y - 148.5),
                (X - 182, Y - 244.5), (X - 124, Y - 244.5),
                (X - 124, Y - 232.5), (X - 36, Y - 232.5),
                (X - 36, Y - 318.5), (X - 9, Y - 318.5), (X - 9, Y - 314.5),
                (X - 11, Y - 314.5),
                (X - 11, Y - 312.5), (X - 7, Y - 312.5), (X - 7, Y - 318.5),
                (X + 7, Y - 318.5), (X + 7, Y - 312.5), (X + 11, Y - 312.5),
                (X + 11, Y - 314.5), (X + 9, Y - 314.5), (X + 9, Y - 318.5),
                (X + 36, Y - 318.5), (X + 36, Y - 232.5),
                (X + 124, Y - 232.5), (X + 124, Y - 244.5),
                (X + 182, Y - 244.5), (X + 182, Y - 148.5),
                (X + 124, Y - 148.5), (X + 124, Y - 160.5),
                (X + 36, Y - 160.5), (X + 36, Y - 20.5)]
     points3 = [(X - 12, Y - 44.5), (X - 12, Y - 184.5),
                (X - 148, Y - 184.5), (X - 148, Y - 180.5),
                (X - 172, Y - 180.5), (X - 172, Y - 212.5),
                (X - 148, Y - 212.5), (X - 148, Y - 208.5),
                (X - 12, Y - 208.5), (X - 12, Y - 300.5),
                (X - 1.5, Y - 300.5), (X - 1.5, Y - 306.5),
                (X + 2.5, Y - 306.5), (X + 2.5, Y - 304.5),
                (X + 0.5, Y - 304.5), (X + 0.5, Y - 300.5),
                (X + 12, Y - 300.5), (X + 12, Y - 208.5),
                (X + 148, Y - 208.5), (X + 148, Y - 212.5),
                (X + 172, Y - 212.5), (X + 172, Y - 180.5),
                (X + 148, Y - 180.5), (X + 148, Y - 184.5),
                (X + 12, Y - 184.5), (X + 12, Y - 44.5)]
     poly2 = gs.Polygon(points2)
     poly3 = gs.Polygon(points3)
     cap_fin = gs.boolean(poly2, poly3, "not")
     self.cell.add(cap_fin)
Exemple #6
0
    def _subtract_holes_from_ground(
            self, diff_holes_cell) -> Union[gdspy.library.Cell, None]:
        """Get reference to ground cell and then subtract the holes from
        ground. Place the difference into a new cell, which will eventually
        be added under Top.

        Args:
            diff_holes_cell ([type]): Cell which contains all the holes.

        Returns:
            Union[gdspy.library.Cell, None]: If worked, the new cell with
            cheesed ground, otherwise, None.
        """

        # Still need to 'not' with Top_main_1 (ground)
        top_chip_layer_name = f'TOP_{self.chip_name}_{self.layer}'
        if top_chip_layer_name in self.lib.cells.keys():
            ground_cell = self.lib.cells[top_chip_layer_name]
            ground_cheese = gdspy.boolean(ground_cell.get_polygons(),
                                          diff_holes_cell.get_polygonsets(),
                                          'not',
                                          max_points=self.max_points,
                                          precision=self.precision,
                                          layer=self.layer,
                                          datatype=self.datatype_cheese)
            ground_cheese_cell_name = (f'TOP_{self.chip_name}_{self.layer}'
                                       f'_Cheese_{self.datatype_cheese}')
            ground_cheese_cell = self.lib.new_cell(ground_cheese_cell_name,
                                                   overwrite_duplicate=True)
            return ground_cheese_cell.add(ground_cheese)

        self.logger.warning(
            f'The cell:{top_chip_layer_name} was not found in self.lib. '
            f'Cheesing not implemented.')
        return None
Exemple #7
0
 def generate_JJ(self):
     self.JJ = squid3JJ.JJ_2(self.JJ_coordinates[0],
                             self.JJ_coordinates[1],
                             self.JJ_params['a1'],
                             self.JJ_params['jj1_width'],
                             self.JJ_params['jj1_height'],
                             self.JJ_params['jj2_width'],
                             self.JJ_params['jj2_height'],
                             self.JJ_params['jj3_width'],
                             self.JJ_params['jj3_height'],
                             self.JJ_params['c2'],
                             add_JJ=self.third_JJ,
                             hole_in_squid_pad=self.hole_in_squid_pad)
     result = self.JJ.generate_jj()
     result = gdspy.boolean(result,
                            result,
                            'or',
                            layer=self.layer_configuration.jj_layer)
     angle = self.JJ_params['angle_JJ']
     if self.JJ_pad_connection_shift:
         connection_shift = self.JJ.contact_pad_b_outer / 2
     else:
         connection_shift = 0
     result.rotate(angle, (self.JJ_coordinates[0], self.JJ_coordinates[1]))
     rect = gdspy.Rectangle(
         (self.JJ_coordinates[0] - self.JJ.contact_pad_a_outer / 2,
          self.JJ_coordinates[1] + connection_shift +
          self.JJ.contact_pad_b_outer),
         (self.JJ_coordinates[0] + self.JJ.contact_pad_a_outer / 2,
          self.JJ_coordinates[1] + connection_shift -
          self.JJ.contact_pad_b_outer),
         layer=self.layer_configuration.total_layer)
     rect.rotate(angle, (self.JJ_coordinates[0], self.JJ_coordinates[1]))
     return result, rect
Exemple #8
0
def Heater(l_heater2):
    # define  heater
    w_heater = 3
    w_port = 10
    w_wire = w_port * 2
    cell = lib.new_cell('heater')
    # add middle long rect
    heater = gdspy.Rectangle((0, w_heater / 2), (l_heater2, -w_heater / 2),
                             **layer_heater)
    cell.add(heater)
    # add left rect and wire
    heater = gdspy.Rectangle((-w_port / 2, w_port / 2),
                             (w_port / 2, -w_port / 2), **layer_heater)
    cell.add(heater)
    heater = gdspy.Rectangle((-w_wire / 2, w_wire / 2),
                             (w_wire / 2, -w_wire / 2), **layer_wire)
    cell.add(heater)
    # add right rect and wire
    heater = gdspy.Rectangle((l_heater2 - w_port / 2, w_port / 2),
                             (l_heater2 + w_port / 2, -w_port / 2),
                             **layer_heater)
    cell.add(heater)
    heater = gdspy.Rectangle((l_heater2 - w_wire / 2, w_wire / 2),
                             (l_heater2 + w_wire / 2, -w_wire / 2),
                             **layer_wire)
    cell.add(heater)

    path1 = gdspy.Path(w_wg)
    path1.segment(l_heater2)
    path2 = gdspy.Path(w_wg_cld)
    path2.segment(l_heater2)
    cell.add(gdspy.boolean(path2, path1, 'xor', **layer_FETCH_COR))

    return cell
Exemple #9
0
    def add_bandages(self):
        bandage_to_island = gdspy.Rectangle(
            (self.JJ_coordinates[0] - self.JJ.contact_pad_a_outer / 4,
             self.JJ_coordinates[1] + self.JJ.contact_pad_b_outer / 2),
            (self.JJ_coordinates[0] + self.JJ.contact_pad_a_outer / 4,
             self.JJ_coordinates[1] - 3 * self.JJ.contact_pad_b_outer / 4),
            layer=self.layer_configuration.bandages_layer)
        bandage_to_ground = gdspy.Rectangle(
            (self.JJ.rect2[0] - self.JJ.rect_size_a / 4,
             self.JJ.rect2[1] - self.JJ.rect_size_b / 4),
            (self.JJ.rect2[0] + self.JJ.rect_size_a / 4,
             self.JJ.rect2[1] - 5 * self.JJ.rect_size_b / 4),
            layer=self.layer_configuration.bandages_layer)

        bandage_to_fluxline = gdspy.Rectangle(
            (self.JJ.rect1[0] - self.JJ.rect_size_a / 4,
             self.JJ.rect1[1] - self.JJ.rect_size_b / 4),
            (self.JJ.rect1[0] + self.JJ.rect_size_a / 4,
             self.JJ.rect1[1] - 5 * self.JJ.rect_size_b / 4),
            layer=self.layer_configuration.bandages_layer)
        bandages = gdspy.boolean(bandage_to_island,
                                 [bandage_to_fluxline, bandage_to_ground],
                                 'or',
                                 layer=self.layer_configuration.bandages_layer)
        return bandages
Exemple #10
0
    def unite(self, entities, keep_originals=True):

        blank_entity = entities.pop(0)
        blank_polygon = self.gds_object_instances.pop(blank_entity.name)
        self.cell = self.gds_cells[blank_entity.body.name]
        self.cell.polygons.remove(blank_polygon)

        tool_polygons = []
        for tool_entity in entities:
            tool_polygon = self.gds_object_instances[tool_entity.name]
            if isinstance(tool_polygon, gdspy.PolygonSet):
                for polygon in tool_polygon.polygons:
                    tool_polygons.append(polygon)
            else:
                tool_polygons.append(tool_polygon)

        #2 unite operation
        tool_polygon_set = gdspy.PolygonSet(tool_polygons,
                                            layer=blank_entity.layer)
        united = gdspy.boolean(blank_polygon,
                               tool_polygon_set,
                               'or',
                               precision=TOLERANCE,
                               max_points=0,
                               layer=blank_entity.layer)

        self.gds_object_instances[blank_entity.name] = united
        self.cell.add(united)

        return blank_entity
Exemple #11
0
    def render(self):
        # first the two contacts
        contact_1 = gdspy.Rectangle(
            (-self.padsize / 2, self.length / 2 - self.padsize / 2),
            (self.padsize / 2, self.length / 2 + self.padsize / 2))
        contact_2 = gdspy.Rectangle(
            (-self.padsize / 2, -self.length / 2 - self.padsize / 2),
            (self.padsize / 2, -self.length / 2 + self.padsize / 2))
        contacts = gdspy.boolean(
            contact_1,
            contact_2,
            'or',
            layer=self.layer_configuration.airbridges_pad_layer)
        # add restricted area for holes
        restricted_area = gdspy.Rectangle(
            (-self.padsize / 2, -self.length / 2 - self.padsize / 2),
            (self.padsize / 2, self.length / 2 + self.padsize / 2))
        # now the bridge itself
        bridge = gdspy.Rectangle(
            (-self.width / 2, -self.length / 2),
            (self.width / 2, self.length / 2),
            layer=self.layer_configuration.airbridges_layer)

        return {
            'airbridges_pad_layer': [contacts],
            'airbridges_layer': [bridge],
            'restrict': (restricted_area, )
        }
def plg_bool(plgsa,plgsb,operation,**kwargs):
    '''take two poly_lists and perform layer-wise boolean operations.

    This is not grade-A code.  It doesn't support subtracting a contained object.'''
    if not isinstance(plgsa,poly_list) or not isinstance(plgsb,poly_list):
        print 'both objects need to be poly lists!'
        pass

    if operation == 'int':
        f = lambda a,b: a and b
    elif operation == 'union':
        f = lambda a,b: a or b
    elif operation == 'sub':
        f = lambda a, b: a and not b

    out_plgs = poly_list()

    for layer in plgsa:
        if plgsb.has_key(layer):
#            print 'found two in the same layer'
#            print 'a:', plgsa[layer]
#            print 'b:', plgsb[layer]
            ret = gdspy.boolean([plgsa[layer], plgsb[layer]], f, eps=1e-10)
#            print 'ret:', ret
            ret.layers = [layer,]*len(ret.polygons)
            ret.datatypes = [0,]*len(ret.polygons)
#            print 'ret:', ret
            out_plgs[layer] = ret


    return out_plgs
    def render(self):
        """
        Draws edge g metallization on chip
        :return:
        """

        contact_window = gdspy.Rectangle(
            np.asarray(self.position) - self.window_size / 2,
            np.asarray(self.position) + self.window_size / 2,
            layer=self.layer_configuration.airbridges_pad_layer)

        squares = None
        for sqc in ((1, 1), (1, -1), (-1, 1), (-1, -1)):
            sqc = gdspy.Rectangle(
                np.asarray(self.position) + np.asarray(sqc) *
                (self.gap / 2 + self.square_size),
                np.asarray(self.position) + np.asarray(sqc) * self.gap / 2)
            squares = gdspy.boolean(squares,
                                    sqc,
                                    'or',
                                    layer=self.layer_configuration.total_layer)

        return {
            'positive': squares,
            'restrict': contact_window,
            'airbridges_pads': contact_window
        }
Exemple #14
0
def markers_photo_litho(center_coords, chip_side_x, chip_side_y, w, l_x, l_y,
                        layer_align):
    """
    Generates photo-litho markers that are cross hairs on the wafer edges with desired width and length
    INPUT: array with center position of the chips, chip dimensions
    OUTPUT: dicing markers elements
    """
    elements = []
    # positions of photo-litho alignment markers
    positions = [
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
        20, 21, 22, 23
    ]
    for j in positions:
        elements.append(
            crosshair(center_coords[j][0], center_coords[j][1], w, l_x, l_y,
                      layer_align))

    markers = gdspy.boolean(elements,
                            None,
                            'or',
                            precision=0.001,
                            max_points=199,
                            layer=layer_align)
    return markers
Exemple #15
0
def bwToGDS(Width, Height, bwArray, layer, datatype):
    #Converts a black and white
    """
    Args:
        Width: The width of the bmp in the GDSPY base units (1 unit = 1um by default)
        Height: The height of the bmp in the GDSPY base unit (1 unit = 1um by default)
        bwArray: The black and white image for layout
        layer: Layer the BMP should be placed on in the GDS Layout
        datatype: The datatype of the bmp when placed in the GDS Layout
    Returns:
        A GDSPY polygonset
    """
    black = 0  #We assume that the material is already converted to a black only version.
    YRes = len(bwArray)
    XRes = len(bwArray[0])
    pX = Width / XRes
    pY = Height / YRes
    rects = []
    for i in range(len(bwArray)):
        for j in range(len(bwArray[0])):
            if bwArray[i][j] == black:
                rects.append(
                    gdspy.Rectangle((pX * j, -pY * i),
                                    (pX * (j + 1), -pY * (i + 1)), layer,
                                    datatype))

    patt = None
    try:
        patt = gdspy.boolean(rects[0], rects[1:], "or", max_points=0)
        print("Polygonset Successfully Generated")
    except:
        print("Polygonset is Empty! Check black value and try again")
        None
    return patt
Exemple #16
0
    def render(self):

        if self.cross_type=='Navigation':
            filename = "\/navigation_cross.gds"
            cell_name = 'Navigation_cross'

        elif self.cross_type=='Cut':
            filename = "\cut_cross.gds"
            cell_name = 'Cut_cross'

        cross_positive = gdspy.GdsLibrary().read_gds(infile=self.path_mask +
                                                            filename).cells[cell_name].remove_polygons(lambda pts,layer,
                                                           datatype: layer != self.layers_configuration['total'])

        cross_negative = gdspy.GdsLibrary().read_gds(infile=self.path_mask +
                                                            filename).cells[cell_name].remove_polygons(lambda pts,layer,
                                                           datatype: layer != self.layers_configuration['inverted'])


        for elements_layer in [cross_negative.polygons,cross_positive.polygons]:
            for element in elements_layer:
                element.translate(self.cross_position[0],self.cross_position[1])

        restricted_object=gdspy.boolean(cross_negative.get_polygons(),cross_positive.get_polygons(),'or')

        return {'positive': cross_positive,
                'inverted': cross_negative,
                'restrict': restricted_object}
Exemple #17
0
def markers_ebeam_litho1(center_coords, chip_side_x, chip_side_y, layer_align):
    """
    Generates "crosshair" markers at the corners of each chip for alignment of the dicing saw and dots following that fo alignment of ebeam
    INPUT: array with center position of the chips, chip dimensions
    OUTPUT: dicing markers elements
    """
    elements = []
    w = 5  # width of the cross hair on the corner of a chip
    l_x = 100  # length of the cross hair
    l_y = 100

    for c in center_coords:
        print(c)
        print(type(c))
        rv = gdspy.Rectangle(
            (c[0] - chip_side_x / 2 - w / 2, c[1] + chip_side_y / 2 - l_y / 2),
            (c[0] - chip_side_x / 2 + w / 2, c[1] + chip_side_y / 2 + l_y / 2),
            layer=layer_align)
        rh = gdspy.Rectangle(
            (c[0] - chip_side_x / 2 - l_x / 2, c[1] + chip_side_y / 2 - w / 2),
            (c[0] - chip_side_x / 2 + l_x / 2, c[1] + chip_side_y / 2 + w / 2),
            layer=layer_align)
        crosshair = gdspy.boolean(
            rv, rh, 'or',
            layer=layer_align)  #making a cross hair on the edge of a chip
        elements.append(crosshair)
    return elements
Exemple #18
0
def text_rect(bounding_box,
              box_length,
              box_width,
              txt_label,
              txt_height,
              layer,
              rect_shift,
              extra_text=None):
    """creates a bounding rectangle with text subtracted from it. 
	returns a cell.
	"""
    # get the bounding box
    # add a 1um offset from the rest of the pattern
    offset = box_length / 2 + 1

    xshift, yshift = rect_shift

    print(xshift)

    test1 = offset + xshift
    # add the text
    vtext = gdspy.Text(txt_label,
                       txt_height, (offset + xshift, box_width / 2 + yshift),
                       horizontal=False,
                       **layer)

    # first subtract the interior rectangle from the exterior rectangle
    sub = gdspy.boolean(bounding_box, vtext, 'not')
    return sub
Exemple #19
0
def bounding_rectangle(pattern_w, pattern_l, padding, layer, rect_shift,
                       clearance, opt_litho_layer):
    """ creates a rectangle of a predefined width bounding the pattern. 
	Rect shift is a tuple of coordinates specifying the offset of the
	rectangle
	"""
    print('pattern_w :' + str(pattern_w))
    print('pattern_l: ' + str(pattern_l))
    print('padding: ' + str(padding))
    print('layer: ' + str(layer))
    print('rect shift: ' + str(rect_shift))
    xshift, yshift = rect_shift

    interior_rectangle = gdspy.Rectangle(
        (-pattern_l / 2 + xshift, -pattern_w / 2 + yshift),
        (pattern_l / 2 + xshift, pattern_w / 2 + yshift), **layer)
    exterior_rectangle = gdspy.Rectangle(
        (-pattern_l / 2 - padding + xshift, -pattern_w / 2 - padding + yshift),
        (pattern_l / 2 + padding + xshift, pattern_w / 2 + padding + yshift),
        layer)

    # define the rectangle used for optical lithography
    opt_rectangle = gdspy.Rectangle(
        (-pattern_l / 2 - padding + xshift + clearance,
         -pattern_w / 2 - padding + yshift + clearance),
        (pattern_l / 2 + padding + xshift - clearance,
         pattern_w / 2 + padding + yshift - clearance), **opt_litho_layer)

    # subtract the interior rectangle from the exterior rectangle
    sub = gdspy.boolean(exterior_rectangle, interior_rectangle, 'not')
    return sub, pattern_l, opt_rectangle
def gdspy_shift_size(polyset, shift, layer):
    new_polygons = []

    for ps in polyset.polygons:
        new_ps = []
        N = len(ps)
        for idx in range(N):
            vec = ps[idx] - ps[idx - 1]
            vec_len = np.linalg.norm(vec)
            vec_t = vec / vec_len
            vec_n = np.array([vec_t[1], -vec_t[0]])

            new_ps.extend(
                (ps[idx - 1] + vec_n * shift, ps[idx] + vec_n * shift))

        new_polygons.append(gdspy.Polygon(np.array(new_ps)))

    #union_shape = polyset
    union_shape = None
    for poly in new_polygons:
        union_shape = gdspy.boolean(union_shape,
                                    poly,
                                    'or',
                                    max_points=0,
                                    layer=layer)

    return union_shape
Exemple #21
0
    def _subtract_keepout_from_hole_grid(
            self, gather_holes_cell: gdspy.library.Cell) -> gdspy.library.Cell:
        """Given a cell with all the holes, subtract the keepout region.
        Then return a new cell with the result.

        Args:
            gather_holes_cell (gdspy.library.Cell): Holds a grid of all
                                                the holes for cheesing.

        Returns:
            gdspy.library.Cell: Newly created cell that holds the difference
                                        of holes minus the keep=out region.
        """

        # subtact the keepout, note, Based on user options,
        # the keepout (no_cheese) cell may not be in self.lib.
        temp_keepout_chip_layer_cell = f'temp_keepout_{self.chip_name}_{self.layer}'
        temp_keepout_cell = self.lib.new_cell(temp_keepout_chip_layer_cell,
                                              overwrite_duplicate=True)
        temp_keepout_cell.add(self.nocheese_gds)
        diff_holes = gdspy.boolean(gather_holes_cell.get_polygonsets(),
                                   temp_keepout_cell.get_polygonsets(),
                                   'not',
                                   max_points=self.max_points,
                                   precision=self.precision,
                                   layer=self.layer,
                                   datatype=self.datatype_cheese + 1)
        diff_holes_cell_name = f'TOP_{self.chip_name}_{self.layer}_Cheese_diff'
        diff_holes_cell = self.lib.new_cell(diff_holes_cell_name,
                                            overwrite_duplicate=True)
        diff_holes_cell.add(diff_holes)

        self.lib.remove(temp_keepout_chip_layer_cell)
        return diff_holes_cell
    def finish_him(self):

        _tmp = gdspy.boolean(
            self.total_cell.get_polygons(by_spec=True)[(self.total_layer, 0)],
            self.cell_to_remove.get_polygons(by_spec=True)[(0, 0)],
            'not',
            layer=self.total_layer)
        self.result.add(_tmp)

        # self.total_cell.add(gdspy.boolean(self.total_cell.get_polygons(by_spec=True)[(self.total_layer, 0)],
        #                               self.cell_to_remove.get_polygons(by_spec=True)[(0, 0)], 'not',
        #                               layer=self.total_layer))

        for each_two_rects in self.two_small_rectangles_list:
            _tmp = gdspy.boolean(_tmp, each_two_rects, 'or')

        self.result.add(_tmp)
Exemple #23
0
def union(one, two, layer = 1, datatype = 1):
    ### Makes a mask from two objects of the type:
    ### Polygon, PolygonSet, CellReference, CellArray,
    ### or an array-like[N][2] of vertices of a polygon.
    spec = {'layer': layer, 'datatype': datatype}
    # Apply boolean operation and add boolean to cell
    return gdspy.boolean([one, two],
        lambda one, two: one or two, **spec)
Exemple #24
0
def test_notempty():
    name = 'cr_notempty'
    c = gdspy.Cell(name)
    ref = gdspy.CellReference(name, (1, -1), 90, 2, True)
    ref.translate(-1, 1)
    c.add(gdspy.Rectangle((0, 0), (1, 2), 2, 3))
    assert ref.area() == 8
    assert ref.area(True) == {(2, 3): 8}
    err = numpy.array(((0, 0), (4, 2))) - ref.get_bounding_box()
    assert numpy.max(numpy.abs(err)) < 1e-15
    assert ref.origin[0] == ref.origin[1] == 0
    r = gdspy.boolean(ref.get_polygons(), gdspy.Rectangle((0, 0), (4, 2)), 'xor', 1e-6, 0)
    assert r is None
    d = ref.get_polygons(True)
    assert len(d.keys()) == 1
    r = gdspy.boolean(d[(2, 3)], gdspy.Rectangle((0, 0), (4, 2)), 'xor', 1e-6, 0)
    assert r is None
 def generate_coupler(self,coordinate,r_init,r_final,rect_end):
     #to fix bug
     bug=5
     result = gdspy.Round(coordinate, r_init, r_final,
                               initial_angle=(self.arc_start) * np.pi, final_angle=(self.arc_finish) * np.pi)
     rect = gdspy.Rectangle((coordinate[0]+r_final-bug,coordinate[1]-self.w/2),(coordinate[0]+rect_end+bug, coordinate[1]+self.w/2))
     rect.rotate(self.phi*np.pi, coordinate)
     return gdspy.boolean(result,rect, 'or')
 def generate_qubit(self):
     ground = gdspy.Round(self.center, self.outer_ground, self.R4, initial_angle=0, final_angle=2*np.pi)
     restricted_area = gdspy.Round(self.center, self.outer_ground,  layer=self.restricted_area_layer)
     core = gdspy.Round(self.center, self.R1, inner_radius=0, initial_angle=0, final_angle=2*np.pi)
     result = gdspy.boolean(ground, core, 'or', layer=self.total_layer)
     if len(self.Couplers) != 0:
         for Coupler in self.Couplers:
             if Coupler.grounded == True:
                 result = gdspy.boolean(Coupler.generate_coupler(self.center, self.R2, self.outer_ground,self.R4 ), result, 'or', layer=self.total_layer)
             else:
                 result = gdspy.boolean(Coupler.generate_coupler(self.center, self.R2, self.R3, self.R4), result, 'or', layer=self.total_layer)
     self.JJ_coordinates = (self.center[0] + self.R1*np.cos(self.JJ_params['angle_qubit']), self.center[1] + self.R1*np.sin(self.JJ_params['angle_qubit']))
     JJ,rect = self.generate_JJ()
     result = gdspy.boolean(result, rect, 'or')
     # self.AB1_coordinates = coordinates(self.center.x, self.center.y + self.R4)
     # self.AB2_coordinates = coordinates(self.center.x, self.center.y - self.outer_ground)
     return result, restricted_area, JJ
Exemple #27
0
def connect_zShape(cell, pos_start, pos_end, len_port=5, w_wg=0.5, w_etch=3, radius=10, type_layout='positive'):
    path1 = connect_zShape_(pos_start, pos_end, len_port, w_wg, radius=radius, **ld_wg)
    path2 = connect_zShape_(pos_start, pos_end, len_port, w_wg+2*w_etch, radius=radius, **ld_cld)
    if type_layout=='positive':
        cell.add([path1, path2])
    if type_layout=='negative':
        cell.add(gdspy.boolean(path2, path1, 'xor', **ld_fulletch))
    return cell
Exemple #28
0
    def render(self):
        """
        Draws edge g metallization on chip
        :return:
        """
        edge = 600 #  fundamental constant - edge length
        r1 = gdspy.Rectangle((0, 0), (self.chip_geometry.sample_horizontal_size, self.chip_geometry.sample_vertical_size))
        r2 = gdspy.Rectangle((edge, edge), (self.chip_geometry.sample_horizontal_size - edge,
                                            self.chip_geometry.sample_vertical_size - edge))
        result = gdspy.boolean(r1, r2, 'not')

        for pad in self.pads.items():
            pad = pad.get()
            to_bool = gdspy.Rectangle(pad['positive'].get_bounding_box()[0].tolist(), pad['positive'].get_bounding_box()[1].tolist())
            result = gdspy.boolean(result, to_bool, 'not')
        result_restricted = gdspy.boolean(result, result, 'or', layer=self.layer_configuration.restricted_area_layer)
        return {'positive': result, 'restrict': result_restricted}
Exemple #29
0
def alignment_mark(xw, xl, layer):
    """ creates a cross alignment mark geometry, by taking the  union of 2 
	rectangles.
	"""
    horizontal = gdspy.Rectangle((-xl / 2, -xw / 2), (xl / 2, xw / 2), **layer)
    vertical = gdspy.Rectangle((-xw / 2, -xl / 2), (xw / 2, xl / 2), **layer)
    cross = gdspy.boolean(horizontal, vertical, 'or', **layer)
    return cross
    def generate_fluxline_end(self,end):
        JJ = end['JJ']
        length = end['length']
        width = end['width']
        point1 = JJ.rect1
        point2 = JJ.rect2
        result = None
        # rect_to_remove = gdspy.Rectangle((),
        #                                  ())
        for point in [point1,point2]:
            line = gdspy.Rectangle((point[0]-width/2, point[1]),
                                (point[0]+width/2, point[1]-length))
            result = gdspy.boolean(line, result, 'or', layer=6)
        # result = gdspy.boolean(line1,line2,'or',layer=self.total_layer)
        path1 = gdspy.Polygon([(point1[0]+width/2, point1[1]-length),(point1[0]-width/2, point1[1]-length),
                               (self.end[0]+(self.core/2+self.gap+width)*np.cos(self.angle+np.pi/2),
                                self.end[1]+(self.core/2+self.gap+width)*np.sin(self.angle+np.pi/2)),
                               (self.end[0] + (self.core / 2 + self.gap ) * np.cos(self.angle +np.pi/2),
                                self.end[1] + (self.core / 2 + self.gap ) * np.sin(self.angle +np.pi/2))])


        result = gdspy.boolean(path1,result, 'or', layer=6)

        path2 = gdspy.Polygon([(point2[0] + width / 2, point2[1] - length),(point2[0] - width / 2, point2[1] - length),
                               (self.end[0] +(self.core / 2)*np.cos(self.angle+np.pi/2),self.end[1]+( self.core / 2)*np.sin(self.angle+np.pi/2)),
                               (self.end[0] + self.core / 2 *np.cos(self.angle+3*np.pi/2),self.end[1]+( self.core / 2)*np.sin(self.angle+3*np.pi/2))])
        result = gdspy.boolean(path2, result, 'or', layer=6)

        # if end['type'] != 'coupler':
        restricted_area = gdspy.Polygon([(point1[0] - width / 2, point1[1]),
                                         (point2[0] + width / 2 + self.gap, point2[1]),
                                         (point2[0] + width / 2 + self.gap, point2[1] - length),
                                         (self.end[0] + (self.core / 2 + self.gap) * np.cos(
                                             self.angle + 3 * np.pi / 2),
                                          self.end[1] + (self.core / 2 + self.gap) * np.sin(
                                              self.angle + 3 * np.pi / 2)),
                                         (self.end[0] + (self.core / 2 + self.gap + width) * np.cos(
                                             self.angle + np.pi / 2),
                                          self.end[1] + (self.core / 2 + self.gap + width) * np.sin(
                                              self.angle + np.pi / 2)),
                                         (point1[0] - width / 2, point1[1] - length)],
                                        layer=self.rectricted_area_layer)
        # else:
        #
        return result,restricted_area,restricted_area
Exemple #31
0
def generateRings(lib,
                  centerWidth=2200,
                  centerHeight=2200,
                  ringWidth=[750, 450, 270, 162, 97, 58],
                  traceWidth=0,
                  traceSpacing=0,
                  name="RINGS",
                  layer=1,
                  offset=[0, 0]):
    rings = lib.new_cell(name)
    for i in range(len(ringWidth)):

        outerHalfWidth = centerWidth / 2 + np.sum(ringWidth[0:i + 1]) + np.sum(
            ringWidth[0:i])
        innerHalfWidth = centerWidth / 2 + 2 * np.sum(ringWidth[0:i])
        outerHalfHeight = centerHeight / 2 + np.sum(
            ringWidth[0:i + 1]) + np.sum(ringWidth[0:i])
        innerHalfHeight = centerHeight / 2 + 2 * np.sum(ringWidth[0:i])

        outerPoints = np.array(offset) + np.array([[
            -outerHalfWidth, -outerHalfHeight
        ], [-outerHalfWidth, outerHalfHeight], [
            outerHalfWidth, outerHalfHeight
        ], [outerHalfWidth, -outerHalfHeight]])

        innerPoints = np.array(offset) + np.array([[
            -innerHalfWidth, -innerHalfHeight
        ], [-innerHalfWidth, innerHalfHeight], [
            innerHalfWidth, innerHalfHeight
        ], [innerHalfWidth, -innerHalfHeight]])

        cutoutPoints = np.array(offset) + np.array(
            [[-innerHalfWidth, traceSpacing + traceWidth / 2],
             [-outerHalfWidth, traceSpacing + traceWidth / 2],
             [-outerHalfWidth, -traceSpacing - traceWidth / 2],
             [-innerHalfWidth, -traceSpacing - traceWidth / 2]])

        ringOuter = gdspy.Polygon(outerPoints)
        ringInner = gdspy.Polygon(innerPoints)
        ringCutout = gdspy.Polygon(cutoutPoints)
        ring = gdspy.boolean(ringOuter, ringInner, 'not')
        ring = gdspy.boolean(ring, ringCutout, 'not', layer=layer)

        rings.add(ring)
    return rings
Exemple #32
0
 def useAsMask(self, groundPlane = None):
     ### Generates metal from groundPlane using CPW as a negative mask
     ### Make a fake 1000x1000 at origin ground plane if none given
     ### Returns resulting object
     spec = self.spec
     if groundPlane is None:
         groundPlane = gdspy.Rectangle((-500, -500), (500, 500), 0)
     # Create a PolygonSet from CPW path
     cpwPolySet = self.makePolySet(self.path)
     # Apply boolean operation
     return gdspy.boolean([groundPlane, cpwPolySet],
         lambda groundPlane, cpwPolySet: groundPlane and not cpwPolySet, **spec)
Exemple #33
0
def mask(subtractThis, addThis = None, layer = 1, datatype = 1):
    ### Makes a mask from two objects of the type:
    ### Polygon, PolygonSet, CellReference, CellArray,
    ### or an array-like[N][2] of vertices of a polygon.
    ### cell - specify which GDS cell to add mask to
    ### Make a fake 1000x1000 at origin ground plane if addThis not given
    spec = {'layer': layer, 'datatype': datatype}
    if addThis is None:
        addThis = gdspy.Rectangle((-500, -500), (500, 500), 0)
    # Apply boolean operation and add boolean to cell
    return gdspy.boolean([addThis, subtractThis],
        lambda addThis, subtractThis: addThis and not subtractThis, **spec)
Exemple #34
0
	# P4=gdspy.Rectangle(7, (2.5, -2.5), ((100+2.5), -(100+2.5)))

	align_cell.add(gdspy.Rectangle(7, (2.5, 2.5), (100+2.5, 100+2.5)))
	align_cell.add(gdspy.Rectangle(7, (-2.5, 2.5), (-(100+2.5), (100+2.5))))
	align_cell.add(gdspy.Rectangle(7, (-2.5, -2.5), (-(100+2.5), -(100+2.5))))
	align_cell.add(gdspy.Rectangle(7, (2.5, -2.5), ((100+2.5), -(100+2.5))))

	align_cell2.add(gdspy.Rectangle(7, (-(100+2.5), -(100+2.5)), ((100+2.5), (100+2.5))))

	#primitives.append(gdspy.PolygonSet(0, [P1.points ,P2.points,P3.points,P4.points]))
	#primitives.append(gdspy.PolygonSet(0,B.points))
	primitives = [gdspy.CellReference(align_cell, origin=(0, 0)), gdspy.CellReference(align_cell2, origin=(0, 0))]

	subtraction = lambda p1, p2: p2 and not p1
	bool_cell = gdspy.Cell('Bool_Alignment_Marks')
	bool_cell.add(gdspy.boolean(1, primitives, subtraction, max_points=199))	


	name = os.path.abspath(os.path.dirname(os.sys.argv[0])) + os.sep + 'bool_align_mark'

	## Output the layout to a GDSII file (default to all created cells).
	## Set the units we used to micrometers and the precision to nanometers.
	gdspy.gds_print(name + '.gds', unit=1.0e-6, precision=1.0e-9)
	print('Sample gds file saved: ' + name + '.gds')

	## Save an image of the boolean cell in a png file.  Resolution refers
	## to the number of pixels per unit in the layout. Resolution changed from 4
	## to 1 to avoid  "malloc_error"
	#gdspy.gds_image([resonator_cell], image_name=name, resolution=1, antialias=4)

	#comment out save as png for speed
Exemple #35
0
    def openGapFillet(self, distance, gapType, filletRadius = 10, direction = None):
        ### Draw a straight CPW gap segment in the direction following the last path with a fillet
        ### Gap type is either 'beg' or 'end' to specify where fillet goes
        gap = self.gap
        width = self.width
        spec = self.spec
        if gapType == 'beg':
            if direction is None:
                direction = self.initalDirection
        if gapType == 'end':
            if direction is None:
                direction = self.path.direction
        cellName = self.cellName
        x = self.path.x
        y = self.path.y
        if direction == '+x':
            theta = 0
        elif direction == '+y':
            theta = pi/2
        elif direction == '-y':
            theta = 3*pi/2
        elif direction == '-x':
            theta = pi
        else:
            theta = direction

        points = self.rectPathPivot(x, y, 0, distance, width + 2*gap, theta)
        gapPoly = gdspy.Polygon(points, **spec)
        gapPoly.fillet(filletRadius)

        if gapType == 'beg':
            points = self.rectPathPivot(x, y, distance - filletRadius, distance, width + 2*gap, theta)
        elif gapType == 'end':
            points = self.rectPathPivot(x, y, 0, filletRadius, width + 2*gap, theta)
        gapPolyNoFillet = gdspy.Polygon(points, **spec)

        union = gdspy.boolean([gapPolyNoFillet, gapPoly],
            lambda gpnf, gp: gpnf or gp, **spec)

        # Correct for path offset
        if direction == '+x':
            self.path.x = x + distance
            self.path.y = y
        elif direction == '+y':
            self.path.x = x
            self.path.y = y + distance
        elif direction == '-y':
            self.path.x = x
            self.path.y = y - distance
        elif direction == '-x':
            self.path.x = x - distance
            self.path.y = y
        else:
            self.path.x  = x + sin(theta)*distance
            self.path.y  = y + cos(theta)*distance

        # Inner fillet position definitions
        if gapType == 'beg':
            x = self.path.x
            y = self.path.y
        elif gapType == 'end':
            x = x - cos(theta)*(2*filletRadius)
            y = y - sin(theta)*(2*filletRadius)

        # Create masks for fillet and so subtraction
        points = self.rectPathPivot(x, y, 0, 2*filletRadius, width, theta)
        rectMask = gdspy.Polygon(points, **spec)
        rectMask.fillet(filletRadius)
        if gapType == 'beg':
            points = self.rectPathPivot(x, y, 0, filletRadius, width, theta)
        elif gapType == 'end':
            points = self.rectPathPivot(x, y, filletRadius, 2*filletRadius, width, theta)
        rect = gdspy.Polygon(points, **spec)
        subtraction = gdspy.boolean([rectMask, rect],
            lambda rem, re: re and not rem, **spec)

        # Add polygons to cell
        cellName.add(subtraction)
        cellName.add(union)
Exemple #36
0
def Draw_Sensor(Sensor_Number, Through_Line_Layer = 1, Resonator_Trace_Layer = 2, Pillar_Layer = 3):
	'''
	This Function draws a sensor. It positions the resonators according to the mask definition input files. 
	Its also draws the pillars outside of the bounding box of the resonators, the sensor die cut lines and
	the through line.
	Origin of the Sensor is the lower left corner.
	'''

	#For Test Only! Remove when deployed
	#gdspy.Cell.cell_dict = {}

	# Obtain Sensor Parameters
	Sensor_Params = Mask_DB.Get_Mask_Data("SELECT X_Length, Y_Length, Cut_Line_Width, Pillar_Diameter, Pillar_Grid_Spacing, Pillar_Clearance, Through_Line_Type, Through_Line_Width, Through_Line_Turn_Radius,Through_Line_Gap, Through_Line_Edge_Offset FROM Sensors WHERE sensor_id = " + str(Sensor_Number),'all')
	#sql_cmd = "SELECT X_Length, Y_Length, Cut_Line_Width, Pillar_Diameter, Pillar_Grid_Spacing, Pillar_Clearance, Through_Line_Type, Through_Line_Width, Through_Line_Turn_Radius,Through_Line_Gap, Through_Line_Edge_Offset FROM Sensors WHERE Sensor = " + str(Sensor_Number)
	#Cursor.execute(sql_cmd)
	#Sensor_Params = Cursor.fetchall()

	#There should only be one sensor returned from database. We make sure of this.
	if len(Sensor_Params) > 1:
		print("Something is wrong. There are more than one senor #" + str(Sensor_Number) + ". Using the first one pulled.")

	Pillar_Grid_Spacing_Reduction_Factor = 3.0

	X_Length, Y_Length, Cut_Line_Width, Pillar_Diameter, Pillar_Grid_Spacing, Pillar_Clearance, Through_Line_Type, Through_Line_Width, Through_Line_Turn_Radius,Through_Line_Gap, Through_Line_Edge_Offset = Sensor_Params[0]
	Pillar_Radius = Pillar_Diameter/2
	Pillar_Grid_Spacing = Pillar_Grid_Spacing*Pillar_Grid_Spacing_Reduction_Factor
	#Initialize Sensor Cell
	sensor_cell_name = 'SENSOR_'+str(Sensor_Number)
	sensor_cell = gdspy.Cell(sensor_cell_name,exclude_from_global=False)


	
	
	# We draw the cut lines by boolean operation on two squares defining the die outline
	poly1 = gdspy.Rectangle(current_sensor_origin, current_sensor_origin+ np.array([X_Length, Y_Length]), layer=Resonator_Trace_Layer)
	poly2 = gdspy.Rectangle(current_sensor_origin + np.array([Cut_Line_Width, Cut_Line_Width]), current_sensor_origin+np.array([X_Length-Cut_Line_Width, Y_Length-Cut_Line_Width]), layer=Resonator_Trace_Layer)
	#poly1 = gdspy.Rectangle(Resonator_Trace_Layer, (0, 0), (X_Length, Y_Length))
	#poly2 = gdspy.Rectangle(Resonator_Trace_Layer, (Cut_Line_Width, Cut_Line_Width), (X_Length-Cut_Line_Width, Y_Length-Cut_Line_Width))
	primitives = [poly2,poly1]
	subtraction = lambda p1, p2: p2 and not p1
	mask_cell.add(gdspy.boolean( primitives, subtraction, max_points=199,layer=Resonator_Trace_Layer))

	#
	#
	#
	#Bare sensor cell is sensor cell without text and cutlines
	#bare_sensor_cell_name = 'BARE_'+sensor_cell_name
	#bare_sensor_cell = gdspy.Cell(bare_sensor_cell_name,exclude_from_global=False)
	#
	#
	#
	#


	#
	#
	#
	#
	#
	#Add the name of the sensor in the lower left of the die
	Text_Offset = 100
	#sensor_cell.add(gdspy.Text(Resonator_Trace_Layer, 'S' + str(Sensor_Number), 300, (Cut_Line_Width+Text_Offset, Cut_Line_Width+Text_Offset)))
	text_cell.add(gdspy.Text('S' + str(Sensor_Number), 300, tuple(current_sensor_origin + np.array([Cut_Line_Width+Text_Offset, Cut_Line_Width+Text_Offset])), layer=Resonator_Trace_Layer))
	#
	#
	#
	##


	#Draw Throughline
	#assuming L shape
 	Though_Line_Trace = gdspy.Path(Through_Line_Width, (X_Length/2, 0))
 	Though_Line_Trace.segment( Through_Line_Edge_Offset + Through_Line_Width/2 - Through_Line_Turn_Radius, '+y', layer=Through_Line_Layer)
 	Though_Line_Trace.turn(Through_Line_Turn_Radius, 'l',layer=Through_Line_Layer)
	Though_Line_Trace.segment((X_Length/2)-Through_Line_Edge_Offset-Through_Line_Width/2 - 2*Through_Line_Turn_Radius, '-x', layer=Through_Line_Layer)
	Though_Line_Trace.turn(Through_Line_Turn_Radius, 'r', layer=Through_Line_Layer)
	Though_Line_Trace.segment(Y_Length-2*Through_Line_Edge_Offset-Through_Line_Width - 2*Through_Line_Turn_Radius, '+y',layer=Through_Line_Layer)
	_res_x_zero = Though_Line_Trace.x
	Though_Line_Trace.turn( Through_Line_Turn_Radius, 'r',layer=Through_Line_Layer)
	_res_y_zero = Though_Line_Trace.y	
	Though_Line_Trace.segment( (X_Length/2)-Through_Line_Edge_Offset-Through_Line_Width/2 - 2*Through_Line_Turn_Radius, '+x',layer=Through_Line_Layer)
	Though_Line_Trace.turn( Through_Line_Turn_Radius, 'l',layer=Through_Line_Layer)
	Though_Line_Trace.segment(Through_Line_Edge_Offset + Through_Line_Width/2 - Through_Line_Turn_Radius, '+y',layer=Through_Line_Layer)

	sensor_cell.add(Though_Line_Trace)

	#This is a test rectange to check the through line placement
	#sensor_cell.add(gdspy.Rectangle(Resonator_Trace_Layer, (Through_Line_Edge_Offset, Through_Line_Edge_Offset), (Through_Line_Edge_Offset+Through_Line_Width/2 + Through_Line_Turn_Radius, Through_Line_Edge_Offset+Through_Line_Width/2 + Through_Line_Turn_Radius)))
	
	#Starting position of first resonator
	_res_x_zero += (Through_Line_Width/2)
	_res_y_zero += (-Through_Line_Width/2)
	_cur_Res_y_pos = _res_y_zero


	Res_IDs = Mask_DB.Get_Mask_Data("SELECT resonator_id, Coupler_Zone, Head_Space, Design_Freq,Design_Q FROM Resonators WHERE sensor_id = " + str(Sensor_Number),'all')
	#sql_cmd = "SELECT Design_Freq, Width, Design_Q, Head_Space, Coupler_Zone, Meander_Pitch, Meander_Zone FROM Resonators WHERE Sensor = " + str(Sensor_Number)
	#Cursor.execute(sql_cmd)
	#Res_IDs = Cursor.fetchall()
	

	
	#For boolean subtraction, however does not work due to insufficient memory
	# #Initialize Resonator Mask Cell, which will contain rectangles positioned over the resonators
	# res_mask_cell_name = 'S'+str(Sensor_Number)+'ResMask'
	# res_mask_cell = gdspy.Cell(res_mask_cell_name, exclude_from_global=True)

	_pillar_x_index = (Pillar_Grid_Spacing+Pillar_Diameter)/2
	_pillar_y_index = Y_Length - (Pillar_Grid_Spacing+Pillar_Diameter)/2

	Res_Number = 1

	
	for ID in Res_IDs:
		resonator_id,Coupler_Zone, Head_Space,Design_Freq,Design_Q = ID

		Resonator_Name = 'F' + str(Design_Freq) + ' Qc' + str(int(Design_Q)) + ' R' + str(resonator_id)
		resonator_cell,_y_initial = Draw_Resonator(Resonator_Name=Resonator_Name,Resonator_ID=resonator_id, Resonator_Trace_Layer = Resonator_Trace_Layer, Pillar_Layer = Pillar_Layer, Y_Pitch_Tight = True, X_Pitch_Tight = True,Update_DB = True)

		_cur_Res_x_pos = Coupler_Zone + _res_x_zero
		_cur_Res_y_pos += -Head_Space-_y_initial
		#global current_resonator_origin
		current_resonator_origin = np.array([_cur_Res_x_pos, _cur_Res_y_pos])
		resonator_origin = str(current_resonator_origin.tolist()).replace(',',';')
		Mask_DB.Update_Computed_Parameters(resonator_id, {"Resonator_Origin":'"'+resonator_origin+'"'})
		_curr_Res_ref =  gdspy.CellReference(resonator_cell, tuple(current_resonator_origin))
		sensor_cell.add(_curr_Res_ref)
		
		#add resonator label text
		text_location = current_sensor_origin + current_resonator_origin + resonator_label_location 
		text_cell.add(gdspy.Text( Resonator_Name, 3*Pillar_Radius, tuple(text_location), layer=Resonator_Trace_Layer))

		_bounding_box_edges = resonator_cell.get_bounding_box() + np.array([[_cur_Res_x_pos, _cur_Res_y_pos],[_cur_Res_x_pos, _cur_Res_y_pos]])
		_total_y_distance = _bounding_box_edges[1][1] - _bounding_box_edges[0][1]
		_cur_Res_y_pos += -_total_y_distance 

		while _pillar_y_index >= _cur_Res_y_pos:
			while _pillar_x_index <= X_Length - Pillar_Radius:
				if not in_rectangle((_pillar_x_index, _pillar_y_index),_bounding_box_edges,Pillar_Radius):#Pillar_Radius+Pillar_Grid_Spacing):
					sensor_cell.add(gdspy.Round((_pillar_x_index, _pillar_y_index), Pillar_Radius,number_of_points=60, layer=Pillar_Layer))
				_pillar_x_index += Pillar_Grid_Spacing
			_pillar_x_index = (Pillar_Grid_Spacing+Pillar_Diameter)/2
			_pillar_y_index -= Pillar_Grid_Spacing

		Res_Number += 1 
	
	while _pillar_y_index >= Pillar_Radius:
		while _pillar_x_index <= X_Length - Pillar_Radius:
			sensor_cell.add(gdspy.Round((_pillar_x_index, _pillar_y_index), Pillar_Radius,number_of_points=60, layer=Pillar_Layer))
			_pillar_x_index += Pillar_Grid_Spacing
		_pillar_x_index = (Pillar_Grid_Spacing+Pillar_Diameter)/2
		_pillar_y_index -= Pillar_Grid_Spacing
	
	#bare_sensor_cell_ref =  gdspy.CellReference(bare_sensor_cell, (0,0))
	#sensor_cell.add(bare_sensor_cell_ref)	
	Sensor_Dict = {"Through_Line_Metal_Area":Though_Line_Trace.area(),"Through_Line_Length":Though_Line_Trace.length, "Sensor_Pillar_Area": sensor_cell.area(by_spec=True)[(Pillar_Layer,0)], "sensor_id":Sensor_Number, "Sensor_Cell_Name":'"'+sensor_cell_name+'"' }
	for ID in Res_IDs:
		resonator_id = ID[0]
		Mask_DB.Update_Computed_Parameters(resonator_id, Sensor_Dict)


	return sensor_cell
Exemple #37
0
	def draw_alignment(Inner_Cross_Layer, Outer_Cross_Layer,Inner_Cross_Thickness,Outer_Cross_Thickness,Outer_Cross_Width, Guidelines = True, Outer_Only = False, *arg):
		""" Inner_Cross_Thickness is line width of cross
		Outer_Cross_Thickness is line width of outer cross
		Outer_Cross_Width is overall width and height of cross
		Guidelines = True -- draws stepped guidlines which point to alignment cross
		Outer_Only =  True  -- draws only the outer features on each layer: Inner_Cross_Layer, Outer_Cross_Layer
		if Outer_Cross_Thickness == 0 only the inner features are drawn on each layer: Inner_Cross_Layer, Outer_Cross_Layer
		"""

		Inner_Cross_Thickness = float(Inner_Cross_Thickness)
		Outer_Cross_Thickness = float(Outer_Cross_Thickness)
		Outer_Cross_Width = float(Outer_Cross_Width)
		if arg is not ():
			ang = arg[0]
		else:
			ang = 0

		def draw_cross(Layer,cross_line_width,cross_width):
			"""cross_line_width is line width of cross
			cross_width is Overall width and height of cross """
			P_1 = gdspy.Path(cross_line_width, (-cross_width/2, 0))
			P_1.segment(cross_width, '+x', layer = Layer)
			P_2 = gdspy.Path(cross_line_width, (0,-cross_width/2))
			P_2.segment((cross_width/2)-(cross_line_width/2), '+y', layer = Layer)
			P_3 = gdspy.Path(cross_line_width, (P_2.x,P_2.y+cross_line_width))
			P_3.segment((cross_width/2)-(cross_line_width/2), '+y', layer = Layer)
			return P_1.polygons+P_2.polygons+ P_3.polygons

		def draw_guide_lines(Layer,Line_Width_Start,Length,Steps):
			polygons = []
			for i in xrange(1,Steps+1):
				polygons.append(gdspy.Path(Line_Width_Start*i,(Outer_Cross_Width/2 + Inner_Cross_Thickness +(i-1)*(Length/Steps),0)).segment(Length/Steps,'+x',layer = Layer).polygons)
			for i in xrange(1,Steps+1):
				polygons.append(gdspy.Path(Line_Width_Start*i,(-(Outer_Cross_Width/2 + Inner_Cross_Thickness +(i-1)*(Length/Steps)),0)).segment(Length/Steps,'-x', layer = Layer).polygons)
			return 	reduce(lambda x, y: x+y,polygons)

		cross_line_width = Inner_Cross_Thickness  #line width of cross
		cross_width = Outer_Cross_Width - 2*Outer_Cross_Thickness # overall width and height of cross

		i = draw_cross(Inner_Cross_Layer,cross_line_width,cross_width)
		inner_cross_poly_set = gdspy.PolygonSet(i, layer =Inner_Cross_Layer ).rotate(ang, center=(0, 0))

		if Outer_Cross_Thickness==0:
			o = draw_cross(Outer_Cross_Layer,cross_line_width,cross_width)
			outer_cross_poly_set = gdspy.PolygonSet(o, layer =Outer_Cross_Layer ).rotate(ang, center=(0, 0))
		else:
			o = draw_cross(Outer_Cross_Layer,3*cross_line_width,Outer_Cross_Width)
			primitives = [gdspy.PolygonSet(i, layer = 0),gdspy.PolygonSet( o, layer = 0)]
			subtraction = lambda p1, p2: p2 and not p1
			outer_cross_poly_set = gdspy.boolean( primitives, subtraction, max_points=199,layer =Outer_Cross_Layer).rotate(ang, center=(0, 0))
		
		if Outer_Only == True:
			inner_cross_poly_set = gdspy.boolean( primitives, subtraction, max_points=199,layer =Inner_Cross_Layer ).rotate(ang, center=(0, 0))
		poly_set_list = [inner_cross_poly_set, outer_cross_poly_set]

		if Guidelines == True:
			guide_line_length = 5*Outer_Cross_Width
			num_steps = 3
			gi = draw_guide_lines(Inner_Cross_Layer,Inner_Cross_Thickness,guide_line_length,num_steps)
			inner_guide_line_poly_set = gdspy.PolygonSet( gi, layer =Inner_Cross_Layer )

			if Outer_Cross_Thickness==0:
				go = draw_guide_lines(Outer_Cross_Layer,Inner_Cross_Thickness,guide_line_length,num_steps)
				outer_guide_line_poly_set = gdspy.PolygonSet( go, layer =Outer_Cross_Layer )
			else:
				go = draw_guide_lines(Outer_Cross_Layer,2*Outer_Cross_Thickness+Inner_Cross_Thickness ,guide_line_length,num_steps)
				primitives = [gdspy.PolygonSet(gi, layer = 0),gdspy.PolygonSet( go, layer = 0 )]
				subtraction = lambda p1, p2: p2 and not p1
				outer_guide_line_poly_set = gdspy.boolean(primitives, subtraction, max_points=199, layer =Inner_Cross_Layer )
			
			if Outer_Only == True:
				inner_guide_line_poly_set = gdspy.boolean(primitives, subtraction, max_points=199, layer =Inner_Cross_Layer )

			poly_set_list.append(inner_guide_line_poly_set)
			poly_set_list.append(outer_guide_line_poly_set)

		align_cell = gdspy.Cell('Alignment_Mark', exclude_from_global=True)
		align_cell.add(poly_set_list)	
		return align_cell
Exemple #38
0
    "6,5 -2,2 0,5 2,2 7,0 0,11 3,0 0,-18 -2,-2",
]


paths = []
for s in spaths:
    p = [np.array(v.split(','), dtype='f8') for v in s.split(' ')]
    p = [np.sum(p[:i + 1], 0) for i in range(len(p))]
    p = [np.array((v[0], H - v[1])) for v in p]
    paths.append(p)


invcells = []
for i, p in enumerate(paths):
    r = gdspy.Rectangle((0, 0), (W, H), layer=0)
    pol = gdspy.boolean([r, p], lambda r, p: r and not p, layer=WGTEXT)
    c = gdspy.Cell("ifont_%1d" % i, exclude_from_global=True)
    c.add(pol)
    invcells.append(c)


invtextid = 0
def invtext(text, height=12):
    global invtextid
    c = gdspy.Cell("invtext_%04d" % int(invtextid), exclude_from_global=True)
    invtextid += 1
    mag = float(height) / H
    for i, l in enumerate(text):
        if l not in "0123456789":
            raise TypeError("DONT KNOW HOW TO MAKE LETTERS \"%s\"." % l)
        c.add(gdspy.CellReference(
import gdspy

bool_cell = gdspy.Cell('BOOLEAN')
liPolygon = []

liUnitDummy = []
yPitch=6
for i in range(4):
    yMove = i*yPitch
    liUnitDummy.append(gdspy.Rectangle(51, (0, yMove+3), (18, yMove)).points)


frame_poly = gdspy.Rectangle(11,(-10,30),(30,-10)).points
frame_poly_list = [frame_poly]

#liPolygon.append(liUnitDummy)
subtraction = lambda p1, p2: p2 and not p1
bool_cell.add(gdspy.boolean(1,[gdspy.PolygonSet(0,liUnitDummy), gdspy.PolygonSet(0,frame_poly_list)], subtraction, max_points=199))
#bool_cell.add(gdspy.PolygonSet(1, liUnitDummy[0]+liUnitDummy[1]+liUnitDummy[2]+liUnitDummy[3]))
#bool_cell.add(liUnitDummy)






name = os.path.abspath(os.path.dirname(os.sys.argv[0])) + os.sep +\
       'gdspy-autodummy'
gdspy.gds_print(name + '.gds', unit=1.0e-6, precision=1.0e-9)
gdspy.LayoutViewer()
Exemple #40
0
    ## We create a PolygonSet that contains both our path segments and
    ## ring, and then append it to our list of operands.
    primitives.append(gdspy.PolygonSet(bool_path.polygons +
                                       ring.polygons))

## The list of operands contains 2 polygon sets.  We will subtract the
## 1st (narrower) from the 2nd (wider).  For that we need to define a
## function that receives 2 integers (each representing an operand) and
## returns the operation we want executed. Here we use a lambda
## expression to do so.
subtraction = lambda p1, p2: p2 and not p1

## We perform the operation, put the resulting polygons in layer 1, and
## add to our boolean cell.
bool_cell.add(gdspy.boolean(primitives, subtraction, max_points=199,
                            layer=1))


## ------------------------------------------------------------------ ##
##      POLYGON OFFSET
## ------------------------------------------------------------------ ##

## Polygon offset (inset and outset) can be used, for instance, to
## define safety margins around shapes.

spec = {'layer': 7}
path4 = gdspy.Path(0.5, (21, -5)).segment(3, '+x', **spec)\
        .turn(4, 'r', **spec).turn(4, 'rr', **spec)\
        .segment(3, **spec)
path_cell.add(path4)
Exemple #41
0
def Draw_Sensor(Sensor_Number, Through_Line_Layer = 1, Resonator_Trace_Layer = 2, Pillar_Layer = 3):
	'''
	This Function draws a sensor. It positions the resonators according to the mask definition input files. 
	Its also draws the pillars outside of the bounding box of the resonators, the sensor die cut lines and
	the through line.
	Origin of the Sensor is the lower left corner.
	'''

	#For Test Only! Remove when deployed
	#gdspy.Cell.cell_dict = {}

	# Obtain Sensor Parameters
	Sensor_Params = Mask_DB.Get_Mask_Data("SELECT X_Length, Y_Length, Cut_Line_Width, Pillar_Diameter, Pillar_Grid_Spacing, Pillar_Clearance, Through_Line_Type, Through_Line_Width, Through_Line_Turn_Radius,Through_Line_Gap, Through_Line_Edge_Offset FROM Sensors WHERE sensor_id = " + str(Sensor_Number),'all')
	#sql_cmd = "SELECT X_Length, Y_Length, Cut_Line_Width, Pillar_Diameter, Pillar_Grid_Spacing, Pillar_Clearance, Through_Line_Type, Through_Line_Width, Through_Line_Turn_Radius,Through_Line_Gap, Through_Line_Edge_Offset FROM Sensors WHERE Sensor = " + str(Sensor_Number)
	#Cursor.execute(sql_cmd)
	#Sensor_Params = Cursor.fetchall()

	#There should only be one sensor returned from database. We make sure of this.
	if len(Sensor_Params) > 1:
		print("Something is wrong. There are more than one senor #" + str(Sensor_Number) + ". Using the first one pulled.")

	Pillar_Grid_Spacing_Reduction_Factor = 3.0

	X_Length, Y_Length, Cut_Line_Width, Pillar_Diameter, Pillar_Grid_Spacing, Pillar_Clearance, Through_Line_Type, Through_Line_Width, Through_Line_Turn_Radius,Through_Line_Gap, Through_Line_Edge_Offset = Sensor_Params[0]
	Pillar_Radius = Pillar_Diameter/2
	Pillar_Grid_Spacing = Pillar_Grid_Spacing*Pillar_Grid_Spacing_Reduction_Factor
	#Initialize Sensor Cell
	sensor_cell_name = 'SENSOR_'+str(Sensor_Number)
	sensor_cell = gdspy.Cell(sensor_cell_name,exclude_from_global=True)


	
	
	# We draw the cut lines by boolean operation on two squares defining the die outline
	poly1 = gdspy.Rectangle(Resonator_Trace_Layer, (0, 0), (X_Length, Y_Length))
	poly2 = gdspy.Rectangle(Resonator_Trace_Layer, (Cut_Line_Width, Cut_Line_Width), (X_Length-Cut_Line_Width, Y_Length-Cut_Line_Width))
	primitives = [poly2,poly1]
	subtraction = lambda p1, p2: p2 and not p1
	sensor_cell.add(gdspy.boolean(Resonator_Trace_Layer, primitives, subtraction, max_points=199))

	#Bare sensor cell is sensor cell without text and cutlines
	bare_sensor_cell_name = 'BARE_'+sensor_cell_name
	bare_sensor_cell = gdspy.Cell(bare_sensor_cell_name,exclude_from_global=False)

	#Add the name of the sensor in the lower left of the die
	Text_Offset = 100
	sensor_cell.add(gdspy.Text(Resonator_Trace_Layer, 'S' + str(Sensor_Number), 300, (Cut_Line_Width+Text_Offset, Cut_Line_Width+Text_Offset)))

	#Draw Throughline
	#assuming L shape
 	Though_Line_Trace = gdspy.Path(Through_Line_Width, (X_Length/2, 0))
 	Though_Line_Trace.segment(Through_Line_Layer, Through_Line_Edge_Offset + Through_Line_Width/2 - Through_Line_Turn_Radius, '+y')
 	Though_Line_Trace.turn(Through_Line_Layer, Through_Line_Turn_Radius, 'l')
	Though_Line_Trace.segment(Through_Line_Layer, (X_Length/2)-Through_Line_Edge_Offset-Through_Line_Width/2 - 2*Through_Line_Turn_Radius, '-x')
	Though_Line_Trace.turn(Through_Line_Layer, Through_Line_Turn_Radius, 'r')
	Though_Line_Trace.segment(Through_Line_Layer, Y_Length-2*Through_Line_Edge_Offset-Through_Line_Width - 2*Through_Line_Turn_Radius, '+y')
	_res_x_zero = Though_Line_Trace.x
	Though_Line_Trace.turn(Through_Line_Layer, Through_Line_Turn_Radius, 'r')
	_res_y_zero = Though_Line_Trace.y	
	Though_Line_Trace.segment(Through_Line_Layer, (X_Length/2)-Through_Line_Edge_Offset-Through_Line_Width/2 - 2*Through_Line_Turn_Radius, '+x')
	Though_Line_Trace.turn(Through_Line_Layer, Through_Line_Turn_Radius, 'l')
	Though_Line_Trace.segment(Through_Line_Layer, Through_Line_Edge_Offset + Through_Line_Width/2 - Through_Line_Turn_Radius, '+y')

	bare_sensor_cell.add(Though_Line_Trace)

	#This is a test rectange to check the through line placement
	#sensor_cell.add(gdspy.Rectangle(Resonator_Trace_Layer, (Through_Line_Edge_Offset, Through_Line_Edge_Offset), (Through_Line_Edge_Offset+Through_Line_Width/2 + Through_Line_Turn_Radius, Through_Line_Edge_Offset+Through_Line_Width/2 + Through_Line_Turn_Radius)))
	
	#Starting position of first resonator
	_res_x_zero += (Through_Line_Width/2)
	_res_y_zero += (-Through_Line_Width/2)
	_cur_Res_y_pos = _res_y_zero


	Res_IDs = Mask_DB.Get_Mask_Data("SELECT resonator_id, Coupler_Zone, Head_Space, Design_Freq,Design_Q FROM Resonators WHERE sensor_id = " + str(Sensor_Number),'all')
	#sql_cmd = "SELECT Design_Freq, Width, Design_Q, Head_Space, Coupler_Zone, Meander_Pitch, Meander_Zone FROM Resonators WHERE Sensor = " + str(Sensor_Number)
	#Cursor.execute(sql_cmd)
	#Res_IDs = Cursor.fetchall()
	

	
	#For boolean subtraction, however does not work due to insufficient memory
	# #Initialize Resonator Mask Cell, which will contain rectangles positioned over the resonators
	# res_mask_cell_name = 'S'+str(Sensor_Number)+'ResMask'
	# res_mask_cell = gdspy.Cell(res_mask_cell_name, exclude_from_global=True)

	_pillar_x_index = (Pillar_Grid_Spacing+Pillar_Diameter)/2
	_pillar_y_index = Y_Length - (Pillar_Grid_Spacing+Pillar_Diameter)/2

	Res_Number = 1

	
	for ID in Res_IDs:
		resonator_id,Coupler_Zone, Head_Space,Design_Freq,Design_Q = ID
		Resonator_Name = 'F' + str(Design_Freq) + ' Qc' + str(int(Design_Q)) + ' R' + str(resonator_id)
		#Resonator_Name = 'S' + str(Sensor_Number) + 'R' + str(Res_Number) + '#' + str(resonator_id)
		resonator_cell,_y_initial = Draw_Resonator(Resonator_Name=Resonator_Name,Resonator_ID=resonator_id, Resonator_Trace_Layer = Resonator_Trace_Layer, Pillar_Layer = Pillar_Layer, Y_Pitch_Tight = True, X_Pitch_Tight = True,Update_DB = True)

		_cur_Res_x_pos = Coupler_Zone + _res_x_zero
		_cur_Res_y_pos += -Head_Space-_y_initial
		_curr_Res_ref =  gdspy.CellReference(resonator_cell, (_cur_Res_x_pos, _cur_Res_y_pos))
		bare_sensor_cell.add(_curr_Res_ref)
		_bounding_box_edges = resonator_cell.get_bounding_box() + np.array([[_cur_Res_x_pos, _cur_Res_y_pos],[_cur_Res_x_pos, _cur_Res_y_pos]])
		#sensor_cell.add(  gdspy.Rectangle(Through_Line_Layer, (_bounding_box_edges[0][0], _bounding_box_edges[0][1]), (_bounding_box_edges[1][0], _bounding_box_edges[1][1])))

		#For boolean subtraction, however does not work due to insufficient memory
		#res_mask_cell.add(gdspy.Rectangle(Through_Line_Layer, (_bounding_box_edges[0][0], _bounding_box_edges[0][1]), (_bounding_box_edges[1][0], _bounding_box_edges[1][1])))

		#_total_x_distance = _bounding_box_edges[1][0] - _bounding_box_edges[0][0] #not used currently
		_total_y_distance = _bounding_box_edges[1][1] - _bounding_box_edges[0][1]
		_cur_Res_y_pos += -_total_y_distance 

		while _pillar_y_index >= _cur_Res_y_pos:
			while _pillar_x_index <= X_Length - Pillar_Radius:
				if not in_rectangle((_pillar_x_index, _pillar_y_index),_bounding_box_edges,Pillar_Radius):#Pillar_Radius+Pillar_Grid_Spacing):
					bare_sensor_cell.add(gdspy.Round(Pillar_Layer, (_pillar_x_index, _pillar_y_index), Pillar_Radius,number_of_points=60))
				_pillar_x_index += Pillar_Grid_Spacing
			_pillar_x_index = (Pillar_Grid_Spacing+Pillar_Diameter)/2
			_pillar_y_index -= Pillar_Grid_Spacing

		Res_Number += 1 
	
	while _pillar_y_index >= Pillar_Radius:
		while _pillar_x_index <= X_Length - Pillar_Radius:
			bare_sensor_cell.add(gdspy.Round(Pillar_Layer, (_pillar_x_index, _pillar_y_index), Pillar_Radius,number_of_points=60))
			_pillar_x_index += Pillar_Grid_Spacing
		_pillar_x_index = (Pillar_Grid_Spacing+Pillar_Diameter)/2
		_pillar_y_index -= Pillar_Grid_Spacing
	
	bare_sensor_cell_ref =  gdspy.CellReference(bare_sensor_cell, (0,0))
	sensor_cell.add(bare_sensor_cell_ref)	

	Sensor_Dict = {"Through_Line_Metal_Area":Though_Line_Trace.area(),"Through_Line_Length":Though_Line_Trace.length, "Sensor_Pillar_Area": sensor_cell.area(by_layer=True)[Pillar_Layer], "sensor_id":Sensor_Number, "Sensor_Cell_Name":'"'+bare_sensor_cell_name+'"'}
	for ID in Res_IDs:
		resonator_id = ID[0]
		Mask_DB.Update_Computed_Parameters(resonator_id, Sensor_Dict)

	#Insufficuent Memory to perform boolean subtraction below
	# #Initialize Pillar Cell, which will contain a grid of pillars for the sensor
	# pillar_cell_name = 'S'+str(Sensor_Number)+'Pillars'
	# pillar_cell = gdspy.Cell(pillar_cell_name, exclude_from_global=True)
	# pillar_cell.add(gdspy.Round(Pillar_Layer, (0, 0), Pillar_Radius))
	# #Perform boolean subtraction of resonator mask rectangels
	# num_pillars_x =  (X_Length-Pillar_Grid_Spacing-2*Pillar_Radius)%Pillar_Grid_Spacing
	# num_pillars_y =  (Y_Length-Pillar_Grid_Spacing-2*Pillar_Radius)%Pillar_Grid_Spacing
	# primitives = [gdspy.CellReference(res_mask_cell),gdspy.CellArray(pillar_cell, int(num_pillars_x), int(num_pillars_y), (Pillar_Grid_Spacing, Pillar_Grid_Spacing) ,(Pillar_Grid_Spacing/2 + Pillar_Radius, Pillar_Grid_Spacing/2 + Pillar_Radius),magnification=1)]
	# sensor_cell.add(gdspy.boolean(Pillar_Layer, primitives, sub, max_points=199))


	# name = os.path.abspath(os.path.dirname(os.sys.argv[0])) + os.sep + 'single_sensor'

	# ## Output the layout to a GDSII file (default to all created cells).
	# ## Set the units we used to micrometers and the precision to nanometers.
	# gdspy.gds_print(name + '.gds', unit=1.0e-6, precision=1.0e-9)
	# print('Sample gds file saved: ' + name + '.gds')

	# ## Save an image of the boolean cell in a png file.  Resolution refers
	# ## to the number of pixels per unit in the layout. Resolution changed from 4
	# ## to 1 to avoid  "malloc_error"
	# #gdspy.gds_image([resonator_cell], image_name=name, resolution=1, antialias=4)

	# #comment out save as png for speed
	# #print('Image of the boolean cell saved: ' + name + '.png')

	# ## Import the file we just created, and extract the cell 'POLYGONS'. To
	# ## avoid naming conflict, we will rename all cells.
	# #gdsii = gdspy.GdsImport(name + '.gds', rename={sensor_cell_name:'IMPORT_SENSOR'})

	# ## Now we extract the cells we want to actually include in our current
	# ## structure. Note that the referenced cells will be automatically
	# ## extracted as well.
	# #gdsii.extract(sensor_cell_name)
	    
	# ## View the layout using a GUI.  Full description of the controls can
	# ## be found in the online help at http://gdspy.sourceforge.net/
	# gdspy.LayoutViewer(colors=[None] * 64) # for outlined polygons
	# #gdspy.LayoutViewer()
	return sensor_cell