Esempio n. 1
0
 def DPathPolygon(pts, width, start, end, giveupsomepoints=False):
     region1 = pya.Region([
         pya.Polygon.from_dpoly(
             pya.DPath(pts, width, start, end).polygon())
     ])
     region2 = pya.Region([
         pya.Polygon.from_dpoly(
             pya.DPath(pts, width + 2000, start, end).polygon())
     ])
     polygon = list((region1 & region2).each_merged())[0]
     if giveupsomepoints:
         pts = []
         sourcepts = list(polygon.each_point_hull())
         for i, pt in enumerate(sourcepts):
             if i == 0 or pt.distance(pts[-1]) >= min(
                     1000, max(100, rounded)):
                 pts.append(pt)
         return pya.DPolygon(pts)
     return polygon
Esempio n. 2
0
  def __init__(self):

    # Important: initialize the super class
    super(CPW, self).__init__()

    # declare the parameters
    self.param("l", self.TypeLayer, "Layer", default = pya.LayerInfo(1, 0))
    self.param("s", self.TypeShape, "", default = pya.DPath(0, 0))
    self.param("w", self.TypeDouble, "Center Conductor width", default = 10)
    self.param("g", self.TypeInt, "Gap Width", default = 6)
    self.param("name", self.TypeString, "Name", default= "cpw")
    # this hidden parameter is used to determine whether the radius has changed
    # or the "s" handle has been moved
    self.param("length", self.TypeDouble, "Length", default=0.0, readonly=True)
    self.param("frequency", self.TypeDouble, "Frequency", default = 0.0, readonly= True)
    self.param("impedance", self.TypeDouble, "Impedance", default = 50., readonly = True)
Esempio n. 3
0
def port_to_pin_helper(ports_list, cell, layerPinRec):
    # Create the pins, as short paths:
    from siepic_tools.config import PIN_LENGTH
    dbu = cell.layout().dbu

    for port in ports_list:
        if port.name.startswith("el"):
            pin_length = port.width
        else:
            pin_length = PIN_LENGTH * dbu

        port_position_i = port.position.to_itype(dbu)
        cell.shapes(layerPinRec).insert(
            pya.DPath([port.position - 0.5 * pin_length * port.direction,
                       port.position + 0.5 * pin_length * port.direction], port.width).to_itype(dbu))
        cell.shapes(layerPinRec).insert(pya.Text(port.name, pya.Trans(
            pya.Trans.R0, port_position_i.x, port_position_i.y))).text_size = 2 / dbu
Esempio n. 4
0
    def translate_from_center(self, offset):
        from math import pi, cos, sin, acos, sqrt
        from .utils import angle_vector
        pts = [pt for pt in self.get_dpoints()]
        tpts = [pt for pt in self.get_dpoints()]
        for i in range(0, len(pts)):
            if i == 0:
                u = pts[i] - pts[i + 1]
                v = -u
            elif i == (len(pts) - 1):
                u = pts[i - 1] - pts[i]
                v = -u
            else:
                u = pts[i - 1] - pts[i]
                v = pts[i + 1] - pts[i]

            if offset < 0:
                o1 = pya.DPoint(abs(offset) * cos(angle_vector(u) * pi / 180 - pi / 2),
                                abs(offset) * sin(angle_vector(u) * pi / 180 - pi / 2))
                o2 = pya.DPoint(abs(offset) * cos(angle_vector(v) * pi / 180 + pi / 2),
                                abs(offset) * sin(angle_vector(v) * pi / 180 + pi / 2))
            else:
                o1 = pya.DPoint(abs(offset) * cos(angle_vector(u) * pi / 180 + pi / 2),
                                abs(offset) * sin(angle_vector(u) * pi / 180 + pi / 2))
                o2 = pya.DPoint(abs(offset) * cos(angle_vector(v) * pi / 180 - pi / 2),
                                abs(offset) * sin(angle_vector(v) * pi / 180 - pi / 2))

            p1 = u + o1
            p2 = o1
            p3 = v + o2
            p4 = o2
            d = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x)

            if round(d, 10) == 0:
                tpts[i] += p2
            else:
                tpts[i] += pya.DPoint(((p1.x * p2.y - p1.y * p2.x) * (p3.x - p4.x) - (p1.x - p2.x) * (p3.x * p4.y - p3.y * p4.x)) / d,
                                     ((p1.x * p2.y - p1.y * p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x * p4.y - p3.y * p4.x)) / d)

        if self.__class__ == pya.Path:
            return pya.Path([pya.Point(pt.x, pt.y) for pt in tpts], self.width)
        elif self.__class__ == pya.DPath:
            return pya.DPath(tpts, self.width)
Esempio n. 5
0
def layout_waveguide_rel(cell, layer, start_point, points, w, radius):
    # create a path, then convert to a polygon waveguide with bends
    # cell: cell into which to place the waveguide
    # layer: layer to draw on
    # start_point: starting vertex for the waveguide
    # points: array of vertices, relative to start_point
    # w: waveguide width

    # example usage:
    # cell = pya.Application.instance().main_window().current_view().active_cellview().cell
    # LayerSi = LayerInfo(1, 0)
    # points = [ [15, 2.75], [30, 2.75] ]  # units of microns.
    # layout_waveguide_rel(cell, LayerSi, [0,0], points, 0.5, 10)

    #print("* layout_waveguide_rel(%s, %s, %s, %s)" % (cell.name, layer, w, radius) )

    ly = cell.layout()
    dbu = cell.layout().dbu

    start_point = [start_point[0] / dbu, start_point[1] / dbu]

    a1 = []
    for p in points:
        a1.append(pya.DPoint(float(p[0]), float(p[1])))

    wg_path = pya.DPath(a1, w)

    npoints = points_per_circle(radius / dbu)
    param = {
        "npoints": npoints,
        "radius": float(radius),
        "path": wg_path,
        "layer": layer
    }

    pcell = ly.create_cell("ROUND_PATH", "Basic", param)

    # Configure the cell location
    trans = Trans(Point(start_point[0], start_point[1]))

    # Place the PCell
    cell.insert(pya.CellInstArray(pcell.cell_index(), trans))
Esempio n. 6
0
    pya.Point(50, 0),
    pya.Point(50, 50),
    pya.Point(40, 60),
    pya.Point(0, 50)
]
polygon1 = pya.Polygon(pts)
top.shapes(l1).insert(polygon1)
#DPath
dpts = [
    pya.DPoint(0.4, 0),
    pya.DPoint(50, 0),
    pya.DPoint(50, 50),
    pya.DPoint(40.5, 60.6),
    pya.DPoint(0, 50)
]
dpath1 = pya.DPath(dpts, 4, 5, 0, True)
top.shapes(l1).insert(pya.Path.from_dpath(dpath1))
#DCplxTrans
#倍数,逆时针度数,是否绕x翻转,平移x,平移y
tr = pya.DCplxTrans(10, 45, False, 1000, 1000)
#xxx.transform(tr)#本身改变
#xxx.transformed(tr)本身不变返回新的
#对一个点pt做变换的方法
#pya.DEdge(pya.DPoint(),pt).transformed(DCplxTrans).p2

#DText
text1 = pya.DText("TEST_Text", pya.DTrans(-10, -10), 100, 1)
top.shapes(l1).insert(pya.Text.from_dtext(text1))
#a text can be printed @ruby
#it dose not work in python
#lib.layout.pcell_declaration can't be found
Esempio n. 7
0
    def test_3_DTrans(self):

        c = pya.DCplxTrans(5.0, -7.0)
        self.assertEqual(str(c), "r0 *1 5,-7")

        c = pya.DCplxTrans(pya.DCplxTrans.M135)
        self.assertEqual(str(c), "m135 *1 0,0")
        self.assertEqual(c.is_unity(), False)
        self.assertEqual(c.is_ortho(), True)
        self.assertEqual(c.is_mag(), False)
        self.assertEqual(c.is_mirror(), True)
        self.assertEqual(c.rot(), pya.DCplxTrans.M135.rot())
        self.assertEqual(str(c.s_trans()), "m135 0,0")
        self.assertAlmostEqual(c.angle, 270)

        self.assertEqual(str(c.trans(pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str((c * pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str(c.trans(pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str((c * pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str(c.trans(pya.DText("text", pya.DVector(0, 1)))),
                         "('text',m135 -1,0)")
        self.assertEqual(str((c * pya.DText("text", pya.DVector(0, 1)))),
                         "('text',m135 -1,0)")
        self.assertEqual(
            str(
                c.trans(
                    pya.DPolygon([
                        pya.DPoint(0, 1),
                        pya.DPoint(2, -3),
                        pya.DPoint(4, 5)
                    ]))), "(-5,-4;-1,0;3,-2)")
        self.assertEqual(
            str((c * pya.DPolygon(
                [pya.DPoint(0, 1),
                 pya.DPoint(2, -3),
                 pya.DPoint(4, 5)]))), "(-5,-4;-1,0;3,-2)")
        self.assertEqual(
            str(c.trans(pya.DPath(
                [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))),
            "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false")
        self.assertEqual(
            str((c * pya.DPath(
                [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))),
            "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false")

        c = pya.DCplxTrans.from_itrans(pya.CplxTrans.M135)
        self.assertEqual(str(c), "m135 *1 0,0")

        c = pya.DCplxTrans(1.5)
        self.assertEqual(str(c), "r0 *1.5 0,0")
        self.assertEqual(c.is_unity(), False)
        self.assertEqual(c.is_ortho(), True)
        self.assertEqual(c.is_mag(), True)
        self.assertEqual(c.is_mirror(), False)
        self.assertEqual(c.rot(), pya.DCplxTrans.R0.rot())
        self.assertEqual(str(c.s_trans()), "r0 0,0")
        self.assertAlmostEqual(c.angle, 0)

        c = pya.DCplxTrans(0.75, 45, True, 2.5, -12.5)
        self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5")
        c = pya.DCplxTrans(0.75, 45, True, pya.DPoint(2.5, -12.5))
        self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5")
        self.assertEqual(c.is_unity(), False)
        self.assertEqual(c.is_ortho(), False)
        self.assertEqual(c.is_mag(), True)
        self.assertEqual(c.rot(), pya.DCplxTrans.M0.rot())
        self.assertEqual(str(c.s_trans()), "m0 2.5,-12.5")
        self.assertAlmostEqual(c.angle, 45)

        self.assertEqual(str(c.ctrans(5)), "3.75")
        self.assertEqual(str(c.trans(pya.DPoint(12, 16))),
                         "17.3492424049,-14.6213203436")

        self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0")
        self.assertEqual(pya.DCplxTrans().is_unity(), True)
        self.assertEqual((c * c.inverted()).is_unity(), True)

        c.mirror = False
        self.assertEqual(str(c), "r45 *0.75 2.5,-12.5")
        c.mag = 1.5
        self.assertEqual(str(c), "r45 *1.5 2.5,-12.5")
        c.disp = pya.DPoint(-1.0, 5.5)
        self.assertEqual(str(c), "r45 *1.5 -1,5.5")
        self.assertEqual(c.mag, 1.5)
        c.angle = 60
        self.assertEqual(str(c), "r60 *1.5 -1,5.5")
        self.assertEqual(("%g" % c.angle), "60")

        # Constructor variations
        self.assertEqual(str(pya.ICplxTrans()), "r0 *1 0,0")
        self.assertEqual(str(pya.ICplxTrans(1.5)), "r0 *1.5 0,0")
        self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20), 1.5)),
                         "r90 *1.5 10,20")
        self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20))),
                         "r90 *1 10,20")
        self.assertEqual(
            str(pya.ICplxTrans(1.5, 80, True, pya.Vector(100, 200))),
            "m40 *1.5 100,200")
        self.assertEqual(str(pya.ICplxTrans(1.5, 80, True, 100, 200)),
                         "m40 *1.5 100,200")
        self.assertEqual(str(pya.ICplxTrans(pya.Vector(100, 200))),
                         "r0 *1 100,200")
        self.assertEqual(str(pya.ICplxTrans(100, 200)), "r0 *1 100,200")
        self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200))),
                         "r0 *1 100,200")
        self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5)),
                         "r0 *1.5 150,300")
        self.assertEqual(
            str(
                pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5,
                               pya.Vector(10, 20))), "r0 *1.5 160,320")
        self.assertEqual(
            str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, 10, 20)),
            "r0 *1.5 160,320")

        self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0")
        self.assertEqual(str(pya.DCplxTrans(1.5)), "r0 *1.5 0,0")
        self.assertEqual(
            str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02), 1.5)),
            "r90 *1.5 0.01,0.02")
        self.assertEqual(str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02))),
                         "r90 *1 0.01,0.02")
        self.assertEqual(
            str(pya.DCplxTrans(1.5, 80, True, pya.DVector(0.1, 0.2))),
            "m40 *1.5 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(1.5, 80, True, 0.1, 0.2)),
                         "m40 *1.5 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(pya.DVector(0.1, 0.2))),
                         "r0 *1 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(0.1, 0.2)), "r0 *1 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2))),
                         "r0 *1 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5)),
                         "r0 *1.5 0.15,0.3")
        self.assertEqual(
            str(
                pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5,
                               pya.DVector(0.01, 0.02))), "r0 *1.5 0.16,0.32")
        self.assertEqual(
            str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, 0.01, 0.02)),
            "r0 *1.5 0.16,0.32")
Esempio n. 8
0
def layout_path_with_ends(cell, layer, point_iterator, w):
    dpath = pya.DPath(list(point_iterator), w, w / 2, w / 2)
    cell.shapes(layer).insert(dpath)
Esempio n. 9
0
def layout_path(cell, layer, point_iterator, w):
    path = pya.DPath(list(point_iterator), w, 0, 0).to_itype(cell.layout().dbu)
    cell.shapes(layer).insert(pya.Path.from_dpath(path))
Esempio n. 10
0
def layout_path_with_ends(cell, layer, point_iterator, w):
    ''' Simple wrapper for pya.DPath.'''
    dpath = pya.DPath(list(point_iterator), w, w / 2, w / 2)
    cell.shapes(layer).insert(dpath)
Esempio n. 11
0
    def produce_impl(self):
        size = []
        if len(self.size) < 2:
            if self.debug:
                print("Size < 2 dimension")
            if len(self.size) == 0:
                if self.debug:
                    print(
                        "paramter size has been adjusted to default - invalid data have provided"
                    )
                size = [100.0, 100.0]
            else:
                if self.debug:
                    print("Size has been adjusted to {}:{}".format(
                        self.size[0] / dbu, self.size[0] / dbu))
                size.append(float(self.size[0]))
                size.append(float(self.size[0]))
        else:
            size.append(float(self.size[0]))
            size.append(float(self.size[1]))

        ovSize = []
        if len(self.ovsize) < 2:
            if self.debug:
                print("overal size < 2 dimension")
            if len(self.ovsize) == 0:
                if self.debug:
                    print(
                        "paramter size has been adjusted to default - invalid data have provided"
                    )
                ovSize = [100.0, 100.0]
            else:
                ovSize.append(float(self.ovsize[0]))
                ovSize.append(float(self.ovsize[0]))
        else:
            ovSize.append(float(self.ovsize[0]))
            ovSize.append(float(self.ovsize[1]))

        #armLenght = self.armLenght
        armWidth = self.armWidth
        armBSS = self.armBMS
        activeArea = [size[0] - self.actOffset, size[1] - self.actOffset]
        #woW = self.woW/dbu
        #woOP = self.woOP/dbu

        # Membrane Geometry:
        memParts = []
        #   Firstly generate the centerpart
        memCenter = pya.Polygon(
            pya.DPolygon(
                pya.DBox(-size[0] / 2, -size[1] / 2, size[0] / 2,
                         size[1] / 2)))
        memParts.append(memParts)
        #   Time for beams
        #   Calculate the BeamArmcenter to the membrane edge, alias beam to memrane spacing
        memBMS = [(ovSize[0]-size[0]/2) -armBSS -armWidth/2,\
            (ovSize[1]-size[1]/2) -armBSS -armWidth/2]

        memBeam1 = pya.Polygon(pya.DPath([\
            pya.DPoint((size[0]-armWidth)/2, size[1]/2),\
            pya.DPoint((size[0]-armWidth)/2, size[1]/2+memBMS[1]),\
            pya.DPoint(-ovSize[0]/2, size[1]/2+memBMS[1])], armWidth).polygon())
        memParts.append(memBeam1)

        memBeam2 = pya.Polygon(pya.DPath([\
            pya.DPoint(-size[0]/2, (size[1]/2)-armWidth/2),\
            pya.DPoint(-size[0]-memBMS[0], size[1]/2-armWidth/2),\
            pya.DPoint(-size[0]-memBMS[0], -ovSize[1]/2)], armWidth).polygon())
        memParts.append(memBeam2)

        memBeam3 = pya.Polygon(pya.DPath([\
            pya.DPoint((-size[0]+armWidth)/2, -size[1]/2),\
            pya.DPoint((-size[0]+armWidth)/2, -size[1]/2-memBMS[1]),\
            pya.DPoint(ovSize[0]/2, -size[1]/2-memBMS[1])], armWidth).polygon())
        memParts.append(memBeam3)

        memBeam4 = pya.Polygon(pya.DPath([\
            pya.DPoint(size[0]/2, (-size[1]-armWidth)/2),\
            pya.DPoint(size[0]+memBMS[0], -size[1]/2+armWidth/2),\
            pya.DPoint(size[0]+memBMS[0], ovSize[1]/2)], armWidth).polygon())
        memParts.append(memBeam4)

        #here it would be probably useful to put them all into one polygon object (hopefully it\
        # would work ;))
        if self.debug:
            print(memParts)
            for member in memParts:
                self.cell.shapes(self.l_layer).insert(member)
        tr = pya.DCplxTrans(1000.0)  #workaround for difference in DBU
        region = pya.Region(memParts)
        region.merge()
        region.transform(tr)
        self.cell.shapes(self.l_layer).insert(region)

        #Active Area
        actBox = pya.DBox(-activeArea[0]/2, -activeArea[1]/2,\
             activeArea[0]/2, activeArea[1]/2)
        if self.showAct:
            self.cell.shapes(self.la_layer).insert(actBox)

        # Etch area - in this variant the overal size of membrane
        etchRegion = pya.Region(actBox)
        etchRegion.transform(tr)

        tempRegion = region ^ etchRegion
        etchRegion = tempRegion & etchRegion
        self.cell.shapes(self.ool_layer).insert(etchRegion)
Esempio n. 12
0
    def produce_impl(self):
        #Calculate layout database unit
        #dbu = self.layout.dbu
        dbu = 1
        size = []
        if len(self.size) < 2:
            if self.debug:
                print("Size < 2 dimension")
            if len(self.size) == 0:
                if self.debug:
                    print(
                        "paramter size has been adjusted to default - invalid data have provided"
                    )
                size = [100.0, 100.0]
            else:
                if self.debug:
                    print("Size has been adjusted to {}:{}".format(
                        self.size[0] / dbu, self.size[0] / dbu))
                size.append(float(self.size[0]) / dbu)
                size.append(float(self.size[0]) / dbu)
        else:
            size.append(float(self.size[0]) / dbu)
            size.append(float(self.size[1]) / dbu)

        ovSize = []
        if len(self.ovsize) < 2:
            if self.debug:
                print("overal size < 2 dimension")
            if len(self.ovsize) == 0:
                if self.debug:
                    print(
                        "paramter size has been adjusted to default - invalid data have provided"
                    )
                ovSize = [100.0, 100.0]
            else:
                ovSize.append(float(self.ovsize[0]) / dbu)
                ovSize.append(float(self.ovsize[0]) / dbu)
        else:
            ovSize.append(float(self.ovsize[0]) / dbu)
            ovSize.append(float(self.ovsize[1]) / dbu)

        armLenght = self.armLenght / dbu
        armWidth = self.armWidth / dbu
        activeArea = [size[0] - self.actOffset, size[1] - self.actOffset]
        woW = self.woW / dbu
        woOP = self.woOP / dbu

        # Membrane Geometry:

        ## arm location on a rectangle = edgeArmOffset
        edgeArmOffset = armWidth / 2 * math.sqrt(2)

        if self.debug:
            print("Size 0:{:.3f}, {}, {}".format(size[0], armLenght, armWidth))
        ## arm starts at following points
        pointArmA = pya.DPoint(size[0] / 2 - edgeArmOffset, size[1] / 2)
        pointArmD = pya.DPoint(size[0] / 2, size[1] / 2 - edgeArmOffset)

        ## arm ends in the point P - might be usefull as a connector point
        pointP = pya.DPoint(size[0] / 2 + armLenght / math.sqrt(2),
                            size[1] / 2 + armLenght / math.sqrt(2))

        ## arm edge points offsets from the center point P
        armEndPointoffset = armWidth / 2 / math.sqrt(2)

        ## Arm edge points in relation to the P point

        pointArmB = pya.DPoint(pointP.x - armEndPointoffset,
                               pointP.y + armEndPointoffset)
        pointArmC = pya.DPoint(pointP.x + armEndPointoffset,
                               pointP.y - armEndPointoffset)

        ## Lets Try to assemble the membrane as 1/4

        polyPoints = []
        polyPoints.append(pya.DPoint(0.0, 0.0))
        polyPoints.append(pya.DPoint(0.0, size[1] / 2))
        polyPoints.append(pointArmA)
        polyPoints.append(pointArmB)
        polyPoints.append(pointArmC)
        polyPoints.append(pointArmD)
        polyPoints.append(pya.DPoint(size[0] / 2, 0.0))

        #Lets put it there
        shapeSet = []

        Poly = pya.DPolygon(polyPoints)
        shapeSet.append(Poly)

        t = pya.DCplxTrans(1.0, 180, False, 0.0, 0.0)
        Poly1 = pya.DPolygon(polyPoints)
        Poly1.transform(t)
        shapeSet.append(Poly1)

        t = pya.DCplxTrans(1.0, 0, True, 0.0, 0.0)
        Poly2 = pya.DPolygon(polyPoints)
        Poly2.transform(t)
        shapeSet.append(Poly2)

        t = pya.DCplxTrans(1.0, 180, True, 0.0, 0.0)
        Poly3 = pya.DPolygon(polyPoints)
        Poly3.transform(t)
        shapeSet.append(Poly3)

        tr = pya.DCplxTrans(1000.0)
        region = pya.Region(shapeSet)
        region.merge()
        region.transform(tr)

        self.cell.shapes(self.l_layer).insert(region)

        #Active Area
        if self.showAct:
            actBox = pya.DBox(-activeArea[0] / 2, -activeArea[1] / 2,
                              activeArea[0] / 2, activeArea[1] / 2)
            self.cell.shapes(self.la_layer).insert(actBox)

        # Etch area - a rectangele limited by the membrane shape and P point
        etchBox = pya.DBox(-pointP.x, -pointP.y, pointP.x, pointP.y)
        etchRegion = pya.Region(etchBox)
        etchRegion.transform(tr)
        tempRegion = region ^ etchRegion
        etchRegion = tempRegion & etchRegion
        self.cell.shapes(self.ool_layer).insert(etchRegion)

        # Heater wire
        if self.genHeater:
            if self.heatType == 0:
                #Hilbert is defined only for square areas. We would fit whatever is smaller

                if activeArea[0] != activeArea[1]:
                    if (activeArea[0] > activeArea[1]):
                        wireArea = activeArea[1] / 2
                    else:
                        wireArea = activeArea[0] / 2
                else:
                    wireArea = activeArea[0] / 2

                #issue num2:
                #  the diagonal contact placemnet is required
                #  so we have to calculate space for the return path
                #  segment separation 1sqg => seg = wireArea / 2^n + 1

                Hcnt = 2**self.heatOrder + 1
                Hseg = wireArea / (Hcnt)
                print("Hseq: {:.3f}".format(Hseg))
                wireAreaRed = wireArea - Hseg
                a = wireAreaRed + wireAreaRed * 1j
                b = wireAreaRed - wireAreaRed * 1j
                z = 0

                for i in range(1, self.heatOrder + 1):
                    w = 1j * z.conjugate()
                    z = numpy.array([w - a, z - b, z + a, b - w]) / 2
                z = z.flatten()
                X = [x.real for x in z]
                Y = [x.imag for x in z]

                heatPoints = []

                for i in range(0, len(X)):
                    heatPoints.append(pya.DPoint(X[i], Y[i]))

                #lets add the return path
                #  start with calculation of intersection to the beam

                #  linEqa = -1*(pointP.y / pointP.x) - valid only for Square
                #
                #print("Linear equation is y = {:.3f}.x".format(linEqa))

                heatInitial = heatPoints[0]

                pointS1 = pya.DPoint(-size[0] / 2, size[1] / 2)
                #pointS2 = pya.DPoint(activeArea[0]/2, -activeArea[1]/2)
                if self.debug:
                    print("P:{:.3f},{:.3f} ; S:{:.3f},{:.3f}".format(
                        -pointP.x, pointP.y, pointS1.x, pointS1.y))
                linEqa = (pointP.y - pointS1.y) / (-pointP.x - pointS1.x)
                linEqb = pointP.y - linEqa * -pointP.x
                if self.debug:
                    print("Line equation is: y={:.3f}x+{:.3f}".format(
                        linEqa, linEqb))

                heatPoints.insert(
                    0, pya.DPoint(heatPoints[0].x - 2 * Hseg, heatPoints[0].y))
                heatPoints.insert(
                    0,
                    pya.DPoint(heatPoints[0].x,
                               linEqa * (heatPoints[0].x + Hseg) + linEqb))
                heatPoints.append(pya.DPoint(heatPoints[len(heatPoints)-1].x, \
                    linEqa*(heatPoints[len(heatPoints)-1].x+Hseg)-linEqb))

                heatPoints.append(pya.DPoint(pointP.x - Hseg,
                                             -pointP.y))  #arm contacts
                heatPoints.insert(0, pya.DPoint(-pointP.x - Hseg, pointP.y))

                #probably somewhere here is a good time to calculate perforations
                # teoretically first opening should be -Heg/2 to the left of the very first
                # point and should repeat in X and Y axis with interval of Hseg
                #

                # center is HeatPoints[2] -Hseg/2 ?
                if self.perfAct:
                    perfW = self.perfSize / 2 / dbu
                    #perfCenter = pya.DPoint(heatPoints[2].x - Hseg, heatPoints[2].y - Hseg)
                    #perfBox = pya.DBox(perfCenter.x-perfW, perfCenter.y-perfW, perfCenter.x+perfW, perfCenter.y-perfW)
                    elCell = self.layout.create_cell("Perforator")
                    perfBox = pya.DPolygon(
                        pya.DBox(-perfW, -perfW, perfW, perfW))
                    if self.roundPath:
                        perfBox = perfBox.round_corners(Hseg / 2, Hseg / 2, 32)
                    elCell.shapes(self.perfl_layer).insert(perfBox)

                    #lets make an array of them
                    x_vect = pya.DVector(2 * Hseg, 0.0)
                    y_vect = pya.DVector(0.0, 2 * Hseg)
                    t = pya.DCplxTrans(heatInitial.x, heatInitial.y + Hseg)
                    perfArr = pya.DCellInstArray(elCell.cell_index(), t,
                                                 x_vect, y_vect, Hcnt - 1,
                                                 Hcnt - 2)

                    self.cell.insert(perfArr)

                    #move to the right coordinates
                    pathT = pya.DCplxTrans(Hseg, 0)
                    heatPath = pya.DPath(heatPoints, self.heatW)
                    heatPathT = heatPath.transformed(pathT)
                    if self.roundPath:
                        heatPathT = heatPath.round_corners(Hseg / 2, 32, 0.001)
                        heatCenter = heatPathT.bbox().center()
                        print(heatCenter)
                        print("Rounded Path center: {}:{}".format(
                            heatCenter.x, heatCenter.y))
                        pathTr = pya.DCplxTrans(-heatCenter.x, -heatCenter.y)
                        heatPathT = heatPathT.transformed(pathTr)
                    self.cell.shapes(self.heatl_layer).insert(heatPathT)
            else:
                print("Wire definition has not been found!")
                #TODO ... other types of heaters

        if self.genWO:
            #we would make a wire connection from the P point to the edge of the membrane
            # overpass on both sides as an option

            # it has to be realized as a set of the 4 path
            print("Overal size: {}:{}".format(ovSize[0], ovSize[1]))
            woPathA = pya.DPath(
                [pointP, pya.DPoint(ovSize[0] / 2, ovSize[1] / 2)], woW, woOP,
                woOP)
            woPathB = pya.DPath([pya.DPoint(-pointP.x, pointP.y), pya.DPoint(-ovSize[0]/2, ovSize[1]/2)],\
                woW, woOP, woOP)
            woPathC = pya.DPath([pya.DPoint(-pointP.x, -pointP.y), pya.DPoint(-ovSize[0]/2, -ovSize[1]/2)],\
                woW, woOP, woOP)
            woPathD = pya.DPath([pya.DPoint(pointP.x, -pointP.y), pya.DPoint(ovSize[0]/2, -ovSize[1]/2)],\
                woW, woOP, woOP)
            self.cell.shapes(self.cntl_layer).insert(woPathA)
            self.cell.shapes(self.cntl_layer).insert(woPathB)
            self.cell.shapes(self.cntl_layer).insert(woPathC)
            self.cell.shapes(self.cntl_layer).insert(woPathD)

        if self.genCnt:
            # Ok that would be fun ...
            #   so at first we should be able to find how many of the IGC we would be able to fit
            #   in between of the perforations (maybe we should count also for the minimal separation)
            #   principally:
            #       single IGS pair consists of 2 wires and 2 gaps = IGSpairW?
            #       testing condition is therefore IGSCnt = floor((Hseg - perfW) / IGSpairW)
            cntW = self.cntW / dbu
            cntSp = self.cntSp / dbu
            cntB = self.cntB / dbu
            cntBunchW = 2 * (cntW + cntSp)
            cntCnt = math.floor((2 * Hseg - 2 * perfW) / cntBunchW)
            if self.debug:
                print("IDC W={}".format(cntBunchW))
                print("IDCs per bunch: {}".format(cntCnt))
            if cntCnt == 0:
                print(
                    "Error: Interdigital contacts with given specs could not be realized because of geometric containts!"
                )
            else:
                #lets make a subcell with interdigital pair
                #   so first calculate the active area - contact bars to get the lenght
                #   contacts singles
                cntCell = self.layout.create_cell("IDC_subcell")
                cntArrCell = self.layout.create_cell("IDC_cell")

                #cntLenght = activeArea - 2*cntB - cntSp

                cntPath_p1 = pya.DPoint((cntSp + cntW) / 2,
                                        activeArea[1] / 2 - cntB)
                cntPath_p2 = pya.DPoint((cntSp + cntW) / 2,
                                        -activeArea[1] / 2 + cntSp +
                                        cntB)  #TODO tohle je asi blbe ...
                cntPath_pA = [cntPath_p1, cntPath_p2]
                cntPath_pB = [cntPath_p1 * -1, cntPath_p2 * -1]

                cntPath_A = pya.DPath(cntPath_pA, cntW, 0.0, 0.0)
                cntPath_B = pya.DPath(cntPath_pB, cntW, 0.0, 0.0)

                cntCell.shapes(self.idcl_layer).insert(cntPath_A)
                cntCell.shapes(self.idcl_layer).insert(cntPath_B)

                #now lets make bunches of cntCnt and center them
                # TODO: tady jsem skoncil ... potreba projit odstavec pod
                #BEGIN
                x_vect = pya.DVector(cntBunchW, 0.0)
                y_vect = pya.DVector(0.0, 0.0)
                if self.debug:
                    print("IDC bunch Vectors: {}, {}, {}, {}".format(\
                        x_vect.x, x_vect.y, y_vect.x, y_vect.y))
                t = pya.DCplxTrans(0, 0)
                cntArr = pya.DCellInstArray(cntCell.cell_index(), t, x_vect,
                                            y_vect, cntCnt, 1)

                #center the origins on top of each other
                #   here we have a bunch of IDCs
                cntArr_center = cntArr.bbox(self.layout).center()
                if self.debug:
                    print("Bunch center: {},{}".format(cntArr_center.x,
                                                       cntArr_center.y))
                t = pya.DCplxTrans(1.0, 0, False, -cntArr_center.x,
                                   -cntArr_center.y)
                cntArr.transform(t)
                cntArrCell.insert(cntArr)

                #   move the array to the position of Hilb. initial and paste it into the overal array

                a_vect = pya.DVector(2 * Hseg, 0.0)
                b_vect = pya.DVector(0.0, 0.0)

                cntLoct = pya.DCplxTrans(1.0, 0, False, heatInitial.x - Hseg,
                                         0.0)

                cntArrAll = pya.DCellInstArray(cntArrCell.cell_index(),
                                               cntLoct, a_vect, b_vect, Hcnt,
                                               1)
                self.cell.insert(cntArrAll)

                #Top and bottom contact
                #  by principle the bar-contact should be horizontally oriented across the active zone
                #  then they should continue to the respective P-points (upright, lowerleft)

                #  Contact bar would be a box from the edge to the edge of active area with a width of
                #  cntB

                # pointCNT1A = pya.DPoint(activeArea[0]/2, activeArea[1]/2)

                # if self.debug:
                #     print("P:{:.3f},{:.3f} ; CNT:{:.3f},{:.3f}".format(-pointP.x, pointP.y, pointCNT1A.x, pointCNT1A.y))
                # linCntEqa = (pointP.y-pointCNT1A.y)/(-pointP.x-pointCNT1A.x)
                # linCntEqb = pointP.y - linCntEqa*-pointP.x

                # if self.debug:
                #     print("CNT line equation is: y={:.3f}x+{:.3f}".format(linEqa,linEqb))

                # pointCNT1B =

                # Contact Bars
                cntBarW = self.cntB / dbu
                cntWoW = self.cntWO / dbu
                shapeSetCNT = []
                #cntBarA
                shapeSetCNT.append(pya.DBox(-activeArea[0]/2, activeArea[1]/2-cntBarW,\
                    activeArea[0]/2, activeArea[1]/2))
                #cntBarB
                shapeSetCNT.append(pya.DBox(-activeArea[0]/2, -activeArea[1]/2,\
                    activeArea[0]/2, -activeArea[1]/2+cntBarW))

                pointS2 = pya.DPoint(activeArea[0] / 2, activeArea[1] / 2)
                #cntWOPathA
                shapeSetCNT.append(
                    pya.DPath([pointS2, pointP], cntWoW, cntWoW / 2,
                              cntWoW).polygon())
                #cntWOPathB
                shapeSetCNT.append(
                    pya.DPath([-pointS2, -pointP], cntWoW, cntWoW / 2,
                              cntWoW).polygon())

                for shape in shapeSetCNT:
                    self.cell.shapes(self.idcl_layer).insert(shape)

                #Vias
                #TODO: repair position of the vias

                cntViaW = cntWoW * 0.9 / 2  # 10% smaller then the wire
                tr = pya.DCplxTrans(1.0, 45.0, False, pya.DVector(pointP))
                cntViaA = pya.DPolygon(pya.DBox(-cntViaW, -cntViaW,\
                    cntViaW, cntViaW)).transform(tr)
                tr = pya.DCplxTrans(1.0, 45.0, False, pya.DVector(-pointP))
                cntViaB = pya.DPolygon(pya.DBox(-cntViaW, -cntViaW,\
                    cntViaW, cntViaW)).transformed(tr)
                self.cell.shapes(self.lvia_layer).insert(cntViaA)
                self.cell.shapes(self.lvia_layer).insert(cntViaB)
Esempio n. 13
0
    def DrawParametricCurve(cell, layer, brush, xfunc, yfunc, pointnumber,
                            startlength, deltalength, number, lengthlist):
        ''' 
        沿参数曲线画空心线, 并每一段间隔变宽一小段  
        返回曲线参数为0和参数为1的两端的笔刷 [brush0,brush1]

        lengthlist=[l1,l2,d1,w1,w2] 描述变宽部分, 其内外长度和间隔, 外内宽度  
        xfunc,yfunc 是曲线参数函数, 参数均匀从取0~1中取pointnumber个, pointnumber尽量取大但是也不要大到让程序变慢  

        待改进 todo : 智能选点匹配到 IO.pointdistance
        '''
        def getp(ll, p1, p2):
            bl = p1.distance(p2)
            dx = p2.x - p1.x
            dy = p2.y - p1.y
            k = 1.0 * ll / bl
            return pya.DPoint(p1.x + k * dx, p1.y + k * dy)

        #
        cpts = [
            pya.DPoint(xfunc(ii / (pointnumber - 1)),
                       yfunc(ii / (pointnumber - 1)))
            for ii in range(pointnumber)
        ]
        # todo : cpts智能选点匹配到 IO.pointdistance
        #
        outpolygons = []
        inpolygons = []
        #
        path = pya.DPath(cpts, brush.widout, 0, 0)
        polygon = path.polygon()
        outpolygons.append(polygon)
        path = pya.DPath(cpts, brush.widin, 3, 3)
        polygon = path.polygon()
        inpolygons.append(polygon)
        #
        l1 = lengthlist[0]
        l2 = lengthlist[1]
        d1 = lengthlist[2]
        w1 = lengthlist[3]
        w2 = lengthlist[4]
        #
        finishnumber = 0

        distance = 0

        startchecklength = startlength

        bigstartindex = 0
        bigstartp = None
        smallstartindex = 0
        smallstartp = None

        status = 0  # 1进入大矩阵 2进入小矩阵 3出小矩阵 0出大矩阵

        for i, pt in enumerate(cpts[1:-1], 1):
            delda = pt.distance(cpts[i - 1])
            distance = distance + delda
            # 进入大矩阵
            if status == 0 and distance >= startchecklength:
                status = 1
                bigstartindex = i
                bigstartp = getp(distance - startchecklength, pt, cpts[i - 1])
            # 进入小矩阵
            if status == 1 and distance >= startchecklength + d1:
                status = 2
                smallstartindex = i
                smallstartp = getp(distance - startchecklength - d1, pt,
                                   cpts[i - 1])
            # 出小矩阵
            if status == 2 and distance >= startchecklength + d1 + l2:
                status = 3
                smallendindex = i
                ep = getp(distance - startchecklength - d1 - l2, pt,
                          cpts[i - 1])
                temp = [smallstartp]
                temp.extend(cpts[smallstartindex:smallendindex - 1])
                temp.append(ep)
                path = pya.DPath(temp, w2, 0, 0)
                polygon = path.polygon()
                inpolygons.append(polygon)
            # 出大矩阵
            if status == 3 and distance >= startchecklength + l1:
                status = 0
                bigendindex = i
                ep = getp(distance - startchecklength - l1, pt, cpts[i - 1])
                temp = [bigstartp]
                temp.extend(cpts[bigstartindex:bigendindex - 1])
                temp.append(ep)
                path = pya.DPath(temp, w1, 0, 0)
                polygon = path.polygon()
                outpolygons.append(polygon)
                startchecklength += deltalength
                finishnumber += 1
                if finishnumber == number:
                    break

        if status == 3:
            inpolygons.pop()  # 状态是最后一个大矩阵未完成, 此时弹出不应有的对应的小矩阵

        region = pya.Region([pya.Polygon.from_dpoly(x) for x in outpolygons]) - \
            pya.Region([pya.Polygon.from_dpoly(x) for x in inpolygons])
        region.transform(pya.ICplxTrans.from_dtrans(brush.DCplxTrans))

        BasicPainter.Draw(cell, layer, region)

        p0 = cpts[0]
        p1 = cpts[1]
        brush0 = CavityBrush(pointc=p0,
                             angle=atan2(p0.y - p1.y, p0.x - p1.x),
                             widout=brush.widout,
                             widin=brush.widin,
                             bgn_ext=0)
        p0 = cpts[-1]
        p1 = cpts[-2]
        brush1 = CavityBrush(pointc=p0,
                             angle=atan2(p0.y - p1.y, p0.x - p1.x),
                             widout=brush.widout,
                             widin=brush.widin,
                             bgn_ext=0)
        return [brush0, brush1]
Esempio n. 14
0
def to_dtype(self, dbu):
  Dpath = pya.DPath(self.get_dpoints(), self.width) * dbu
  Dpath.width = self.width * dbu
  return Dpath
Esempio n. 15
0
def layout_ebeam_waveguide_from_points(cell,
                                       points_list,
                                       radius=None,
                                       width=None):
    """ Takes a list of points and calls SiEPIC Waveguide Pcell
        The points_list should be a rough shape of the waveguide.
        The points_list must be a manhattan path!
        This function will create a smooth waveguide by rounding the trace
        at every corner with a particular radius.

        For example, if points_list has three points forming a square of size
        R, then the output will be a 90-degree arc of radius R.
    """
    from math import floor

    TECHNOLOGY = EBEAM_TECH
    if radius is None:
        radius = WAVEGUIDE_RADIUS
    if width is None:
        width = WAVEGUIDE_WIDTH
    for point in points_list:
        point.x = floor(point.x * 1000) / 1000
        point.y = floor(point.y * 1000) / 1000

    for i in range(0, len(points_list) - 1):
        """
        Calculate the x distance and the y distance to the next point.
        Get the max of the above two numbers
        Set the other number to zero
        """
        posx = abs(points_list[i + 1].x - points_list[i].x)
        posy = abs(points_list[i + 1].y - points_list[i].y)
        if (abs(points_list[i + 1].x - points_list[i].x) > 0
                and abs(points_list[i + 1].y - points_list[i].y) > 0):
            if posx < posy:
                points_list[i + 1].x = points_list[i].x
            else:
                points_list[i + 1].y = points_list[i].y

    wg_dpath = pya.DPath(points_list, 0.5)
    layout = cell.layout()
    with suppress_stdout():
        wg_cell = layout.create_cell(
            "Waveguide",
            TECHNOLOGY["technology_name"],
            {
                "path": wg_dpath,
                "radius": radius,
                "width": width,
                "layers": ["Si"],
                "widths": [width],
                "offsets": [0],
            },
        )

    layerSi = layout.layer(TECHNOLOGY["Si"])
    # let's just get the shapes
    cell.shapes(layerSi).insert(wg_cell.shapes(layerSi))

    layout.delete_cell(wg_cell.cell_index())

    return cell