Ejemplo n.º 1
0
 def makeCells(self, cellsize=2000, startpt=(0, 0)):
     gap = self.cell_gap
     # Define the parameters of our shapes
     if self.cellsAtEdges:
         sl_tri = self.trisize * 1.5  # Only needed if you want to put cells very close the edge of triangle chip
     else:
         sl_tri = self.trisize
     h_tri = np.sqrt(3.) / 2. * sl_tri
     # Create the triangular block
     block = Polygon([
         [-sl_tri / 2., -h_tri / 3.], [sl_tri / 2., -h_tri / 3.],
         [0, 2. * h_tri / 3.], [-sl_tri / 2., -h_tri / 3.]
     ])
     # Make a square cell
     cell = box(-cellsize / 2., -cellsize / 2., cellsize / 2., cellsize / 2.)
     # Make a lattice for the cells
     # lattice = self.createPtLattice(sl_tri, cellsize / 2. + gap / 2.,cellsize/2. + gap)
     lattice = self.createPtLattice(sl_tri, (cellsize + gap) / 2., (cellsize + gap) * np.sqrt(3.) / 2.)
     lattice = lattice + np.array(startpt)
     lattice = [
         pt for pt in lattice if Point(pt).within(block)
         ]  # Keep only points within triangular block
     # Use the lattice of points to translate the cell all over the block
     cells = [translateshape(cell, xoff=x, yoff=y) for x, y in lattice]
     # Keep only the cells that are fully within the block
     cells = [f for f in cells if f.within(block)]
     return cells
Ejemplo n.º 2
0
    def add_aligment_marks(self, layers):
        """
        Create alignment marks on all active layers
        """
        if not (type(layers) == list): layers = [layers]
        d_layers = self.cell_layers
        #        styles=['B' if i%2 else 'B' for i in range(len(d_layers))]            
        #        am = AlignmentMarks(styles, d_layers)
        am = Cell('CONT_ALGN')
        # Define dimensions of the alignment cross
        t = 200.  # Thickness
        t /= 2.
        h = 2000.  # Height
        w = 2000.  # Width
        crosspts = [
            (-t, t), (-t, h), (t, h), (t, t), (w, t), (w, -t), (t, -t), (t, -h),
            (-t, -h), (-t, -t), (-w, -t), (-w, t)]
        # Create shapely polygon for later calculation
        crossPolygon = Polygon(crosspts)
        crossPolygons = []
        for pt in self.align_pts:
            crossPolygons.extend([
                translateshape(crossPolygon, xoff=pt[0], yoff=pt[1])])

        # TODO: Replace these two loops with a single loop, looping over an array of block objects
        # TODO: Make the deleting more efficient by using del for multiple indexes?
        i_del = []
        # Loop over all triangular blocks
        for i, tri in enumerate(self.upTris):
            for poly in crossPolygons:  # Loop over all alignment crosses
                if poly.intersects(tri) or poly.within(tri) or poly.contains(
                        tri):
                    # If conflict is detected, remove that triangular block
                    i_del.append(i)
                    print(('up:' + str(self.upTris[i].centroid.xy)))

        self.upTris = [tri for i, tri in enumerate(self.upTris) if i not in i_del]

        # Repeat for down-facing triangles
        i_del = []
        for i, tri in enumerate(self.downTris):
            for poly in crossPolygons:
                if poly.intersects(tri) or poly.within(tri) or poly.contains(
                        tri):
                    # If conflict is detected, remove that triangular block
                    i_del.append(i)
                    print(('down:' + str(self.downTris[i].centroid.xy)))

        self.downTris = [tri for i, tri in enumerate(self.downTris) if i not in i_del]
        # Refresh the centers of the remaining triangles
        self.upCenters = [list(zip(*tri.centroid.xy)[0]) for tri in self.upTris]
        self.downCenters = [list(zip(*tri.centroid.xy)[0])
                            for tri in self.downTris]

        for l in layers:  # Add marker to all layers
            cross = Boundary(crosspts, layer=l)  # Create gdsCAD shape
            am.add(cross)

        mblock = Cell('WAF_ALGN_BLKS')
        mblock.add(am)
        for pt in self.align_pts:
            self.add(mblock, origin=pt)
Ejemplo n.º 3
0
    def getCellLattice(self, cellsize=2000):
        iterations = self.MCIterations
        ycelloffset = self.cell_gap / 3.5  # Arbitrary, change by trial and error
        if self.doMCSearch:
            best = [0, 0, 0, 0]
            # Iterates many times to find the best fit
            for i in range(iterations):
                # Random seed point
                rndpt = (0, np.random.randint(-cellsize, cellsize))
                # Make cells around this point
                cells = self.makeCells(startpt=rndpt, cellsize=cellsize)
                if not cells:
                    continue
                centroidDist = np.array([cell.centroid.xy for cell in cells]).squeeze()
                if len(centroidDist.shape) == 2:
                    centroidDist = centroidDist.mean(0)
                if len(cells) > best[1]:
                    best = [rndpt, len(cells), cells, centroidDist]
                elif len(cells) == best[1]:
                    # Choose the one that is closer to the center of the wafer
                    if np.sqrt(rndpt[0] ** 2 + rndpt[1] ** 2) < np.sqrt(best[0][0] ** 2 + best[0][1] ** 2):
                        #                    if centroidDist < best[3]:
                        best = [rndpt, len(cells), cells, centroidDist]
                        #                print("Current: {:f}, Best {:f}").format(len(cells),best[1])

                        #            centroidDist = np.array([tri.centroid.xy for tri in cells]).squeeze().mean(0)
                        #            centroidDist = np.sqrt(centroidDist[0]**2+centroidDist[1]**2)
                        #            centroidDist = np.array([cell.centroid.xy for cell in cells]).squeeze()

            # Choose the best configuration (fits the most cells and is closest to centroid)
            cells = best[2]
        else:
            cells = self.makeCells(cellsize=2000)
        sl_tri = self.trisize
        h_tri = np.sqrt(3.) / 2. * sl_tri
        gap = self.block_gap
        from matplotlib import pyplot
        fig = pyplot.figure(1, dpi=90)
        ax = fig.add_subplot(111)
        ax.grid()
        ax.axis('equal')
        block = Polygon([
            [-sl_tri / 2., -h_tri / 3.], [sl_tri / 2., -h_tri / 3.],
            [0, 2. * h_tri / 3.], [-sl_tri / 2., -h_tri / 3.]
        ])
        block = translateshape(block, yoff=h_tri / 3. + gap / 2.)
        block = translateshape(block, xoff=self.blockOffset[0],
                               yoff=self.blockOffset[1])  # TODO: plot output not working properly because of this?
        patch = PolygonPatch(block,
                             facecolor="#{0:0{1}X}".format(np.random.randint(0, 16777215), 6),
                             #                             facecolor=RED,
                             edgecolor=BLACK,
                             alpha=0.3,
                             zorder=2)
        ax.add_patch(patch)
        ax.plot(block.exterior.coords.xy[0], block.exterior.coords.xy[1], 'k-')
        for cell in cells:
            cell = translateshape(cell, yoff=h_tri / 3. + gap / 2. + ycelloffset)
            cell = translateshape(cell, xoff=self.blockOffset[0],
                                  yoff=self.blockOffset[1])  # TODO: plot output not working properly because of this?
            patch = PolygonPatch(cell,
                                 facecolor="#{0:0{1}X}".format(np.random.randint(0, 16777215), 6),
                                 edgecolor='k',
                                 alpha=0.3,
                                 zorder=2)
            ax.add_patch(patch)
        # Convert cells to lattice of points
        cellLattice = np.array([list(zip(*cell.centroid.xy))[0] for cell in cells])
        cellLattice = cellLattice + np.array([0, ycelloffset])
        return cellLattice
Ejemplo n.º 4
0
    def _place_blocks(self):
        """
        Create the list of valid block sites based on block size and wafer diam.
        """
        sl_tri = self.trisize  # Sidelength of the triangular blocks
        h_tri = np.sqrt(3.) / 2. * sl_tri  # Height of triangular blocks
        if self.doMCBlockSearch:
            best = [0, 0, 0, 0]
            # Iterates many times to find the best fit
            for i in range(self.MCBlockIterations):
                # Random seed point
                rndpt = (0, np.random.randint(int(-h_tri), 0))
                # Make cells around this point
                upTris, downTris = self.makeBlocks(sl_tri, startpt=rndpt)
                NTris = (len(upTris) + len(downTris))
                if NTris > best[1]:
                    centroidDist = np.array([
                        tri.centroid.xy for tri in upTris + downTris
                    ]).squeeze().mean(0)
                    centroidDist = np.sqrt(centroidDist[0]**2 +
                                           centroidDist[1]**2)
                    #                    centroidDist = abs(rndpt[1])
                    best = [rndpt, NTris, (upTris, downTris), centroidDist]
                elif NTris == best[1]:
                    #                    Choose the pattern that is most centered on the wafer
                    centroidDist = np.array([
                        tri.centroid.xy for tri in upTris + downTris
                    ]).squeeze().mean(0)
                    centroidDist = np.sqrt(centroidDist[0]**2 +
                                           centroidDist[1]**2)
                    #                    centroidDist = abs(rndpt[1])
                    #                    print centroidDist
                    if centroidDist < best[3]:
                        best = [rndpt, NTris, (upTris, downTris), centroidDist]
                        #                print("Current: {:f}, Best {:f}").format(NTris,best[1])
            # Choose the best configuration (fits the most cells)
            self.upTris, self.downTris = best[2]
            self.blockOffset = best[0]
        else:
            self.upTris, self.downTris = self.makeBlocks(sl_tri)
            self.blockOffset = (0, 0)

        # Find the centers of the triangles
        self.upCenters = [next(zip(*tri.centroid.xy)) for tri in self.upTris]
        self.downCenters = [
            next(zip(*tri.centroid.xy)) for tri in self.downTris
        ]

        # Shift triangles to be centered around (0,0)
        offset = np.mean(np.vstack([self.upCenters, self.downCenters]), 0)
        self.upTris = [
            translateshape(tri, xoff=-offset[0], yoff=-offset[1])
            for tri in self.upTris
        ]
        self.downTris = [
            translateshape(tri, xoff=-offset[0], yoff=-offset[1])
            for tri in self.downTris
        ]

        # Debugging
        self.plotTriangles(self.downTris + self.upTris)

        # Find the centers of the triangles
        self.upCenters = [next(zip(*tri.centroid.xy)) for tri in self.upTris]
        self.downCenters = [
            next(zip(*tri.centroid.xy)) for tri in self.downTris
        ]

        # %%
        sl_lattice = self.trisize + self.block_gap / np.tan(np.deg2rad(30))
        h_lattice = np.sqrt(3.) / 2. * sl_lattice
        base = h_lattice
        # Create label for each block (taken from templates._placeblocks)
        # String prefixes to associate with each row/column index
        x1s, y1s = set(), set()
        for tri in self.upTris:
            # In x use centroid as reference, in y use lower bound so up and down triangles give almost the same value
            x1s.add(np.round(tri.centroid.x, 8))
            y1s.add(base * round(float(tri.bounds[1]) / base))
        # Create dictionary of up and down triangles
        self.orientrows = dict(
            list(zip(y1s, ["up" for i, y in enumerate(y1s)])))
        # Create dictionary of up and down triangles
        x2s, y2s = set(), set()
        for tri in self.downTris:
            x2s.add(np.round(tri.centroid.x, 8))
            y2s.add(base * round(float(tri.bounds[1]) / base))
        self.orientrows.update(
            dict(list(zip(y2s, ["down" for i, y in enumerate(y2s)]))))

        x1s.update(x2s)
        xs = sorted(list(x1s))
        self.blockcols = dict(
            list(zip(xs,
                     [string.ascii_uppercase[i] for i, x in enumerate(xs)])))
        y1s.update(y2s)
        ys = sorted(list(y1s))
        self.blockrows = dict(list(zip(ys,
                                       [str(i) for i, y in enumerate(ys)])))