示例#1
0
def is_cell_outside(cell_test: Device, cell_ref: Device, tolerance: float = 0):
    ''' Checks whether cell_test is not overlap with cell_ref.

    Parameters:
    ---------
    cell_test : Device

    cell_ref : Device

    tolerance : float (optional)

    Returns:
        True (if strictly cell_tot>=cell_test+cell_ref)
        False (otherwise).

    Note:
        if tolerance is not zero, then function returns True if cell_tot>=cell_test+cell_ref-tol
        in all direction
    '''

    if tolerance == 0:

        return _is_cell_outside(cell_test, cell_ref)

    else:

        shifts_set = np.array([[1, 1], [-1, -1], [1, -1], [-1, 1]]) * tolerance

        for shift in shifts_set:

            cell_test.move(destination=shift)

            if not _is_cell_outside(cell_test, cell_ref):

                cell_test.move(destination=-shift)

                return False

            else:

                cell_test.move(destination=-shift)

        else:

            return True
示例#2
0
文件: routing.py 项目: xunguan/phidl
def route_manhattan90(port1, port2, bendType='circular', layer=0, radius=20):
    #this is a subroutine of route_manhattan() and should not be used by itself.
    Total = Device()
    width = port1.width
    #first map into uniform plane with normal x,y coords
    #allows each situation to be put into uniform cases of quadrants for routing.
    #this is because bends change direction and positioning.
    if port1.orientation == 0:
        p2 = [port2.midpoint[0], port2.midpoint[1]]
        p1 = [port1.midpoint[0], port1.midpoint[1]]
    if port1.orientation == 90:
        p2 = [port2.midpoint[1], -port2.midpoint[0]]
        p1 = [port1.midpoint[1], -port1.midpoint[0]]
    if port1.orientation == 180:
        p2 = [-port2.midpoint[0], -port2.midpoint[1]]
        p1 = [-port1.midpoint[0], -port1.midpoint[1]]
    if port1.orientation == 270:
        p2 = [-port2.midpoint[1], port2.midpoint[0]]
        p1 = [-port1.midpoint[1], port1.midpoint[0]]

    #create placeholder ports based on the imaginary coordinates we created
    Total.add_port(name='t1', midpoint=[0, 0], orientation=0, width=width)

    #CHECK THIS

    #first quadrant target, route upward
    if (p2[1] > p1[1]) & (p2[0] > p1[0]):
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=-90,
                       width=width)
        if bendType == 'circular':
            B1 = _arc(radius=radius,
                      width=width,
                      layer=layer,
                      angle_resolution=1,
                      start_angle=0,
                      theta=90)
            radiusEff = radius
        if bendType == 'gradual':
            B1 = _gradual_bend(radius=radius,
                               width=width,
                               layer=layer,
                               start_angle=0,
                               direction='ccw')
            radiusEff = B1.xsize - width / 2
        b1 = Total.add_ref(B1)
        b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
        b1.move([p2[0] - p1[0] - radiusEff, 0])

        R1 = route_basic(port1=Total.ports['t1'],
                         port2=b1.ports[1],
                         layer=layer)
        R2 = route_basic(port1=b1.ports[2],
                         port2=Total.ports['t2'],
                         layer=layer)
        r1 = Total.add_ref(R1)
        r2 = Total.add_ref(R2)
        Total.add_port(name=1, port=r1.ports[1])
        Total.add_port(name=2, port=r2.ports[2])

    #fourth quadrant target, route downward
    if (p2[1] < p1[1]) & (p2[0] > p1[0]):
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=90,
                       width=width)
        if bendType == 'circular':
            B1 = _arc(radius=radius,
                      width=width,
                      layer=layer,
                      angle_resolution=1,
                      start_angle=0,
                      theta=-90)
            radiusEff = radius
        if bendType == 'gradual':
            B1 = _gradual_bend(radius=radius,
                               width=width,
                               layer=layer,
                               start_angle=0,
                               direction='cw')
            radiusEff = B1.xsize - width / 2
        b1 = Total.add_ref(B1)
        b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
        b1.move([p2[0] - p1[0] - radiusEff, 0])
        R1 = route_basic(port1=Total.ports['t1'],
                         port2=b1.ports[1],
                         layer=layer)
        R2 = route_basic(port1=b1.ports[2],
                         port2=Total.ports['t2'],
                         layer=layer)
        r1 = Total.add_ref(R1)
        r2 = Total.add_ref(R2)
        Total.add_port(name=1, port=r1.ports[1])
        Total.add_port(name=2, port=r2.ports[2])
    Total.rotate(angle=port1.orientation, center=p1)
    Total.move(origin=Total.ports['t1'], destination=port1)

    return Total
示例#3
0
文件: routing.py 项目: xunguan/phidl
def route_manhattan180(port1, port2, bendType='circular', layer=0, radius=20):
    #this is a subroutine of route_manhattan() and should not be used by itself.
    Total = Device()
    width = port1.width
    #first map into uniform plane with normal x,y coords
    #allows each situation to be put into uniform cases of quadrants for routing.
    #this is because bends change direction and positioning.
    if port1.orientation == 0:
        p2 = [port2.midpoint[0], port2.midpoint[1]]
        p1 = [port1.midpoint[0], port1.midpoint[1]]
    if port1.orientation == 90:
        p2 = [port2.midpoint[1], -port2.midpoint[0]]
        p1 = [port1.midpoint[1], -port1.midpoint[0]]
    if port1.orientation == 180:
        p2 = [-port2.midpoint[0], -port2.midpoint[1]]
        p1 = [-port1.midpoint[0], -port1.midpoint[1]]
    if port1.orientation == 270:
        p2 = [-port2.midpoint[1], port2.midpoint[0]]
        p1 = [-port1.midpoint[1], port1.midpoint[0]]

    #create placeholder ports based on the imaginary coordinates we created
    Total.add_port(name='t1', midpoint=[0, 0], orientation=0, width=width)
    if (port1.orientation != port2.orientation):
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=180,
                       width=width)
    else:
        Total.add_port(name='t2',
                       midpoint=list(np.subtract(p2, p1)),
                       orientation=0,
                       width=width)

    if port1.orientation == port2.orientation:
        #first quadrant target
        if (p2[1] > p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0], 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])
        #second quadrant target
        if (p2[1] > p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 2])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b2.ports[2],
                             port2=Total.ports['t2'],
                             layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=b1.ports[1])
            Total.add_port(name=2, port=r2.ports[2])
        #third quadrant target
        if (p2[1] < p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 2])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b2.ports[2],
                             port2=Total.ports['t2'],
                             layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=b1.ports[1])
            Total.add_port(name=2, port=r2.ports[2])
        #fourth quadrant target
        if (p2[1] < p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0], 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])

    #other port orientations are not supported:
    elif np.round(np.abs(np.mod(port1.orientation - port2.orientation, 360)),
                  3) != 180:
        raise ValueError(
            '[DEVICE] route() error: Ports do not face each other (orientations must be 180 apart)'
        )
    #otherwise, they are 180 degrees apart:
    else:
        #first quadrant target
        if (p2[1] > p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0] - radiusEff * 2, 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])
        #second quadrant target
        if (p2[1] > p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=90)
                B3 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=180,
                          theta=-90)
                B4 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=90,
                          theta=-90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='ccw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='ccw')
                B3 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=180,
                                   direction='cw')
                B4 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=90,
                                   direction='cw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b3 = Total.add_ref(B3)
            b4 = Total.add_ref(B4)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] - radiusEff * 4])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            b3.connect(port=b3.ports[1], destination=b2.ports[2])
            b3.move([p2[0] - p1[0], 0])
            R2 = route_basic(port1=b2.ports[2], port2=b3.ports[1], layer=layer)
            r2 = Total.add_ref(R2)

            b4.connect(port=b4.ports[1], destination=b3.ports[2])

            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b4.ports[2])
        #third quadrant target
        if (p2[1] < p1[1]) & (p2[0] < p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=-90)
                B3 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-180,
                          theta=90)
                B4 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='cw')
                B3 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-180,
                                   direction='ccw')
                B4 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)
            b3 = Total.add_ref(B3)
            b4 = Total.add_ref(B4)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])

            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 4])
            R1 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r1 = Total.add_ref(R1)
            b3.connect(port=b3.ports[1], destination=b2.ports[2])
            b3.move([p2[0] - p1[0], 0])
            R2 = route_basic(port1=b2.ports[2], port2=b3.ports[1], layer=layer)
            r2 = Total.add_ref(R2)

            b4.connect(port=b4.ports[1], destination=b3.ports[2])

            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b4.ports[2])
        #fourth quadrant target
        if (p2[1] < p1[1]) & (p2[0] > p1[0]):
            if bendType == 'circular':
                B1 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=0,
                          theta=-90)
                B2 = _arc(radius=radius,
                          width=width,
                          layer=layer,
                          angle_resolution=1,
                          start_angle=-90,
                          theta=90)
                radiusEff = radius
            if bendType == 'gradual':
                B1 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=0,
                                   direction='cw')
                B2 = _gradual_bend(radius=radius,
                                   width=width,
                                   layer=layer,
                                   start_angle=-90,
                                   direction='ccw')
                radiusEff = B1.xsize - width / 2
            b1 = Total.add_ref(B1)
            b2 = Total.add_ref(B2)

            b1.connect(port=b1.ports[1], destination=Total.ports['t1'])
            b1.move([p2[0] - p1[0] - radiusEff * 2, 0])
            b2.connect(port=b2.ports[1], destination=b1.ports[2])
            b2.move([0, p2[1] - p1[1] + radiusEff * 2])
            R1 = route_basic(port1=Total.ports['t1'],
                             port2=b1.ports[1],
                             layer=layer)
            r1 = Total.add_ref(R1)
            R2 = route_basic(port1=b1.ports[2], port2=b2.ports[1], layer=layer)
            r2 = Total.add_ref(R2)
            Total.add_port(name=1, port=r1.ports[1])
            Total.add_port(name=2, port=b2.ports[2])

    Total.rotate(angle=port1.orientation, center=p1)
    Total.move(origin=Total.ports['t1'], destination=port1)
    return Total
示例#4
0
文件: routing.py 项目: xunguan/phidl
def route_basic(port1,
                port2,
                path_type='sine',
                width_type='straight',
                width1=None,
                width2=None,
                num_path_pts=99,
                layer=0):

    # Assuming they're both Ports for now
    point_a = np.array(port1.midpoint)
    if width1 is None: width1 = port1.width
    point_b = np.array(port2.midpoint)
    if width2 is None: width2 = port2.width
    if round(abs(mod(port1.orientation - port2.orientation, 360)), 3) != 180:
        raise ValueError(
            '[DEVICE] route() error: Ports do not face each other (orientations must be 180 apart)'
        )
    orientation = port1.orientation

    separation = point_b - point_a  # Vector drawn from A to B
    distance = norm(separation)  # Magnitude of vector from A to B
    rotation = np.arctan2(
        separation[1],
        separation[0]) * 180 / pi  # Rotation of vector from A to B
    angle = rotation - orientation  # If looking out along the normal of ``a``, the angle you would have to look to see ``b``
    forward_distance = distance * cos(angle * pi / 180)
    lateral_distance = distance * sin(angle * pi / 180)

    # Create a path assuming starting at the origin and setting orientation = 0
    # use the "connect" function later to move the path to the correct location
    xf = forward_distance
    yf = lateral_distance
    if path_type == 'straight':
        curve_fun = lambda t: [xf * t, yf * t]
        curve_deriv_fun = lambda t: [xf + t * 0, t * 0]
    if path_type == 'sine':
        curve_fun = lambda t: [xf * t, yf * (1 - cos(t * pi)) / 2]
        curve_deriv_fun = lambda t: [xf + t * 0, yf * (sin(t * pi) * pi) / 2]
    #if path_type == 'semicircle':
    #    def semicircle(t):
    #        t = np.array(t)
    #        x,y = np.zeros(t.shape), np.zeros(t.shape)
    #        ii = (0 <= t) & (t <= 0.5)
    #        jj = (0.5 < t) & (t <= 1)
    #        x[ii] = (cos(-pi/2 + t[ii]*pi/2))*xf
    #        y[ii] = (sin(-pi/2 + t[ii]*pi/2)+1)*yf*2
    #        x[jj] = (cos(pi*3/2 - t[jj]*pi)+2)*xf/2
    #        y[jj] = (sin(pi*3/2 - t[jj]*pi)+1)*yf/2
    #        return x,y
    #    curve_fun = semicircle
    #    curve_deriv_fun = None
    if width_type == 'straight':
        width_fun = lambda t: (width2 - width1) * t + width1
    if width_type == 'sine':
        width_fun = lambda t: (width2 - width1) * (1 - cos(t * pi)
                                                   ) / 2 + width1

    route_path = gdspy.Path(width=width1, initial_point=(0, 0))
    route_path.parametric(curve_fun,
                          curve_deriv_fun,
                          number_of_evaluations=num_path_pts,
                          max_points=199,
                          final_width=width_fun,
                          final_distance=None)
    route_path_polygons = route_path.polygons

    # Make the route path into a Device with ports, and use "connect" to move it
    # into the proper location
    D = Device()
    D.add_polygon(route_path_polygons, layer=layer)
    p1 = D.add_port(name=1, midpoint=(0, 0), width=width1, orientation=180)
    p2 = D.add_port(name=2,
                    midpoint=[forward_distance, lateral_distance],
                    width=width2,
                    orientation=0)
    D.info['length'] = route_path.length

    D.rotate(angle=180 + port1.orientation - p1.orientation,
             center=p1.midpoint)
    D.move(origin=p1, destination=port1)
    return D
示例#5
0
def text(text='abcd', size=10, justify='left', layer=0, font="DEPLOF"):
    """ Creates geometries of text

    Parameters
    ----------
    text : str
        Text string to be written.
    size : int or float
        Size of the text
    justify : {'left', 'right', 'center'}
        Justification of the text.
    layer : int, array-like[2], or set
        Specific layer(s) to put polygon geometry on.
    font: str
        Font face to use. Default DEPLOF does not require additional libraries, otherwise
        freetype will be used to load fonts. Font can be given either by name (e.g. "Times New Roman"),
        or by file path. OTF or TTF fonts are supported.

    Returns
    -------
    t : Device
        A Device containing the text geometry.
    """
    t = Device('text')
    xoffset = 0
    yoffset = 0

    face = font
    if face == "DEPLOF":
        scaling = size / 1000

        for line in text.split('\n'):
            l = Device(name='textline')
            for c in line:
                ascii_val = ord(c)
                if c == ' ':
                    xoffset += 500 * scaling
                elif (33 <= ascii_val <= 126) or (ascii_val == 181):
                    for poly in _glyph[ascii_val]:
                        xpts = np.array(poly)[:, 0] * scaling
                        ypts = np.array(poly)[:, 1] * scaling
                        l.add_polygon([xpts + xoffset, ypts + yoffset],
                                      layer=layer)
                    xoffset += (_width[ascii_val] +
                                _indent[ascii_val]) * scaling
                else:
                    valid_chars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~µ'
                    warnings.warn('[PHIDL] text(): Warning, some characters ignored, no geometry for character "%s" with ascii value %s. ' \
                                  'Valid characters: %s' % (chr(ascii_val), ascii_val, valid_chars))
            t.add_ref(l)
            yoffset -= 1500 * scaling
            xoffset = 0
    else:
        from .font import _get_font_by_name, _get_font_by_file, _get_glyph

        # Load the font
        # If we've passed a valid file, try to load that, otherwise search system fonts
        font = None
        if (face.endswith(".otf")
                or face.endswith(".ttf")) and os.path.exists(face):
            font = _get_font_by_file(face)
        else:
            try:
                font = _get_font_by_name(face)
            except ValueError:
                pass
        if font is None:
            raise ValueError((
                '[PHIDL] Failed to find font: "%s". ' +
                'Try specifying the exact (full) path to the .ttf or .otf file. '
                +
                'Otherwise, it might be resolved by rebuilding the matplotlib font cache'
            ) % (face))

        # Render each character
        for line in text.split('\n'):
            l = Device('textline')
            xoffset = 0
            for letter in line:
                letter_dev = Device("letter")
                letter_template, advance_x = _get_glyph(font, letter)
                for poly in letter_template.polygons:
                    letter_dev.add_polygon(poly.polygons, layer=layer)
                ref = l.add_ref(letter_dev)
                ref.move(destination=(xoffset, 0))
                ref.magnification = size
                xoffset += size * advance_x

            ref = t.add_ref(l)
            ref.move(destination=(0, yoffset))
            yoffset -= size

    justify = justify.lower()
    for l in t.references:
        if justify == 'left': pass
        if justify == 'right': l.xmax = 0
        if justify == 'center':
            l.move(origin=l.center, destination=(0, 0), axis='x')

    t.flatten()
    return t