def makeYShapes(self, length, width, rotAngle, spacing, Nx, Ny, layers):
        if not (type(layers) == list): layers = [layers]
        pt1 = np.array((0, -width / 2.))
        pt2 = np.array((length, width / 2.))
        slit = Cell("Slit")
        for l in layers:
            rect = Rectangle(pt1, pt2, layer=l)
            slit.add(rect)
            shape = Cell('Shapes')
            shape.add(slit, rotation=0 + rotAngle)
            shape.add(slit, rotation=120 + rotAngle)
            shape.add(slit, rotation=240 + rotAngle)

            #            CellArray(slit, Nx, Ny,(length + spacing, pitchV))
            xspacing = length + spacing
            yspacing = (length + spacing) * np.sin(np.deg2rad(60))
            shapearray = CellArray(
                shape,
                Nx,
                Ny / 2, (xspacing, yspacing * 2.),
                origin=(-(Nx * xspacing - spacing) / 2.,
                        -(Ny * yspacing - spacing * np.sin(np.deg2rad(60))) /
                        2.))
            shapearray2 = CellArray(
                shape,
                Nx,
                Ny / 2, (xspacing, yspacing * 2.),
                origin=(
                    xspacing / 2. - (Nx * xspacing - spacing) / 2., yspacing -
                    (Ny * yspacing - spacing * np.sin(np.deg2rad(60))) / 2.))

            allshapes = Cell('All Shapes')
            allshapes.add(shapearray)
            allshapes.add(shapearray2)
            self.add(allshapes)
Ejemplo n.º 2
0
    def build_and_add_blocks(self):
        """
        Create blocks and add them to the wafer Cell
        """

        self.upCellLattice = self.getCellLattice(cellsize=2000)
        # Create a cell for the triangular blocks
        block_up = Cell('upblock')
        for x, y in self.upCellLattice:
            block_up.add(self.cells, origin=(x, y))
        # Take each point in block lattice and make a copy of the block in that location
        for x, y in self.upCenters:
            self.add(block_up, origin=(x, y))

        if self.symmetric_chips:
            for x, y in self.downCenters:
                self.add(block_up, origin=(x, y), rotation=180)
        else:
            self.downCellLattice = np.array(self.upCellLattice) * np.array(
                [1, -1])
            block_down = Cell('downblock')
            for x, y in self.downCellLattice:
                block_down.add(self.cells, origin=(x, y))
            for x, y in self.downCenters:
                self.add(block_down, origin=(x, y))
    def add_tem_nanowires(self):
        size = 500
        y_offset = 1300
        shapes_big = make_shape_array(size,
                                      0.02,
                                      0.5,
                                      'Tris_right',
                                      l_smBeam,
                                      labels=False)
        shapes_small = make_shape_array(size,
                                        0.005,
                                        0.5,
                                        'Tris_right',
                                        l_smBeam,
                                        labels=False)
        tem_shapes = Cell('TEMShapes')
        # tem_shapes.add(shapes_big, origin=(2200 - size / 2., y_offset - size / 2.))
        tem_shapes.add(shapes_small,
                       origin=(-2200 - size / 2., y_offset - size / 2.))

        for x, y in self.upCenters:
            self.add(tem_shapes, origin=(x, y))
        for x, y in self.downCenters:
            self.add(tem_shapes, origin=(
                x, y - 2 * y_offset))  # Don't rotate because of directionality
 def make_many_shapes(self, array_size, shape_areas, pitch, shapes, skew,
                      layer):
     offset_x = array_size * 1.25
     offset_y = array_size * 1.25
     cur_y = 0
     many_shape_cell = Cell('ManyShapes')
     for area in shape_areas:
         cur_x = 0
         for shape in shapes:
             write_top_labels = cur_y == 0
             write_side_labels = cur_x == 0
             s_array = self.make_shape_array(array_size,
                                             area,
                                             pitch,
                                             shape,
                                             layer,
                                             skew,
                                             toplabels=write_top_labels,
                                             sidelabels=write_side_labels)
             many_shape_cell.add(s_array,
                                 origin=(cur_x - array_size / 2.,
                                         cur_y - array_size / 2.))
             cur_x += offset_x
         cur_y -= offset_y
     self.add(many_shape_cell,
              origin=(-offset_x * (len(shapes) - 1) / 2.,
                      offset_y * (len(skews) - 1) / 2.))
    def add_theory_cell(self):

        theory_cells = Cell('TheoryCells')
        theory_cells.add(make_theory_cell(), origin=(-200, 0))
        theory_cells.add(make_theory_cell_br(), origin=(200, 0))

        self.block_up.add(theory_cells, origin=(0, 1300))
        self.block_down.add(theory_cells, origin=(0, -1300))
 def frame_label(self, label_txt, size, beam):
     text = Label(label_txt, size, layer=beam)
     lblVertOffset = 0.4
     text.translate(tuple(
         np.array(-text.bounding_box.mean(0))))  # Center justify label
     lbl_cell = Cell('frame_label')
     lbl_cell.add(text)
     self.add(lbl_cell, origin=(0, self.size_y * lblVertOffset / 2.))
    def add_chip_labels(self):
        wafer_lbl = PATTERN + '\n' + WAFER_ID
        text = Label(wafer_lbl, 20., layer=l_lgBeam)
        text.translate(tuple(
            np.array(-text.bounding_box.mean(0))))  # Center justify label
        chip_lbl_cell = Cell('chip_label')
        chip_lbl_cell.add(text)

        self.block_up.add(chip_lbl_cell, origin=(0, -3000))
        self.block_down.add(chip_lbl_cell, origin=(0, 3000))
Ejemplo n.º 8
0
    def add_wafer_outline(self, layers):
        """
        Create Wafer Outline
        """
        if not (type(layers) == list): layers = [layers]

        outline = Cell('WAF_OLINE')
        for l in layers:
            circ = Circle((0, 0), self.wafer_r, 100, layer=l)
            outline.add(circ)
        self.add(outline)
    def add_theory_cell(self):

        theory_cells = Cell('TheoryCells')
        theory_cells.add(make_theory_cell(), origin=(-200, 0))
        theory_cells.add(make_theory_cell_br(), origin=(200, 0))

        for x, y in self.upCenters:
            self.add(theory_cells, origin=(x, y + 1300))
        for x, y in self.downCenters:
            self.add(theory_cells, origin=(
                x, y - 1300
            ))  # Don't rotate because of directionality of branched membranes
    def add_chip_labels(self):
        wafer_lbl = "AN1.3\n" + WAFER_ID
        text = Label(wafer_lbl, 20., layer=l_lgBeam)
        text.translate(tuple(
            np.array(-text.bounding_box.mean(0))))  # Center justify label
        chip_lbl_cell = Cell('chip_label')
        chip_lbl_cell.add(text)

        for x, y in self.upCenters:
            self.add(chip_lbl_cell, origin=(x, y - 3000))
        for x, y in self.downCenters:
            self.add(chip_lbl_cell, origin=(x, y + 3000))
 def processCheck_CleavingMark(self, yPosition, layers):
     if not (type(layers) == list): layers = [layers]
     for l in layers:
         pt1 = (100, yPosition)
         pt2 = (2000, yPosition)
         pt3 = (-1100, yPosition)
         pt4 = (-2800, yPosition)
         line1 = Path([pt1, pt2], width=10, layer=l)
         line2 = Path([pt3, pt4], width=10, layer=l)
         cMarkCell = Cell('Cleaving Mark')
         cMarkCell.add(line1)
         cMarkCell.add(line2)
         self.add(cMarkCell)
    def makeArrowShape(self, length, width, rotAngle, spacing, Nx, Ny, layers):
        if not (type(layers) == list): layers = [layers]
        pt1 = np.array((-width * 0.3, -width / 2.))
        pt2 = np.array((length, width / 2.))
        slit = Cell("Slit")
        for l in layers:
            rect = Rectangle(pt1, pt2, layer=l)
            slit.add(rect)
            shape = Cell('Shapes')
            shape.add(slit, rotation=-120)
            shape.add(slit, rotation=120)

            xspacing = (width + spacing) / np.cos(np.deg2rad(30))
            yspacing = (length + spacing / 2.) * np.sin(np.deg2rad(60))
            shapearray = CellArray(shape,
                                   Nx,
                                   Ny, (xspacing, yspacing * 2.),
                                   origin=(-(Nx * xspacing - spacing) / 2.,
                                           -(Ny * yspacing - spacing) / 2.))

            allshapes = Cell('All Shapes')
            allshapes.add(shapearray)
            #            allshapes.add(shapearray2)
            #            allshapes.add(shape)
            self.add(allshapes)
    def makeXShape(self, length, width, rotAngle, spacing, Nx, Ny, layers):
        if not (type(layers) == list): layers = [layers]
        pt1 = np.array((-length / 2., -width / 2.))
        pt2 = np.array((length / 2., width / 2.))
        slit = Cell("Slit")
        for l in layers:
            rect = Rectangle(pt1, pt2, layer=l)
            slit.add(rect)
            shape = Cell('Shapes')
            shape.add(slit, rotation=60)
            shape.add(slit, rotation=120)

            xspacing = (length + spacing) * np.cos(np.deg2rad(60))
            yspacing = (length + spacing) * np.sin(np.deg2rad(60))
            shapearray = CellArray(shape,
                                   Nx,
                                   Ny, (xspacing, yspacing),
                                   origin=(-(Nx * xspacing - spacing) / 2.,
                                           -(Ny * yspacing - spacing) / 2.))
            #            shapearray2 = CellArray(shape, Nx, Ny/2,(xspacing,yspacing*2.),origin=(xspacing/2.-(Nx*xspacing-spacing)/2.,yspacing-(Ny*yspacing-spacing*np.tan(np.deg2rad(60)))/2.))
            #            shapearray = CellArray(shape, Nx, Ny,(xspacing,yspacing))
            #            shapearray.rotate(rotAngle)
            #            shapearray.translate((-shapearray.bounding_box.mean(0)[0]/2.,-shapearray.bounding_box.mean(0)[1]/2.))

            allshapes = Cell('All Shapes')
            allshapes.add(shapearray)
            #            allshapes.add(shapearray2)
            #            allshapes.add(shape)
            self.add(allshapes)
Ejemplo n.º 14
0
 def add_orientation_text(self, layers):
     """
     Create Orientation Label
     """
     if not (type(layers) == list): layers = [layers]
     tblock = Cell('WAF_ORI_TEXT')
     for l in layers:
         for (t, pt) in list(self.o_text.items()):
             txt = Label(t, 1000, layer=l)
             bbox = txt.bounding_box
             txt.translate(-np.mean(bbox, 0))  # Center text around origin
             txt.translate(np.array(pt))
             tblock.add(txt)
     self.add(tblock)
Ejemplo n.º 15
0
def make_many_shapes(array_size, shape_areas, pitch, shapes, layer):
    offset_x = array_size * 1.25
    offset_y = array_size * 1.25
    cur_y = 0
    many_shape_cell = Cell('ManyShapes')
    for area in shape_areas:
        cur_x = 0
        for shape in shapes:
            write_labels = cur_y == 0
            s_array = make_shape_array(array_size, area, pitch, shape, layer, labels=write_labels)
            many_shape_cell.add(s_array, origin=(cur_x, cur_y))
            cur_x += offset_x
        cur_y -= offset_y
    return many_shape_cell
Ejemplo n.º 16
0
def makeSlitArray(pitches, spacing, widths, lengths, rotAngle, arrayHeight,
                  arraySpacing, layers):
    '''
    Give it a single pitch and width and it will generate an array for all the lengths
    '''
    if not (type(layers) == list): layers = [layers]
    if not (type(pitches) == list): pitches = [pitches]
    if not (type(lengths) == list): lengths = [lengths]
    if not (type(widths) == list): widths = [widths]
    for l in layers:
        i = -1
        j = -1
        manyslits = Cell("SlitArray")
        slitarray = Cell("SlitArray")
        pitch = pitches[0]
        width = widths[0]
        j += 1
        i = -1
        xlength = 0
        slit = Cell("Slits")
        for length in lengths:
            spacing = length / 5. + 0.1
            i += 1
            pitchV = pitch / np.cos(np.deg2rad(rotAngle))
            #            widthV = width / np.cos(np.deg2rad(rotAngle))
            #            Nx = int(arrayWidth / (length + spacing))
            Ny = int(arrayHeight / (pitchV))
            # Define the slits
            if xlength == 0:
                translation = (length / 2., 0)
                xlength += length
            else:
                translation = (xlength + spacing + length / 2., 0)
                xlength += length + spacing

            pt1 = np.array((-length / 2., -width / 2.)) + translation
            pt2 = np.array((length / 2., width / 2.)) + translation
            rect = Rectangle(pt1, pt2, layer=l)
            rect = rect.copy().rotate(rotAngle)
            slit.add(rect)
        slits = CellArray(slit, 1, Ny, (0, pitchV))
        # slits.translate((-(Nx - 1) * (length + spacing) / 2., -(Ny - 1)* (pitchV) / 2.))
        slits.translate(
            (-slits.bounding_box[1, 0] / 2., -slits.bounding_box[1, 1] / 2.))

        slitarray.add(slits)
        text = Label('w/p\n%i/%i' % (width * 1000, pitch * 1000), 2)
        lblVertOffset = 1.4
        text.translate(
            tuple(
                np.array(-text.bounding_box.mean(0)) +
                np.array((0, arrayHeight /
                          lblVertOffset))))  # Center justify label
        slitarray.add(text)
        #            manyslits.add(slitarray,origin=((arrayWidth + arraySpacing) * i, (arrayHeight + 2.*arraySpacing) * j-arraySpacing/2.))
        manyslits.add(slitarray)

    # self.add(manyslits, origin=(-i * (arrayWidth + arraySpacing) / 2, -j * (arrayHeight + arraySpacing) / 2))
    #    self.add(manyslits)
    return manyslits
    def add_tem_membranes(self, widths, length, pitch, layer):

        tem_membranes = Cell('TEM_Membranes')

        n = 3
        curr_y = 0
        for width in widths:
            membrane = Path([(-length / 2., 0), (length / 2., 0)],
                            width=width,
                            layer=layer)
            membrane_cell = Cell('Membrane_w{:.0f}'.format(width * 1000))
            membrane_cell.add(membrane)
            membrane_array = CellArray(membrane_cell, 1, n, (0, pitch))
            membrane_array_cell = Cell('MembraneArray_w{:.0f}'.format(width *
                                                                      1000))
            membrane_array_cell.add(membrane_array)
            tem_membranes.add(membrane_array_cell, origin=(0, curr_y))
            curr_y += n * pitch

        n2 = 5
        tem_membranes2 = Cell('Many_TEM_Membranes')
        tem_membranes2.add(
            CellArray(tem_membranes, 1, n2, (0, n * len(widths) * pitch)))

        self.block_up.add(tem_membranes2, origin=(0, -2000))
        # self.block_up.add(tem_membranes2, origin=(0, -1400), rotation=90)

        self.block_down.add(tem_membranes2, origin=(0, 2000))
    def make_align_markers(self,
                           t,
                           w,
                           position,
                           layers,
                           cross=False,
                           auto_marks=False):
        if not (type(layers) == list):
            layers = [layers]
        self.align_markers = Cell("AlignMarkers")
        self.align_marker = Cell("AlignMarker")
        for l in layers:
            if not cross:
                am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l)
                self.align_marker.add(am0)
            elif cross:
                crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t),
                            (t, w / 2), (0, w / 2), (0, 0)]
                crosspts.extend(
                    tuple(map(tuple, (-np.array(crosspts)).tolist())))

                #                crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.),
                #                            (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.),
                #                            (t / 2., -t / 2.), (t / 2., -h / 2.),
                #                            (-t / 2., -h / 2.), (-t / 2., -t / 2.),
                #                            (-w / 2., -t / 2.), (-w / 2., t / 2.)]
                am0 = Boundary(crosspts, layer=l)  # Create gdsCAD shape
                self.align_marker.add(am0)
                # am1 = Polygon(crosspts) #Create shapely polygon for later calculation

            if auto_marks:  # automatic alignment marks for the e-beam tool
                auto_mark_rect = Rectangle((-10., -10.), (10., 10.), layer=l)
                auto_mark = Cell("AutoMark")
                auto_mark.add(auto_mark_rect)
                self.align_marker.add(auto_mark, origin=(100, 100))
                self.align_marker.add(auto_mark, origin=(-100, 100))
                self.align_marker.add(auto_mark, origin=(100, -100))
                self.align_marker.add(auto_mark, origin=(-100, -100))

            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [1, 1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [-1, 1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [1, -1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [-1, -1]))
            self.add(self.align_markers)
Ejemplo n.º 19
0
def makeSlitArray3(pitches, spacing, widths, lengths, rotAngle,
                   arrayHeight, arrayWidth, arraySpacing, layers):
    '''
    Give it a single pitch and arrays for spacings/widths and it will generate an array for all the combinations
    Makes seperate frame for each pitch
    '''
    if not (type(layers) == list): layers = [layers]
    if not (type(pitches) == list): pitches = [pitches]
    if not (type(lengths) == list): lengths = [lengths]
    if not (type(widths) == list): widths = [widths]
    for l in layers:
        i = -1
        j = -1
        manyslits = Cell("SlitArray")
        length = lengths[0]
        spacing = length / 5. + 0.1  # Set the spacing between arrays
        for pitch in pitches:
            j += 1
            i = -1

            for width in widths:
                #            for pitch in pitches:
                i += 1
                if i % 3 == 0:
                    j += 1  # Move to array to next line
                    i = 0  # Restart at left
                pitchV = pitch / np.cos(np.deg2rad(rotAngle))
                #                    widthV = width / np.cos(np.deg2rad(rotAngle))
                Nx = int(arrayWidth / (length + spacing))
                Ny = int(arrayHeight / (pitchV))
                # Define the slits
                slit = Cell("Slits")
                rect = Rectangle(
                    (-length / 2., -width / 2.),
                    (length / 2., width / 2.),
                    layer=l)
                rect = rect.copy().rotate(rotAngle)
                slit.add(rect)
                slits = CellArray(slit, Nx, Ny,
                                  (length + spacing, pitchV))
                slits.translate((-(Nx - 1) * (length + spacing) / 2., -(Ny - 1) * (pitchV) / 2.))
                slitarray = Cell("SlitArray")
                slitarray.add(slits)
                text = Label('w/p/l\n%i/%i/%i' % (width * 1000, pitch * 1000, length * 1000), 2)
                lblVertOffset = 1.35
                if j % 2 == 0:
                    text.translate(
                        tuple(np.array(-text.bounding_box.mean(0)) + np.array((
                            0, -arrayHeight / lblVertOffset))))  # Center justify label
                else:
                    text.translate(
                        tuple(np.array(-text.bounding_box.mean(0)) + np.array((
                            0, arrayHeight / lblVertOffset))))  # Center justify label
                slitarray.add(text)
                manyslits.add(slitarray,
                              origin=((arrayWidth + arraySpacing) * i, (
                                  arrayHeight + 2. * arraySpacing) * j - arraySpacing / 2.))
    return manyslits
Ejemplo n.º 20
0
def dashed_line(pt1, pt2, dashlength, width, layer):
    line = LineString((pt1, pt2))
    dash_pts = np.arange(0, line.length, dashlength).tolist()
    if len(dash_pts) % 2 == 1:  # Odd number
        dash_pts.append(line.length)  # Add last point on line
    dash_pts = list(
        map(line.interpolate,
            dash_pts))  # Interpolate points along this line to make dashes
    dash_pts = [pt.xy for pt in dash_pts]
    dash_pts = np.reshape(dash_pts, (-1, 2, 2))
    lines = [
        Path(list(linepts), width=width, layer=layer) for linepts in dash_pts
    ]
    dline = Cell('DASHLINE')
    dline.add(lines)
    return dline
 def processCheck_Slits(self, position, arrayWidth, slitWidth, pitch,
                        length, rotation, layers):
     if not (type(layers) == list): layers = [layers]
     Nx = int(arrayWidth / pitch)
     Ny = 1
     for l in layers:
         # Define the slits
         slit = Cell("Slits")
         rect = Rectangle((-slitWidth / 2., -length / 2.),
                          (slitWidth / 2., length / 2.),
                          layer=l)
         slit.add(rect)
         slits = CellArray(slit, Nx, Ny, (pitch, 0))
         slits.translate((-(Nx) * (pitch) / 2., 0.))
         slits.translate(position)
         slitarray = Cell("ProcessCheckingSlits")
         slitarray.add(slits)
     self.add(slitarray)
def slit_elongation_array(pitches, spacing, widths, lengths, rot_angle,
                          array_height, array_spacing, layers):
    if not (type(layers) == list):
        layers = [layers]
    if not (type(pitches) == list):
        pitches = [pitches]
    if not (type(lengths) == list):
        lengths = [lengths]
    if not (type(widths) == list):
        widths = [widths]
    for l in layers:
        j = -1
        manyslits = Cell("SlitArray")
        slitarray = Cell("SlitArray")
        pitch = pitches[0]
        width = widths[0]
        j += 1
        i = -1
        x_length = 0
        slit = Cell("Slits")
        for length in lengths:
            spacing = length / 5. + 0.1
            i += 1
            pitch_v = pitch / np.cos(np.deg2rad(rot_angle))
            n_y = int(array_height / pitch_v)
            # Define the slits
            if x_length == 0:
                translation = (length / 2., 0)
                x_length += length
            else:
                translation = (x_length + spacing + length / 2., 0)
                x_length += length + spacing
            pt1 = np.array((-length / 2., -width / 2.)) + translation
            pt2 = np.array((length / 2., width / 2.)) + translation
            rect = Rectangle(pt1, pt2, layer=l)
            rect = rect.copy().rotate(rot_angle)
            slit.add(rect)
        slits = CellArray(slit, 1, n_y, (0, pitch_v))
        slits.translate(
            (-slits.bounding_box[1, 0] / 2., -slits.bounding_box[1, 1] / 2.))

        slitarray.add(slits)
        text = Label('w/p\n%i/%i' % (width * 1000, pitch * 1000), 2)
        lbl_vert_offset = 1.4
        text.translate(
            tuple(
                np.array(-text.bounding_box.mean(0)) +
                np.array((0, array_height /
                          lbl_vert_offset))))  # Center justify label
        slitarray.add(text)
        manyslits.add(slitarray)
    return manyslits
    def add_tem_nanowires(self):
        size = 500
        y_offset = 1000
        shapes_big = make_shape_array(size,
                                      0.02,
                                      0.5,
                                      'Tris_right',
                                      l_smBeam,
                                      labels=False)
        shapes_small = make_shape_array(size,
                                        0.005,
                                        0.5,
                                        'Tris_right',
                                        l_smBeam,
                                        labels=False)
        tem_shapes = Cell('TEMShapes')
        # tem_shapes.add(shapes_big, origin=(2200 - size / 2., y_offset - size / 2.))
        tem_shapes.add(shapes_small, origin=(-size / 2., -size / 2.))

        self.block_up.add(tem_shapes, origin=(-2200, y_offset))
        self.block_down.add(tem_shapes, origin=(2200, -y_offset))
Ejemplo n.º 24
0
    def add_blockLabels(self, layers, center=False):
        if not (type(layers) == list): layers = [layers]
        vOffsetFactor = 1.
        blocklabelsUp = Cell('BlockLabelsUp')
        h = self.upTris[0].bounds[3] - self.upTris[0].bounds[1]
        sl_lattice = self.trisize + self.block_gap / np.tan(np.deg2rad(30))
        h_lattice = np.sqrt(3.) / 2. * sl_lattice
        base = h_lattice
        for tri in self.upTris:
            lbl_col = self.blockcols[np.round(tri.centroid.x, 8)]
            lbl_row = self.blockrows[base * round(float(tri.bounds[1]) / base)]

            blockid = str(lbl_col) + str(lbl_row)
            blocklabel = Cell('LBL_B_' + blockid)
            for l in layers:
                txt = Label(blockid, 1000, layer=l)
                bbox = txt.bounding_box
                offset = np.array(tri.centroid)
                txt.translate(-np.mean(bbox, 0))  # Center text around origin
                txt.translate(offset)  # Translate it to bottom of wafer
                blocklabel.add(txt)
                blocklabelsUp.add(blocklabel)
        if center:
            self.add(blocklabelsUp)
        else:
            self.add(blocklabelsUp, origin=(0, h / 2. * vOffsetFactor))

        blocklabelsDown = Cell('BlockLabelsDown')
        for tri in self.downTris:
            lbl_col = self.blockcols[np.round(tri.centroid.x, 8)]
            lbl_row = self.blockrows[base * round(float(tri.bounds[1]) / base)]

            blockid = str(lbl_col) + str(lbl_row)
            blocklabel = Cell('LBL_' + blockid)
            for l in layers:
                txt = Label(blockid, 1000, layer=l)
                bbox = txt.bounding_box
                offset = np.array(tri.centroid)
                txt.translate(-np.mean(bbox, 0))  # Center text around origin
                if self.symmetric_chips:
                    txt.rotate(180)
                txt.translate(offset)  # Translate it to bottom of wafer
                blocklabel.add(txt)
                blocklabelsDown.add(blocklabel)
        if center:
            self.add(blocklabelsDown)
        else:
            self.add(blocklabelsDown, origin=(0, -h / 2. * vOffsetFactor))
def make_branch(length, width, layers, rot_angle=0):
    pt1 = np.array((0, -width / 2.))
    pt2 = np.array((length, width / 2.))

    slit = Cell("Slit")
    for l in layers:
        rect = Rectangle(pt1, pt2, layer=l)
        slit.add(rect)

    branch = Cell('Branch-{}/{}-lw'.format(length, width))
    branch.add(slit, rotation=0 + rot_angle)
    branch.add(slit, rotation=120 + rot_angle)
    branch.add(slit, rotation=240 + rot_angle)
    return branch
    def make_shape_array(self,
                         array_size,
                         shape_area,
                         shape_pitch,
                         type,
                         layer,
                         skew,
                         toplabels=False,
                         sidelabels=False):
        num_of_shapes = int(np.ceil(array_size / shape_pitch))
        base_cell = Cell('Base')

        if 'tris' in type.lower():
            triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4)
            tri_shape = scale(
                RegPolygon([0, 0], triangle_side, 3, layer=layer), [skew, 1.0])
            tri_cell = Cell('Tri')
            tri_cell.add(tri_shape)
            if 'right' in type.lower():
                base_cell.add(tri_cell, rotation=0)
            elif 'left' in type.lower():
                base_cell.add(tri_cell, rotation=-180)
            elif 'down' in type.lower():
                base_cell.add(tri_cell,
                              rotation=30)  # not working for skew yet
            elif 'up' in type.lower():
                base_cell.add(tri_cell,
                              rotation=-30)  # not working for skew yet
        elif type.lower() == "circles":
            circ_radius = np.sqrt(shape_area / np.pi)
            circ = scale(Disk([0, 0], circ_radius, layer=layer), [skew, 1.0])
            base_cell.add(circ)
        elif type.lower() == 'hexagons':
            hex_side = np.sqrt(shape_area / 6. / np.sqrt(3) * 4)
            hex_shape = scale(RegPolygon([0, 0], hex_side, 6, layer=layer),
                              [skew, 1.0])
            hex_cell = Cell('Hex')
            hex_cell.add(hex_shape)
            base_cell.add(hex_cell, rotation=0)

        shape_array = CellArray(base_cell, num_of_shapes, num_of_shapes,
                                [shape_pitch, shape_pitch])
        shape_array_cell = Cell('Shape Array')
        shape_array_cell.add(shape_array)

        lbl_dict = {
            'hexagons': 'hex',
            'circles': 'circ',
            'tris_right': 'triR',
            'tris_left': 'triL'
        }

        if toplabels:
            text = Label('{}'.format(lbl_dict[type.lower()]), 2, layer=layer)
            lblVertOffset = 0.8
            text.translate(
                tuple(
                    np.array(-text.bounding_box.mean(0)) +
                    np.array((array_size / 2., array_size /
                              lblVertOffset))))  # Center justify label
            shape_array_cell.add(text)
        if sidelabels:
            text = Label('a={:.0f}knm2'.format(shape_area * 1000),
                         2,
                         layer=layer)
            lblHorizOffset = 1.5
            text.translate(
                tuple(
                    np.array(-text.bounding_box.mean(0)) +
                    np.array((-array_size / lblHorizOffset,
                              array_size / 2.))))  # Center justify label
            shape_array_cell.add(text)

        return shape_array_cell
class Frame(Cell):
    """
    Make a frame for writing to with ebeam lithography
    Params:
    -name of the frame, just like when naming a cell
    -size: the size of the frame as an array [xsize,ysize]
    """
    def __init__(self, name, size, border_layers):
        if not (type(border_layers) == list):
            border_layers = [border_layers]
        Cell.__init__(self, name)
        self.size_x, self.size_y = size
        # Create the border of the cell
        for l in border_layers:
            self.border = Box((-self.size_x / 2., -self.size_y / 2.),
                              (self.size_x / 2., self.size_y / 2.),
                              1,
                              layer=l)
            self.add(self.border)  # Add border to the frame

        self.align_markers = None

    def frame_label(self, label_txt, size, beam):
        text = Label(label_txt, size, layer=beam)
        lblVertOffset = 0.4
        text.translate(tuple(
            np.array(-text.bounding_box.mean(0))))  # Center justify label
        lbl_cell = Cell('frame_label')
        lbl_cell.add(text)
        self.add(lbl_cell, origin=(0, self.size_y * lblVertOffset / 2.))

    def make_align_markers(self,
                           t,
                           w,
                           position,
                           layers,
                           cross=False,
                           auto_marks=False):
        if not (type(layers) == list):
            layers = [layers]
        self.align_markers = Cell("AlignMarkers")
        self.align_marker = Cell("AlignMarker")
        for l in layers:
            if not cross:
                am0 = Rectangle((-w / 2., -w / 2.), (w / 2., w / 2.), layer=l)
                self.align_marker.add(am0)
            elif cross:
                crosspts = [(0, 0), (w / 2., 0), (w / 2., t), (t, t),
                            (t, w / 2), (0, w / 2), (0, 0)]
                crosspts.extend(
                    tuple(map(tuple, (-np.array(crosspts)).tolist())))

                #                crosspts = [(-t / 2., t / 2.), (-t / 2., h / 2.), (t / 2., h / 2.),
                #                            (t / 2., t / 2.), (w / 2., t / 2.), (w / 2., -t / 2.),
                #                            (t / 2., -t / 2.), (t / 2., -h / 2.),
                #                            (-t / 2., -h / 2.), (-t / 2., -t / 2.),
                #                            (-w / 2., -t / 2.), (-w / 2., t / 2.)]
                am0 = Boundary(crosspts, layer=l)  # Create gdsCAD shape
                self.align_marker.add(am0)
                # am1 = Polygon(crosspts) #Create shapely polygon for later calculation

            if auto_marks:  # automatic alignment marks for the e-beam tool
                auto_mark_rect = Rectangle((-10., -10.), (10., 10.), layer=l)
                auto_mark = Cell("AutoMark")
                auto_mark.add(auto_mark_rect)
                self.align_marker.add(auto_mark, origin=(100, 100))
                self.align_marker.add(auto_mark, origin=(-100, 100))
                self.align_marker.add(auto_mark, origin=(100, -100))
                self.align_marker.add(auto_mark, origin=(-100, -100))

            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [1, 1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [-1, 1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [1, -1]))
            self.align_markers.add(self.align_marker,
                                   origin=tuple(np.array(position) * [-1, -1]))
            self.add(self.align_markers)

    # TODO: Center array around the origin
    def make_shape_array(self,
                         array_size,
                         shape_area,
                         shape_pitch,
                         type,
                         layer,
                         skew,
                         toplabels=False,
                         sidelabels=False):
        num_of_shapes = int(np.ceil(array_size / shape_pitch))
        base_cell = Cell('Base')

        if 'tris' in type.lower():
            triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4)
            tri_shape = scale(
                RegPolygon([0, 0], triangle_side, 3, layer=layer), [skew, 1.0])
            tri_cell = Cell('Tri')
            tri_cell.add(tri_shape)
            if 'right' in type.lower():
                base_cell.add(tri_cell, rotation=0)
            elif 'left' in type.lower():
                base_cell.add(tri_cell, rotation=-180)
            elif 'down' in type.lower():
                base_cell.add(tri_cell,
                              rotation=30)  # not working for skew yet
            elif 'up' in type.lower():
                base_cell.add(tri_cell,
                              rotation=-30)  # not working for skew yet
        elif type.lower() == "circles":
            circ_radius = np.sqrt(shape_area / np.pi)
            circ = scale(Disk([0, 0], circ_radius, layer=layer), [skew, 1.0])
            base_cell.add(circ)
        elif type.lower() == 'hexagons':
            hex_side = np.sqrt(shape_area / 6. / np.sqrt(3) * 4)
            hex_shape = scale(RegPolygon([0, 0], hex_side, 6, layer=layer),
                              [skew, 1.0])
            hex_cell = Cell('Hex')
            hex_cell.add(hex_shape)
            base_cell.add(hex_cell, rotation=0)

        shape_array = CellArray(base_cell, num_of_shapes, num_of_shapes,
                                [shape_pitch, shape_pitch])
        shape_array_cell = Cell('Shape Array')
        shape_array_cell.add(shape_array)

        lbl_dict = {
            'hexagons': 'hex',
            'circles': 'circ',
            'tris_right': 'triR',
            'tris_left': 'triL'
        }

        if toplabels:
            text = Label('{}'.format(lbl_dict[type.lower()]), 2, layer=layer)
            lblVertOffset = 0.8
            text.translate(
                tuple(
                    np.array(-text.bounding_box.mean(0)) +
                    np.array((array_size / 2., array_size /
                              lblVertOffset))))  # Center justify label
            shape_array_cell.add(text)
        if sidelabels:
            text = Label('a={:.0f}knm2'.format(shape_area * 1000),
                         2,
                         layer=layer)
            lblHorizOffset = 1.5
            text.translate(
                tuple(
                    np.array(-text.bounding_box.mean(0)) +
                    np.array((-array_size / lblHorizOffset,
                              array_size / 2.))))  # Center justify label
            shape_array_cell.add(text)

        return shape_array_cell

    def make_many_shapes(self, array_size, shape_areas, pitch, shapes, skew,
                         layer):
        offset_x = array_size * 1.25
        offset_y = array_size * 1.25
        cur_y = 0
        many_shape_cell = Cell('ManyShapes')
        for area in shape_areas:
            cur_x = 0
            for shape in shapes:
                write_top_labels = cur_y == 0
                write_side_labels = cur_x == 0
                s_array = self.make_shape_array(array_size,
                                                area,
                                                pitch,
                                                shape,
                                                layer,
                                                skew,
                                                toplabels=write_top_labels,
                                                sidelabels=write_side_labels)
                many_shape_cell.add(s_array,
                                    origin=(cur_x - array_size / 2.,
                                            cur_y - array_size / 2.))
                cur_x += offset_x
            cur_y -= offset_y
        self.add(many_shape_cell,
                 origin=(-offset_x * (len(shapes) - 1) / 2.,
                         offset_y * (len(skews) - 1) / 2.))
smField3.frame_label(lbl, 3, l_smBeam)
smField3.make_align_markers(2., 20., (180., 180.), l_lgBeam, cross=True)
smField3.make_many_shapes(25, areas, pitch, shapes, skew, l_smBeam)

skew = skews[3]
lbl = "Sk={:.1f}x".format(skew)
smField4 = Frame(lbl, (smFrameSize, smFrameSize), [])
smField4.frame_label(lbl, 3, l_smBeam)
smField4.make_align_markers(2., 20., (180., 180.), l_lgBeam, cross=True)
smField4.make_many_shapes(25, areas, pitch, shapes, skew, l_smBeam)

centerAlignField = Frame("CenterAlignField", (smFrameSize, smFrameSize), [])

# Add everything together to a top cell
topCell = Cell("TopCell")
topCell.add(lgField)
smFrameSpacing = 400  # Spacing between the three small frames
dx = smFrameSpacing + smFrameSize
dy = smFrameSpacing + smFrameSize
topCell.add(smField1, origin=(-dx / 2., dy / 2.))
topCell.add(smField2, origin=(dx / 2., dy / 2.))
topCell.add(smField3, origin=(-dx / 2., -dy / 2.))
topCell.add(smField4, origin=(dx / 2., -dy / 2.))
# topCell.add(centerAlignField, origin=(0., 0.))

# %%Create the layout and output GDS file
layout = Layout('LIBRARY', precision=1e-10)

wafer = MBEWafer('MembranesWafer',
                 wafer_r=wafer_r,
                 cells=[topCell],
def make_theory_cell_br():
    ''' Makes the theory cell and returns it as a cell'''
    # Growth Theory Slit Elongation
    pitch = [0.500]
    lengths = list(np.logspace(-3, 0, 20) * 8.0)  # Logarithmic
    widths = [0.044, 0.028, 0.016, 0.012, 0.008]
    TheorySlitElong = Cell('LenWidthDependence')
    arrayHeight = 20.
    arraySpacing = 30.
    spacing = 10.

    TheorySlitElong.add(
        slit_elongation_array(pitch, spacing, widths[0], lengths, 0.,
                              arrayHeight, arraySpacing, l_smBeam))
    TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[1],
                                              lengths, 0., arrayHeight,
                                              arraySpacing, l_smBeam),
                        origin=(0, -30))
    TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[2],
                                              lengths, 0., arrayHeight,
                                              arraySpacing, l_smBeam),
                        origin=(0, -60))
    TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[3],
                                              lengths, 0., arrayHeight,
                                              arraySpacing, l_smBeam),
                        origin=(0, -90))
    TheorySlitElong.add(slit_elongation_array(pitch, spacing, widths[4],
                                              lengths, 0., arrayHeight,
                                              arraySpacing, l_smBeam),
                        origin=(0, -120))

    # Length Dependence
    LenWidDep = Cell('LenWidDependence')
    pitch = [0.5]
    lengths = list(np.logspace(-2, 0, 10) * 8.0)  # Logarithmic
    widths = [0.044, 0.016, 0.008]
    arrayHeight = 20.
    arrayWidth = arrayHeight
    arraySpacing = 30.
    spacing = 0.5

    for i, length in enumerate(lengths):
        for j, width in enumerate(widths):
            LenWidDep.add(make_branch_array(pitch, width, length,
                                            ['pitch', 'width', 'length'],
                                            spacing, 0, arrayHeight,
                                            arrayWidth, arraySpacing,
                                            l_smBeam),
                          origin=(i * 30, j * 30))

    # Make rotating slits
    shape_len = 3.
    shape_wid = 0.044
    N = 13  # number of shapes in the 120 degree arc
    N_rows = 8
    angle_sweep = 180
    wheel_rad = 25.
    wheel1 = Cell('RotDependence_LongSlits')
    for i in range(N_rows):
        angle_offset = (i % 2) * 7.5
        _angle_sweep = 180. - (i % 2) * 15.
        _N = int(N * _angle_sweep / angle_sweep) + (i % 2)
        angle_ref = False
        if i == 0:
            angle_ref = True
        wheel1.add(
            make_rotating_branches(shape_len,
                                   shape_wid,
                                   _N,
                                   wheel_rad + i * shape_len,
                                   l_smBeam,
                                   angle_sweep=_angle_sweep,
                                   angle_ref=angle_ref,
                                   angle_offset=angle_offset))

    wheel2 = Cell('RotDependence_ShortSlits')
    angle_sweep = -180
    wheel2.add(
        make_rotating_slits(2,
                            0.044,
                            91,
                            6. * 2,
                            l_smBeam,
                            angle_ref=True,
                            angle_sweep=angle_sweep))
    for i in range(10):  # number of concentric rings to make
        wheel2.add(
            make_rotating_slits(2,
                                0.044,
                                91, (7.2 + i * 1.2) * 2,
                                l_smBeam,
                                angle_sweep=angle_sweep))

    # Make branch devices
    shape_len = 3.
    shape_wid = 0.044
    N = 13  # number of shapes in the 120 degree arc
    N_rows = 2
    angle_sweep = 180
    wheel_rad = 50.
    wheel3 = Cell('RotDependence_BranchDev')
    for i in range(N_rows):
        angle_offset = (i % 2) * 7.5
        _angle_sweep = 180. - (i % 2) * 15.
        _N = int(N * _angle_sweep / angle_sweep) + (i % 2)
        angle_ref = False
        if i == 0:
            angle_ref = True
        wheel3.add(
            make_rotating_branch_devices(shape_len,
                                         shape_wid,
                                         _N,
                                         wheel_rad + i * shape_len * 2.,
                                         l_smBeam,
                                         angle_sweep=_angle_sweep,
                                         angle_ref=angle_ref,
                                         angle_offset=angle_offset))

    # Pitch Dependence
    PitchDep = Cell('PitchDependence')
    pitches = list(np.round(np.logspace(-1, 1, 10), 1))  # Logarithmic
    length = [2.]
    widths = [0.044, 0.016, 0.008]
    arrayHeight = 20.
    arrayWidth = arrayHeight
    arraySpacing = 30.
    spacing = 0.5

    for j, width in enumerate(widths):
        for i, pitch in enumerate(pitches):
            PitchDep.add(make_branch_array(pitch, width, length,
                                           ['pitch', 'width', 'length'],
                                           spacing, 0, arrayHeight, arrayWidth,
                                           arraySpacing, l_smBeam),
                         origin=(i * 30, j * 30))
    # Make arrays of various shapes
    hexagon_array = make_shape_array(20, 0.02, 0.75, 'Hexagons', l_smBeam)
    circles_array = make_shape_array(20, 0.02, 0.75, 'Circles', l_smBeam)
    triangle_down_array = make_shape_array(20, 0.02, 0.75, 'Tris_down',
                                           l_smBeam)
    triangle_up_array = make_shape_array(20, 0.02, 0.75, 'Tris_up', l_smBeam)

    # Merry Christmas!
    xmas_texts = [
        LineLabel('Merry Christmas!',
                  2,
                  style='gothgbt',
                  line_width=0.044,
                  layer=l_smBeam),
        LineLabel('Merry Christmas!',
                  2,
                  style='italict',
                  line_width=0.044,
                  layer=l_smBeam),
        LineLabel('Merry Christmas!',
                  2,
                  style='scriptc',
                  line_width=0.044,
                  layer=l_smBeam),
        LineLabel('Merry Christmas!',
                  2,
                  style='scripts',
                  line_width=0.044,
                  layer=l_smBeam),
        LineLabel('Merry Christmas!',
                  2,
                  style='romanc',
                  line_width=0.044,
                  layer=l_smBeam),
        LineLabel('Merry Christmas!',
                  2,
                  style='romand',
                  line_width=0.044,
                  layer=l_smBeam)
    ]

    xmax_cell = Cell('MerryChristmas')
    for i, xmas_text in enumerate(xmas_texts):
        xmas_text.translate(
            tuple(
                np.array(-xmas_text.bounding_box.mean(0)) +
                np.array([20, -80 - i * 10.])))  # Center justify label
        xmax_cell.add(xmas_text)

    TopCell = Cell('GrowthTheoryTopCell')
    TopCell.add(wheel1, origin=(-170., -50.), rotation=-90.)
    TopCell.add(wheel2, origin=(-175., -50.), rotation=-90.)
    TopCell.add(wheel3, origin=(0, -80))
    TopCell.add(PitchDep, origin=(-200., -250.))
    TopCell.add(LenWidDep, origin=(-200., -50.))
    TopCell.add(xmax_cell, origin=(-110., 60.))
    return TopCell
def make_shape_array(array_size, shape_area, shape_pitch, type, layer):
    num_of_shapes = int(np.ceil(array_size / shape_pitch))
    base_cell = Cell('Base')
    if type.lower() == "circles":
        circ_radius = np.sqrt(shape_area / np.pi)
        circ = Disk([0, 0], circ_radius, layer=layer)
        base_cell.add(circ)
    elif type.lower() == 'tris_down':
        triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4)
        tri_shape = RegPolygon([0, 0], triangle_side, 3, layer=layer)
        tri_cell = Cell('Tri')
        tri_cell.add(tri_shape)
        base_cell.add(tri_cell, rotation=30)
    elif type.lower() == 'tris_up':
        triangle_side = np.sqrt(shape_area / np.sqrt(3) * 4)
        tri_shape = RegPolygon([0, 0], triangle_side, 3, layer=layer)
        tri_cell = Cell('Tri')
        tri_cell.add(tri_shape)
        base_cell.add(tri_cell, rotation=-30)
    elif type.lower() == 'hexagons':
        hex_side = np.sqrt(shape_area / 6. / np.sqrt(3) * 4)
        hex_shape = RegPolygon([0, 0], hex_side, 6, layer=layer)
        hex_cell = Cell('Hex')
        hex_cell.add(hex_shape)
        base_cell.add(hex_cell, rotation=0)

    shape_array = CellArray(base_cell, num_of_shapes, num_of_shapes,
                            [shape_pitch, shape_pitch])
    shape_array_cell = Cell('Shape Array')
    shape_array_cell.add(shape_array)

    text = Label('{}'.format(type), 2)
    lblVertOffset = 0.8
    text.translate(
        tuple(
            np.array(-text.bounding_box.mean(0)) +
            np.array((array_size / 2.,
                      array_size / lblVertOffset))))  # Center justify label

    shape_array_cell.add(text)

    return shape_array_cell