예제 #1
0
 def init_regions( self ):
     self.P0 = DPoint( 0,0 )
     self.P1 = self.P0 + DPoint( self.Z1.gap,0 )
     self.P2 = self.P1 + DPoint( self.Z1.width,0 )
     self.P3 = self.P2 + DPoint( 0,self.Z1.gap )
     self.P4 = self.P2 + DPoint( self.Z1.gap, self.Z2.gap )
     self.P5 = self.P4 + DPoint( 0,self.Z2.width )
     self.P6 = DPoint( 0, self.Z1.gap + self.Z1.width )
     self.P7 = DPoint( 0, self.Z1.gap )
     self.P8 = self.P7 + DPoint( self.Z1.gap,0 )
     self.P9 = self.P2 + DPoint( self.Z1.gap,0 )
     self.P10 = self.P5 + DPoint( 0, self.Z2.gap )
     self.P11 = self.P10 - DPoint( 2*self.Z1.gap + self.Z1.width, 0 )
     self.P12 = self.P6 + DPoint( 0, self.Z1.gap )
     
     self.connections = [(self.P6 + self.P7)*0.5,(self.P1 + self.P2)*0.5,(self.P5 + self.P4)*0.5]
     self.angle_connections = [0,3/2*pi,0]
             
     self.metal_polygon = DPolygon( [self.P1,self.P2,self.P3,self.P4,self.P5,self.P6,self.P7,self.P8] )
     self.empty1_polygon = DPolygon( [self.P0,self.P1,self.P8,self.P7] )
     self.empty2_polygon = DPolygon( [self.P2,self.P9,self.P4,self.P3]  )
     self.empty3_polygon = DPolygon( [self.P5,self.P10,self.P12,self.P6] )
     self.gnd_polygon = DPolygon( [self.P10,self.P11,self.P12] )
     self.metal_region = pya.Region( list(map(pya.Polygon().from_dpoly,[self.metal_polygon,self.gnd_polygon])) )
     self.empty_region = pya.Region( list(map(pya.Polygon().from_dpoly ,[self.empty1_polygon,self.empty2_polygon,self.empty3_polygon])) )
예제 #2
0
    def init_regions(self):
        Rout = self.r
        Rin = self.r - self.t
        dpts_arr_Rout = [DPoint(Rout * cos(2 * pi * i / self.n_pts), Rout * sin(2 * pi * i / self.n_pts)) for i in
                         range(0, self.n_pts)]
        dpts_arr_Rin = [DPoint(Rin * cos(2 * pi * i / self.n_pts), Rin * sin(2 * pi * i / self.n_pts)) for i in
                        range(0, self.n_pts)]
        ring_dpoly = DPolygon(dpts_arr_Rout)
        ring_dpoly.insert_hole(dpts_arr_Rin)
        ring_poly = Polygon().from_dpoly(ring_dpoly)

        if self.inverse:
            self.empty_region.insert(ring_poly)
        else:
            self.metal_region.insert(ring_poly)
예제 #3
0
 def init_regions(self):
     pts_raw = [
         -199499.00, -299939.00, -199499.00, -201544.00, -301346.00,
         -201544.00, -301346.00, 202661.00, -194835.00, 202661.00,
         -194835.00, 249057.00, -3110.00, 249057.00, -3110.00, 243800.00,
         -3006.00, 243800.00, -3006.00, 9362.00, -1507.00, 9362.00,
         -1507.00, 389.00, -10506.00, 389.00, -10506.00, 1862.00,
         -250230.00, 1862.00, -250230.00, -3138.00, -10506.00, -3138.00,
         -10506.00, -1639.00, -1507.00, -1639.00, -1507.00, -10638.00,
         -3006.00, -10638.00, -3006.00, -249398.00, 1994.00, -249398.00,
         1994.00, -10638.00, 495.00, -10638.00, 495.00, -1639.00, 9494.00,
         -1639.00, 9494.00, -3138.00, 250101.00, -3138.00, 250101.00,
         1862.00, 9494.00, 1862.00, 9494.00, 363.00, 521.00, 363.00, 521.00,
         9362.00, 1994.00, 9362.00, 1994.00, 249057.00, -194835.00,
         249057.00, -194835.00, 299939.00, 202792.00, 299939.00, 202792.00,
         196681.00, 301345.00, 196681.00, 301345.00, 140894.00, 149560.00,
         140894.00, 149560.00, 140729.00, 301345.00, 140729.00, 301345.00,
         -203457.00, 202313.00, -203457.00, 202313.00, -299939.00
     ]
     pts = [
         DPoint(pts_raw[2 * i], pts_raw[2 * i + 1])
         for i in range(int(len(pts_raw) // 2))
     ]
     poly = Polygon(DPolygon(pts))
     if self.inverse:
         self.empty_region.insert(poly)
     else:
         self.metal_region.insert(poly)
예제 #4
0
    def produce_impl(self):
        from SiEPIC._globals import PIN_LENGTH
        from SiEPIC.extend import to_itype
        import math
        from pya import DPolygon
        # This is the main part of the implementation: create the layout

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes
        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        #variables
        pitch = self.pitch
        w = self.w
        r = self.r
        ff = self.ff
        angle = self.angle
        gap = self.gap
        W_ratio = self.W_ratio
        doublebus = self.doublebus
        print(doublebus)

        # set the deltaL of sT-shaped silicon pillar (deltaL = (Lin-Lout)/4)
        deltaL = (2 * pitch * ff) * (W_ratio - 1) / ((1 + W_ratio) * (4))

        if (r - w / 2 <= 0):
            r = 5
            print('invalid radius, set r to default: 5')

        #Calculate number of segments
        s1 = pitch * ff  #silicon
        s2 = pitch - s1  #gap

        #calculate best radius
        pi = math.pi
        const = math.ceil(2 * pi * r / (s1 + s2))
        #if doesn't divide evenly, replace r with best possible r
        if ((2 * pi * r) % (s1 + s2) != 0):
            r = const * (s1 + s2) / (2 * pi)
            print('r adjusted to ' + str(r) + 'um to fit periods perfectly.')

        #theta1 = (s1/r)
        #theta2 = (s2/r)
        theta1 = math.atan(s1 /
                           r)  # angle of silicon compared to the origin point
        theta2 = math.atan(s2 /
                           r)  # angle of the gap compared to the origin point
        nSeg = int(
            math.floor(angle /
                       (math.degrees(theta1) +
                        math.degrees(theta2))))  #how many segments to have
        si_first = True  #for alternating between silicon and gap
        j = 0  #index of how many silicon thetas
        jj = 0  #index of how many gap thetas
        ORDER = True  #ordering of the coordinates for polygon drawing

        #xo = [(r-w/2)*math.cos(0)]
        #yo = [(r-w/2)*math.sin(0)]
        #xo.append((r+w/2)*math.cos(0))
        #yo.append((r+w/2)*math.sin(0))

        xo = [(r - w / 2) * math.cos(0) + deltaL * math.sin(0)]
        yo = [(r - w / 2) * math.sin(0) - deltaL * math.cos(0)]
        xo.append((r + w / 2) * math.cos(0) - deltaL * math.sin(0))
        yo.append((r + w / 2) * math.sin(0) + deltaL * math.cos(0))

        for i in range(0, nSeg * 2):
            if si_first:
                j = j + 1
                si_first = not (si_first)
            else:
                jj = jj + 1
                si_first = not (si_first)

            if ORDER:
                xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2) +
                          deltaL * math.sin(j * theta1 + jj * theta2))
                yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2) -
                          deltaL * math.cos(j * theta1 + jj * theta2))
                xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2) -
                          deltaL * math.sin(j * theta1 + jj * theta2))
                yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2) +
                          deltaL * math.cos(j * theta1 + jj * theta2))
                ORDER = not (ORDER)
            else:
                xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2) +
                          deltaL * math.sin(j * theta1 + jj * theta2))
                yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2) -
                          deltaL * math.cos(j * theta1 + jj * theta2))
                xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2) -
                          deltaL * math.sin(j * theta1 + jj * theta2))
                yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2) +
                          deltaL * math.cos(j * theta1 + jj * theta2))
                ORDER = not (ORDER)

            if len(xo) == 4:
                dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)
                xo = []
                yo = []

        #Draw Bus WG
        #calulate ideal length of bus
        bus_length = self.cell.bbox().height() * dbu + pitch * 2
        constant = math.ceil(bus_length / (s1 + s2))
        if bus_length % (s1 + s2) != 0:
            bus_length = constant * (s1 + s2)

        #draw first box at center
        xo = [(r + w / 2 + gap), (r + w / 2 + gap + w), (r + w / 2 + gap + w),
              (r + w / 2 + gap)]
        yo = [0, 0, s1, s1]
        dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))]
        dpolygon = DPolygon(dpts)
        element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
        shapes(LayerSiN).insert(element)

        for i in range(0, int(math.ceil((constant) / 2))):
            yu = [yo[j] + i * pitch for j in range(len(yo))]
            yd = [yo[j] - i * pitch for j in range(len(yo))]

            dpts = [pya.DPoint(xo[i], yu[i]) for i in range(len(xo))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)
            dpts = [pya.DPoint(xo[i], yd[i]) for i in range(len(xo))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

        if doublebus:
            for i in range(0, int(math.ceil((constant) / 2))):
                x2 = [xo[j] * -1 for j in range(len(xo))]
                yu = [yo[j] + i * pitch for j in range(len(yo))]
                yd = [yo[j] - i * pitch for j in range(len(yo))]

                dpts = [pya.DPoint(x2[i], yu[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)
                dpts = [pya.DPoint(x2[i], yd[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

        #DEV BOX
        if doublebus is False:
            half_l = (self.cell.bbox().width() - w / dbu - gap / dbu) / 2
            half_r = self.cell.bbox().width() - half_l
            dev = Box(-half_l, yd[-4] / dbu, half_r, yu[-1] / dbu)
            shapes(LayerDevRecN).insert(dev)
            dev_width = self.cell.bbox().width() / 2
        else:
            half_l = (self.cell.bbox().width()) / 2
            half_r = self.cell.bbox().width() - half_l
            dev = Box(-half_l, yd[-4] / dbu, half_r, yu[-1] / dbu)
            shapes(LayerDevRecN).insert(dev)
            dev_width = self.cell.bbox().width() / 2

    # Create the pins on the waveguides, as short paths:
        from SiEPIC._globals import PIN_LENGTH as pin_length

        w = to_itype(self.w, dbu)
        gap = to_itype(self.gap, dbu)
        bus_length = to_itype(bus_length / 2, dbu)

        #Pin1
        t = Trans(Trans.R0, half_r - w / 2, yu[-1] / dbu)
        pin = Path([Point(0, -pin_length / 2), Point(0, pin_length / 2)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        #Pin2
        t = Trans(Trans.R0, half_r - w / 2, yd[-4] / dbu)
        pin = Path([Point(0, pin_length / 2), Point(0, -pin_length / 2)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin2", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        if doublebus is True:
            half_l = self.cell.bbox().width() / 2
            half_r = self.cell.bbox().width() - half_l
            #pin 3
            t = Trans(Trans.R0, -half_l + w / 2, yu[-1] / dbu)
            pin = Path([Point(0, -pin_length / 2),
                        Point(0, pin_length / 2)], w)
            pin_t = pin.transformed(t)
            shapes(LayerPinRecN).insert(pin_t)
            text = Text("pin3", t)
            shape = shapes(LayerPinRecN).insert(text)
            shape.text_size = 0.4 / dbu

            #Pin4
            t = Trans(Trans.R0, -half_l + w / 2, yd[-4] / dbu)
            pin = Path([Point(0, pin_length / 2),
                        Point(0, -pin_length / 2)], w)
            pin_t = pin.transformed(t)
            shapes(LayerPinRecN).insert(pin_t)
            text = Text("pin4", t)
            shape = shapes(LayerPinRecN).insert(text)
            shape.text_size = 0.4 / dbu
예제 #5
0
    def produce_impl(self):
        from SiEPIC._globals import PIN_LENGTH
        from SiEPIC.extend import to_itype
        from pya import DPolygon
        import math
        # This is the main part of the implementation: create the layout

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes
        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        #variables
        pitch = self.pitch
        w = self.w
        wc = self.wc
        ff = self.ff
        #angle = self.angle
        gap = self.gap
        #gap2 = self.gap2
        row = self.row
        Length = self.Length
        taperL = self.taperL
        phaseshifted = self.phaseshifted
        #print(doublebus)

        if Length <= 3 * pitch:
            Length = 3 * pitch
            print(
                'invalid length of MultiBox Bragg grating, set length at least 3 times larger than the period of multibox blocks'
            )

        s1 = pitch * ff  #silicon
        s2 = pitch - s1  #gap

        # Draw the first Multi-box Waveguides
        #calulate ideal length of bus
        Bragg_length = Length
        #bus_length = self.cell.bbox().height()*dbu +pitch*2
        constant = math.ceil(Bragg_length / (s1 + s2))
        if Bragg_length % (s1 + s2) != 0:
            Bragg_length = constant * (s1 + s2)

        for ii in range(0, int(row)):
            xo = [(ii * (w + gap)), (w + ii * (w + gap)), (w + ii * (w + gap)),
                  (ii * (w + gap))]
            yo = [0, 0, s1, s1]
            dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

            # draw the SWG waveguide from the center one to +/- positions
            for i in range(0, int(math.ceil((constant) / 2))):
                yu = [yo[j] + i * pitch for j in range(len(yo))]
                yd = [yo[j] - i * pitch for j in range(len(yo))]

                dpts = [pya.DPoint(xo[i], yu[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)
                dpts = [pya.DPoint(xo[i], yd[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

            # draw the tapers from waveguide to SWG
            if taperL != 0:
                xtu = [((ii * (w + gap)) + (w - 0.06) / 2),
                       ((ii * (w + gap)) + (w - 0.06) / 2 + 0.06),
                       ((ii * (w + gap)) + w + gap / 2),
                       ((ii * (w + gap)) - gap / 2)]
                ytu = [(yu[3] - taperL), (yu[3] - taperL), (yu[3]), (yu[3])]
                dpts = [pya.DPoint(xtu[i], ytu[i]) for i in range(len(xtu))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

                ytd = [(yd[1] + taperL), (yd[1] + taperL), (yd[1]), (yd[1])]
                dpts = [pya.DPoint(xtu[i], ytd[i]) for i in range(len(xtu))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

                # taper connections from multi-tapers to std WG
                xTu = [(-gap / 2), (-gap / 2 + row * (gap + w)),
                       ((row * (gap + w) - gap) / 2 + 0.25),
                       ((row * (gap + w) - gap) / 2 - 0.25)]
                yTu = [(yu[3]), (yu[3]), (yu[3] + taperL), (yu[3] + taperL)]
                dpts = [pya.DPoint(xTu[i], yTu[i]) for i in range(len(xTu))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

                yTd = [(yd[1]), (yd[1]), (yd[1] - taperL), (yd[1] - taperL)]
                dpts = [pya.DPoint(xTu[i], yTd[i]) for i in range(len(xTu))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)
                # f is the factor to define the Dev starting point
                f = 1

            if taperL == 0:
                yTd = yd
                yTu = yu
                xTu = [0, 0, 0, 0]
                f = 0

        # draw the corrugations of the Bragg gratings
        constant_c = math.ceil((Bragg_length - taperL) / (s1 + s2))

        for iii in range(0, int(math.ceil(constant_c / 4))):
            yuc = [yo[j] + 2 * iii * pitch for j in range(len(yo))]
            ydc = [yo[j] - 2 * iii * pitch for j in range(len(yo))]
            xlc = [-wc - s2, -s2, -s2, -wc - s2]
            xrc = [
                row * pitch, row * pitch + wc, row * pitch + wc, row * pitch
            ]

            dpts = [pya.DPoint(xlc[i], yuc[i]) for i in range(len(xo))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

            dpts = [pya.DPoint(xrc[i], yuc[i]) for i in range(len(xo))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

        if phaseshifted is False:
            for iii in range(0, int(math.ceil(constant_c / 4))):
                #yuc = [yo[j]+2*iii*pitch for j in range(len(yo))]
                ydc = [yo[j] - 2 * iii * pitch for j in range(len(yo))]
                #xlc = [-wc-s2, -s2, -s2,-wc-s2]
                #xrc = [row*pitch, row*pitch+wc, row*pitch+wc, row*pitch]

                dpts = [pya.DPoint(xlc[i], ydc[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

                dpts = [pya.DPoint(xrc[i], ydc[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

        if phaseshifted is True:
            for iii in range(0, int(math.ceil(constant_c / 4))):
                #yuc = [yo[j]+2*iii*pitch for j in range(len(yo))]
                yddc = [
                    yo[j] - pitch - 2 * iii * pitch for j in range(len(yo))
                ]

                dpts = [pya.DPoint(xlc[i], yddc[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

                dpts = [pya.DPoint(xrc[i], yddc[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

        #DEV BOX
        dev = Box(f * (-gap - wc - (2) * pitch) / dbu, yTd[-1] / dbu,
                  (wc + (row + 2) * pitch) / dbu, yTu[-1] / dbu)
        shapes(LayerDevRecN).insert(dev)
        dev_width = self.cell.bbox().width() / 2

        dev_up = yu[-1] / dbu + taperL / dbu
        dev_down = yd[-4] / dbu - taperL / dbu

        # Create the pins on the waveguides, as short paths:
        from SiEPIC._globals import PIN_LENGTH as pin_length

        w = to_itype(self.w, dbu)
        gap = to_itype(self.gap, dbu)

        #Pin1
        t = Trans(Trans.R0, xTu[-1] / dbu + 250, dev_up)
        pin = Path([Point(0, -pin_length / 2),
                    Point(0, pin_length / 2)], 500)  #500 is width of std WG
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        t = Trans(Trans.R270, xTu[-1] / dbu + 250, dev_up)
        text = Text("pin1", t)
        text.halign = 0
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        #Pin2
        t = Trans(Trans.R0, xTu[-1] / dbu + 250, dev_down)
        pin = Path([Point(0, pin_length / 2), Point(0, -pin_length / 2)], 500)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        t = Trans(Trans.R90, xTu[-1] / dbu + 250, dev_down)
        text = Text("pin2", t)
        text.halign = 0
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        # Ref
        t = Trans(Trans.R270, xTu[-1] / dbu + 250 + 0.5 / dbu, dev_up)
        text = Text("Ref: E. Luan, doi.org/10.1364/BOE.10.004825", t)
        text.halign = 0
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu
예제 #6
0
    def produce_impl(self):
        from SiEPIC._globals import PIN_LENGTH
        from SiEPIC.extend import to_itype
        import math
        from pya import DPolygon

        pi = math.pi
        # This is the main part of the implementation: create the layout

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes
        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        #variables
        pitch = self.pitch
        w = self.w
        r = self.r
        ff = self.ff
        angle = self.angle
        gap = self.gap
        gap2 = self.gap2
        row = self.row
        busL = self.busL
        taperL = self.taperL
        #doublebus = self.doublebus
        #print(doublebus)

        if (r - w / 2 <= 0):
            r = 5
            print('invalid radius, set r to default: 5')
        if row <= 1:
            row = 1
            print('invalid number of rows, set row to default: 1')
        if busL <= 10:
            busL = taperL * 2 + 10
            print(
                'invalid length of SWG bus waveguide, set length at least 2 times larger than taper length and pluse 10 um'
            )
        #Calculate number of segments
        s1 = pitch * ff  #silicon
        s2 = pitch - s1  #gap

        # Draw the Multi-box Ring
        for i in range(0, int(row)):  # draw different radius SWG rings
            #calculate best radius
            #const = math.ceil(2*pi*r/(s1+s2))
            const = math.floor(2 * pi * r / (s1 + s2))
            #if doesn't divide evenly, replace r with best possible r
            if ((2 * pi * r) % (s1 + s2) != 0):
                r = const * (s1 + s2) / (2 * pi)
                print('r adjusted to ' + str(r) +
                      'um to fit periods perfectly.')

            theta1 = math.atan(s1 / r)
            theta2 = math.atan(s2 / r)
            nSeg = int(
                math.floor(angle /
                           (math.degrees(theta1) +
                            math.degrees(theta2))))  #how many segments to have
            si_first = True  #for alternating between silicon and gap
            j = 0  #index of how many silicon thetas
            jj = 0  #index of how many gap thetas
            ORDER = True  #ordering of the coordinates for polygon drawing

            xo = [(r - w / 2) * math.cos(0)]
            yo = [(r - w / 2) * math.sin(0)]
            xo.append((r + w / 2) * math.cos(0))
            yo.append((r + w / 2) * math.sin(0))

            for i in range(0, nSeg * 2):
                if si_first:
                    j = j + 1
                    si_first = not (si_first)
                else:
                    jj = jj + 1
                    si_first = not (si_first)

                if ORDER:
                    xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2))
                    yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2))
                    xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2))
                    yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2))
                    ORDER = not (ORDER)
                else:
                    xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2))
                    yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2))
                    xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2))
                    yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2))
                    ORDER = not (ORDER)

                if len(xo) == 4:
                    dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))]
                    dpolygon = DPolygon(dpts)
                    element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                    shapes(LayerSiN).insert(element)
                    xo = []
                    yo = []
            r = r - (w + gap)
# Draw the Bus Waveguides
#Draw Bus WG
# to go back to the initial point for Multi-box drawing, ger the first adjusted r value
        r = self.r
        const = math.floor(2 * pi * r / (s1 + s2))
        #if doesn't divide evenly, replace r with best possible r
        if ((2 * pi * r) % (s1 + s2) != 0):
            r = const * (s1 + s2) / (2 * pi)

        #calulate ideal length of bus
        bus_length = busL
        #bus_length = self.cell.bbox().height()*dbu +pitch*2
        constant = math.ceil(bus_length / (s1 + s2))
        if bus_length % (s1 + s2) != 0:
            bus_length = constant * (s1 + s2)

        for ii in range(0, int(row)):
            xo = [(r + w / 2 + gap2 + ii * (w + gap)),
                  (r + w / 2 + gap2 + w + ii * (w + gap)),
                  (r + w / 2 + gap2 + w + ii * (w + gap)),
                  (r + w / 2 + gap2 + ii * (w + gap))]
            yo = [0, 0, s1, s1]
            dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

            # draw the bus waveguide
            for i in range(0, int(math.ceil((constant) / 2))):
                yu = [yo[j] + i * pitch for j in range(len(yo))]
                yd = [yo[j] - i * pitch for j in range(len(yo))]

                dpts = [pya.DPoint(xo[i], yu[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)
                dpts = [pya.DPoint(xo[i], yd[i]) for i in range(len(xo))]
                dpolygon = DPolygon(dpts)
                element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
                shapes(LayerSiN).insert(element)

            # draw the tapers from waveguide to SWG
            xtu = [
                ((r + w / 2 + gap2 + ii * (w + gap)) + (w - 0.06) / 2),
                ((r + w / 2 + gap2 + ii * (w + gap)) + (w - 0.06) / 2 + 0.06),
                ((r + w / 2 + gap2 + ii * (w + gap)) + w + gap / 2),
                ((r + w / 2 + gap2 + ii * (w + gap)) - gap / 2)
            ]
            ytu = [(yu[3] - taperL), (yu[3] - taperL), (yu[3]), (yu[3])]
            dpts = [pya.DPoint(xtu[i], ytu[i]) for i in range(len(xtu))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

            ytd = [(yd[1] + taperL), (yd[1] + taperL), (yd[1]), (yd[1])]
            dpts = [pya.DPoint(xtu[i], ytd[i]) for i in range(len(xtu))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

        # taper connections from multi-tapers to std WG
        xTu = [(r + w / 2 + gap2 - gap / 2),
               (r + w / 2 + gap2 - gap / 2 + row * (gap + w)),
               (r + w / 2 + gap2 + row * (gap + w) / 2 + 0.25),
               (r + w / 2 + gap2 + row * (gap + w) / 2 - 0.25)]
        yTu = [(yu[3]), (yu[3]), (yu[3] + taperL), (yu[3] + taperL)]
        dpts = [pya.DPoint(xTu[i], yTu[i]) for i in range(len(xTu))]
        dpolygon = DPolygon(dpts)
        element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
        shapes(LayerSiN).insert(element)

        yTd = [(yd[1]), (yd[1]), (yd[1] - taperL), (yd[1] - taperL)]
        dpts = [pya.DPoint(xTu[i], yTd[i]) for i in range(len(xTu))]
        dpolygon = DPolygon(dpts)
        element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
        shapes(LayerSiN).insert(element)

        # add std WG
        if 2 * r >= busL + 2 * taperL:
            xstdu = [(r + w / 2 + gap2 + row * (gap + w) / 2 - 0.25),
                     (r + w / 2 + gap2 + row * (gap + w) / 2 + 0.25),
                     (r + w / 2 + gap2 + row * (gap + w) / 2 + 0.25),
                     (r + w / 2 + gap2 + row * (gap + w) / 2 - 0.25)]
            ystdu = [(yu[3] + taperL), (yu[3] + taperL),
                     (yu[3] + r - busL / 2 + 1), (yu[3] + r - busL / 2 + 1)]
            dpts = [pya.DPoint(xstdu[i], ystdu[i]) for i in range(len(xstdu))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)

            ystdd = [(yd[1] - taperL), (yd[1] - taperL),
                     (yd[1] - r + busL / 2 - 1), (yd[1] - r + busL / 2 - 1)]
            dpts = [pya.DPoint(xstdu[i], ystdd[i]) for i in range(len(xstdu))]
            dpolygon = DPolygon(dpts)
            element = Polygon.from_dpoly(dpolygon * (1.0 / dbu))
            shapes(LayerSiN).insert(element)
        else:
            xstdu = xTu
            ystdu = yTu
            ystdd = yTd

        #DEV BOX
        half_l = (self.cell.bbox().width() - row *
                  (gap + w) / dbu - gap2 / dbu + (gap / 2) / dbu) / 2
        half_r = self.cell.bbox().width() - half_l
        dev = Box(-half_l, ystdd[-1] / dbu - 1, half_r, ystdu[-1] / dbu + 1)
        shapes(LayerDevRecN).insert(dev)
        dev_width = self.cell.bbox().width() / 2

        if 2 * r >= busL + 2 * taperL:
            dev_up = yu[-1] / dbu + taperL / dbu + (yu[3] + r - busL / 2 + 1 -
                                                    (yu[3] + taperL)) / dbu
            dev_down = yd[-4] / dbu - taperL / dbu - (yu[3] + r - busL / 2 +
                                                      1 -
                                                      (yu[3] + taperL)) / dbu
        else:
            dev_up = yu[-1] / dbu + taperL / dbu
            dev_down = yd[-4] / dbu - taperL / dbu

        # Create the pins on the waveguides, as short paths:
        from SiEPIC._globals import PIN_LENGTH as pin_length

        w = to_itype(self.w, dbu)
        gap = to_itype(self.gap, dbu)
        bus_length = to_itype(bus_length / 2, dbu)

        #Pin1
        #t = Trans(Trans.R0, dev_width-w/2,dev_up)
        t = Trans(Trans.R0, xstdu[-1] / dbu + 251, dev_up + 1)
        pin = Path([Point(0, -pin_length / 2),
                    Point(0, pin_length / 2)], 500)  #500 is width of std WG
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu
        print(dev_up)
        print(dev_up * dbu)
        #Pin2
        t = Trans(Trans.R0, xstdu[-1] / dbu + 251, dev_down - 1)
        pin = Path([Point(0, pin_length / 2), Point(0, -pin_length / 2)], 500)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin2", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu