Example #1
0
def offset(
    elements,
    distance=0.1,
    join_first=True,
    precision=1e-4,
    num_divisions=[1, 1],
    join="miter",
    tolerance=2,
    max_points=4000,
    layer=0,
):
    """ returns an element containing all polygons with an offset
    from phidl geometry
    """
    if type(elements) is not list:
        elements = [elements]
    polygons_to_offset = []
    for e in elements:
        if isinstance(e, (Device, DeviceReference)):
            polygons_to_offset += e.get_polygons(by_spec=False)
        elif isinstance(e, (Polygon, gdspy.Polygon)):
            polygons_to_offset.append(e)
    if len(polygons_to_offset) == 0:
        return pp.Component("offset")
    polygons_to_offset = _merge_floating_point_errors(
        polygons_to_offset, tol=precision / 1000
    )
    gds_layer, gds_datatype = _parse_layer(layer)
    if all(np.array(num_divisions) == np.array([1, 1])):
        p = gdspy.offset(
            polygons_to_offset,
            distance=distance,
            join=join,
            tolerance=tolerance,
            precision=precision,
            join_first=join_first,
            max_points=max_points,
            layer=gds_layer,
            datatype=gds_datatype,
        )
    else:
        p = _offset_polygons_parallel(
            polygons_to_offset,
            distance=distance,
            num_divisions=num_divisions,
            join_first=join_first,
            precision=precision,
            join=join,
            tolerance=tolerance,
        )

    D = pp.Component("offset")
    polygons = D.add_polygon(p, layer=layer)
    [
        polygon.fracture(max_points=max_points, precision=precision)
        for polygon in polygons
    ]
    return D
Example #2
0
def text(
    text: str = "abcd",
    size: float = 10.0,
    position: Tuple[int, int] = (0, 0),
    justify: str = "left",
    layer: Tuple[int, int] = LAYER.TEXT,
) -> Component:
    """ adds text

    .. plot::
      :include-source:

      import pp

      c = pp.c.text(text="abcd", size=10, position=(0, 0), justify="left", layer=1)
      pp.plotgds(c)

    """
    scaling = size / 1000
    xoffset = position[0]
    yoffset = position[1]
    t = pp.Component(name=clean_name(text) +
                     "_{}_{}".format(int(position[0]), int(position[1])))
    for i, line in enumerate(text.split("\n")):
        label = pp.Component(name=t.name + "{}".format(i))
        for c in line:
            ascii_val = ord(c)
            if c == " ":
                xoffset += 500 * scaling
            elif 33 <= ascii_val <= 126:
                for poly in _glyph[ascii_val]:
                    xpts = np.array(poly)[:, 0] * scaling
                    ypts = np.array(poly)[:, 1] * scaling
                    label.add_polygon([xpts + xoffset, ypts + yoffset],
                                      layer=layer)
                xoffset += (_width[ascii_val] + _indent[ascii_val]) * scaling
            else:
                ValueError(
                    "[PHIDL] text(): No glyph for character with ascii value %s"
                    % ascii_val)
        t.add_ref(label)
        yoffset -= 1500 * scaling
        xoffset = position[0]
    justify = justify.lower()
    for label in t.references:
        if justify == "left":
            pass
        if justify == "right":
            label.xmax = position[0]
        if justify == "center":
            label.move(origin=label.center, destination=position, axis="x")
    return t
Example #3
0
def manhattan_text(text="abcd",
                   size=10,
                   position=(0, 0),
                   justify="left",
                   layer=LAYER.M1):
    """

    .. plot::
      :include-source:

      import pp

      c = pp.c.text(text="abcd", size=10, position=(0, 0), justify="left", layer=1)
      pp.plotgds(c)

    """
    pixel_size = size
    xoffset = position[0]
    yoffset = position[1]
    t = pp.Component(name=clean_name(text) +
                     "_{}_{}".format(int(position[0]), int(position[1])))
    for i, line in enumerate(text.split("\n")):
        l = pp.Component(name=t.name + "{}".format(i))
        for c in line:
            try:
                if c not in CHARAC_MAP:
                    c = c.upper()
                pixels = CHARAC_MAP[c]
            except:
                print(
                    "character {} could not be written (probably not part of dictionnary)"
                    .format(c))
                continue

            _c = l.add_ref(
                pixel_array(pixels=pixels, pixel_size=pixel_size, layer=layer))
            _c.move((xoffset, yoffset))
            l.absorb(_c)
            xoffset += pixel_size * 6

        t.add_ref(l)
        yoffset -= pixel_size * 6
        xoffset = position[0]
    justify = justify.lower()
    for l in t.references:
        if justify == "left":
            pass
        if justify == "right":
            l.xmax = position[0]
        if justify == "center":
            l.move(origin=l.center, destination=position, axis="x")
    return t
Example #4
0
def circle(
    radius: float = 10.0,
    angle_resolution: float = 2.5,
    layer: Tuple[int, int] = pp.LAYER.WG,
) -> Component:
    """ Generate a circle geometry.

    Args:
        radius: float, Radius of the circle.
        angle_resolution: float, Resolution of the curve of the ring (# of degrees per point).
        layer: (int, array-like[2], or set) Specific layer(s) to put polygon geometry on.

    .. plot::
      :include-source:

      import pp

      c = pp.c.circle(radius = 10, angle_resolution = 2.5, layer = 0)
      pp.plotgds(c)

    """

    c = pp.Component()
    t = np.linspace(0, 360, int(360 / angle_resolution) + 1) * pi / 180
    xpts = (radius * cos(t)).tolist()
    ypts = (radius * sin(t)).tolist()
    c.add_polygon(points=(xpts, ypts), layer=layer)
    return c
Example #5
0
def linespace(
    x0: float,
    y0: float,
    width: float,
    height: float,
    pitch: float,
    ymax: float,
    layer: Tuple[int, int],
) -> Component:
    """Creates a line space pattern in y-direction.

    Args:
        x0: x coordinate of the lower left line
        y0: y coordinate of the lower left line
        width: width of each line
        height: height of each line
        pitch: pitch of each line
        pitch > height
    """
    assert abs(pitch) < abs(height), "pitch must be greater then height"
    LS = pp.Component()
    if pitch > 0:
        while y0 + height <= ymax:
            Li = line(x0=x0, y0=y0, width=width, height=height, layer=layer)
            LS.add_ref(Li)
            y0 += pitch
    elif pitch < 0:
        while y0 + height >= -ymax:
            Li = line(x0=x0, y0=y0, width=width, heigh=height, layer=layer)
            LS.add_ref(Li)
            y0 += pitch
    return LS
Example #6
0
def align_wafer(
    width=10.0,
    spacing=10.0,
    cross_length=80.0,
    layer=pp.LAYER.WG,
    with_tile_excl=True,
    square_corner="bottom_left",
):
    """ returns cross inside a frame to align wafer

    .. plot::
      :include-source:

      import pp

      c = pp.c.align_wafer()
      pp.plotgds(c)

    """
    c = pp.Component()
    cross = pp.c.cross(length=cross_length, width=width, layer=layer)
    c.add_ref(cross)

    b = cross_length / 2 + spacing + width / 2
    w = width

    rh = rectangle(size=(2 * b + w, w), layer=layer, centered=True)
    rtop = c.add_ref(rh)
    rbot = c.add_ref(rh)
    rtop.movey(+b)
    rbot.movey(-b)

    rv = rectangle(w=w, h=2 * b, layer=layer, centered=True)
    rl = c.add_ref(rv)
    rr = c.add_ref(rv)
    rl.movex(-b)
    rr.movex(+b)

    wsq = (cross_length + 2 * spacing) / 4
    square_mark = c << rectangle(size=(wsq, wsq), layer=layer, centered=True)
    a = width / 2 + wsq / 2 + spacing

    corner_to_position = {
        "bottom_left": (-a, -a),
        "bottom_right": (a, -a),
        "top_right": (a, a),
        "top_left": (-a, a),
    }

    square_mark.move(corner_to_position[square_corner])

    if with_tile_excl:
        rc_tile_excl = rectangle(
            size=(2 * (b + spacing), 2 * (b + spacing)),
            layer=pp.LAYER.NO_TILE_SI,
            centered=True,
        )
        c.add_ref(rc_tile_excl)

    return c
Example #7
0
def reticle_mockup():
    from pp.layers import LAYER

    dx = 9000.0
    dy = 8000.0
    a0 = 50.0
    component = pp.Component()
    for x in [0, dx, 2 * dx, 3 * dx]:
        a = x + a0
        b = x - a0

        component.add_polygon(
            [(a, 0), (b, 0), (b, 3 * dy), (a, 3 * dy)], LAYER.FLOORPLAN
        )

    for y in [0, dy, 2 * dy, 3 * dy]:
        a = y + a0
        b = y - a0
        component.add_polygon(
            [(0, a), (0, b), (3 * dx, b), (3 * dx, a)], LAYER.FLOORPLAN
        )

    c = mini_block_mockup()

    for i, j in [(0, 0), (2, 2), (0, 2), (2, 0), (1, 1)]:
        component.add(c.ref(position=(i * dx, j * dy)))

    return component
def test_connect_bundle_waypointsB():
    import pp
    from pp.component import Port

    ys1 = np.array([0, 5, 10, 15, 30, 40, 50, 60]) + 0.0
    ys2 = np.array([0, 10, 20, 30, 70, 90, 110, 120]) + 500.0
    N = ys1.size

    ports1 = [Port("A_{}".format(i), (0, ys1[i]), 0.5, 0) for i in range(N)]
    ports2 = [
        Port("B_{}".format(i), (500, ys2[i]), 0.5, 180) for i in range(N)
    ]

    p0 = ports1[0].position + (0, 22.5)

    top_cell = pp.Component()
    way_points = [
        p0,
        p0 + (200, 0),
        p0 + (200, -200),
        p0 + (400, -200),
        (p0[0] + 400, ports2[0].y),
        ports2[0].position,
    ]

    elements = connect_bundle_waypoints(ports1, ports2, way_points)
    top_cell.add(elements)

    return top_cell
Example #9
0
def demo():
    """plot curvature of bends
    """
    from matplotlib import pyplot as plt

    c = crossing45(port_spacing=20.0, dx=15)
    c2 = compensation_path(crossing45=c)
    print(c.info["min_bend_radius"])
    print(c2.info["min_bend_radius"])

    component = pp.Component(name="top_lvl")
    component.add(c.ref(port_id="W0"))
    component.add(c2.ref(port_id="W0", position=(0, 10)))

    bend_info1 = c.info["components"]["bezier_bend"].info
    bend_info2 = c2.info["components"]["sbend"].info

    DL = bend_info1["length"]
    L2 = bend_info1["length"]
    plt.plot(bend_info1["t"][1:-1] * DL, abs(bend_info1["curvature"]))
    plt.plot(bend_info2["t"][1:-1] * L2, abs(bend_info2["curvature"]))
    plt.xlabel("bend length (um)")
    plt.ylabel("curvature (um^-1)")
    pp.show(component)
    plt.show()
Example #10
0
def add_pins(
    component: Component,
    function: Callable = _add_pins_labels_and_outline,
    recursive: bool = False,
) -> Component:
    """Add pins to a Component and returns a container

    Args:
        component:
        function: function to add pins
        recursive: goes down the hierarchy

    Returns:
        New component
    """

    component_new = pp.Component(f"{component.name}_pins")
    reference = component_new << component
    function(component=component_new, reference=reference)

    if recursive:
        for reference in component.references:
            function(component=component_new, reference=reference)

    return component_new
Example #11
0
def ellipse(
    radii: Tuple[float, float] = (10.0, 5.0),
    angle_resolution: float = 2.5,
    layer: Tuple[int, int] = pp.LAYER.WG,
) -> Component:
    """Generate an ellipse geometry.

    Args:
        radii: (tuple) Semimajor and semiminor axis lengths of the ellipse.
        angle_resolution: (float) Resolution of the curve of the ring (# of degrees per point).
        layer: (int, array-like[2], or set) Specific layer(s) to put polygon geometry on.

    The orientation of the ellipse is determined by the order of the radii variables;
    if the first element is larger, the ellipse will be horizontal and if the second
    element is larger, the ellipse will be vertical.

    .. plot::
      :include-source:

      import pp

      c = pp.c.ellipse(radii=(10, 5), angle_resolution=2.5, layer=0)
      pp.plotgds(c)

    """

    D = pp.Component()
    a = radii[0]
    b = radii[1]
    t = np.linspace(0, 360, int(360 / angle_resolution) + 1) * pi / 180
    r = a * b / (sqrt((b * cos(t))**2 + (a * sin(t))**2))
    xpts = r * cos(t)
    ypts = r * sin(t)
    D.add_polygon(points=(xpts, ypts), layer=layer)
    return D
Example #12
0
def test_connect_u_direct():
    w = h = 10
    c = pp.Component()
    pad_south = pp.c.pad_array(port_list=["S"], spacing=(15, 0), width=w, height=h)
    pt = c << pad_south
    pb = c << pad_south
    pb.rotate(90)
    pt.rotate(90)
    pb.move((0, -100))

    pbports = pb.get_ports_list()
    ptports = pt.get_ports_list()

    pbports.reverse()

    r = pp.routing.connect_bundle(pbports, ptports)
    # r = pp.routing.link_ports(pbports, ptports) # does not work
    c.add(r)
    # print(r[0].parent.length)
    # print(r[1].parent.length)
    # print(r[2].parent.length)
    # print(r[3].parent.length)
    # print(r[4].parent.length)
    # print(r[5].parent.length)
    assert np.isclose(r[0].parent.length, 36.435926535897934)
    assert np.isclose(r[1].parent.length, 76.43592653589793)
    assert np.isclose(r[2].parent.length, 116.43592653589793)
    assert np.isclose(r[3].parent.length, 156.43592653589792)
    assert np.isclose(r[4].parent.length, 196.43592653589795)
    assert np.isclose(r[5].parent.length, 236.43592653589795)
    return c
Example #13
0
def test_connect_bundle_optical3():
    """ connect 4 waveguides into a 4x1 component """
    c = pp.Component()

    w = c << pp.c.waveguide_array(n_waveguides=4, spacing=200)
    d = c << pp.c.nxn(west=4, east=1)
    d.y = w.y
    d.xmin = w.xmax + 200

    ports1 = w.get_ports_list(prefix="E")
    ports2 = d.get_ports_list(prefix="W")

    r = pp.routing.link_optical_ports(ports1, ports2, sort_ports=True)
    # print(r[0].parent.length)
    # print(r[1].parent.length)
    # print(r[2].parent.length)
    # print(r[3].parent.length)

    assert np.isclose(r[0].parent.length, 489.4159265358979)
    assert np.isclose(r[3].parent.length, 489.4159265358979)

    assert np.isclose(r[1].parent.length, 290.74892653589797)
    assert np.isclose(r[2].parent.length, 290.74892653589797)
    c.add(r)
    return c
def test_route_south():
    c = pp.Component()
    cr = c << pp.c.mmi2x2()
    routes, ports = pp.routing.route_south(cr)

    lengths = [
        15.708,
        1.0,
        0.5,
        15.708,
        5.0,
        1.6499999999999968,
        15.708,
        1.0,
        0.5,
        15.708,
        5.0,
        1.6499999999999968,
    ]
    for route, length in zip(routes, lengths):
        c.add(route)
        route_length = route.parent.get_settings()["info"]["length"]
        print(route_length)
        assert np.isclose(route_length, length)
    return c
Example #15
0
def test_path_length_matching_nb_loops():
    c = pp.Component("path_length_match_sample")

    dy = 2000.0
    xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650]

    pitch = 100.0
    N = len(xs1)
    xs2 = [-20 + i * pitch for i in range(N)]

    a1 = 90
    a2 = a1 + 180

    ports1 = [pp.Port(f"top_{i}", (xs1[i], 0), 0.5, a1) for i in range(N)]
    ports2 = [pp.Port(f"bottom_{i}", (xs2[i], dy), 0.5, a2) for i in range(N)]

    routes = pp.routing.connect_bundle_path_length_match(ports1,
                                                         ports2,
                                                         nb_loops=2)
    for route in routes:
        # print(route.parent.length)
        assert np.isclose(route.parent.length, 2681.07963267949)
    c.add(routes)
    c.routes = routes
    return c
Example #16
0
def crossing(arm: Callable = crossing_arm) -> Component:
    """waveguide crossing

    .. plot::
      :include-source:

      import pp

      c = pp.c.crossing()
      pp.plotgds(c)

    """
    cx = pp.Component()
    arm = pp.call_if_func(arm)
    arm_h = arm.ref()
    arm_v = arm.ref(rotation=90)

    port_id = 0
    for c in [arm_h, arm_v]:
        cx.add(c)
        cx.absorb(c)
        for p in c.ports.values():
            cx.add_port(name="{}".format(port_id), port=p)
            port_id += 1
    cx = pp.port.rename_ports_by_orientation(cx)
    return cx
Example #17
0
def cross(x0: float, y0: float, width: float, lw: float,
          layer: Tuple[int, int]) -> Component:
    """cross

    Args:
        x0,y0 : center
        width: width of the bounding box
        lw: linewidth
    """
    cross = pp.Component()
    cross.add_polygon(
        [
            (x0 - width / 2, y0 - lw / 2),
            (x0 - width / 2, y0 + lw / 2),
            (x0 + width / 2, y0 + lw / 2),
            (x0 + width / 2, y0 - lw / 2),
        ],
        layer=layer,
    )
    cross.add_polygon(
        [
            (x0 - lw / 2, y0 - width / 2),
            (x0 - lw / 2, y0 + width / 2),
            (x0 + lw / 2, y0 + width / 2),
            (x0 + lw / 2, y0 - width / 2),
        ],
        layer=layer,
    )
    return cross
Example #18
0
def add_padding(
    component: Component,
    padding: Union[float, int] = 50,
    x: None = None,
    y: None = None,
    layers: Union[List[ListConfig], List[Layer]] = [pp.LAYER.PADDING],
    suffix: str = "p",
) -> Component:
    """adds padding layers to a NEW component that has the same:
    - ports
    - settings
    - test_protocols and data_analysis_protocols

    as the old component
    """
    x = x if x is not None else padding
    y = y if y is not None else padding

    c = pp.Component(name=f"{component.name}_{suffix}")
    c << component
    c.ports = component.ports

    points = [
        [c.xmin - x, c.ymin - y],
        [c.xmax + x, c.ymin - y],
        [c.xmax + x, c.ymax + y],
        [c.xmin - x, c.ymax + y],
    ]
    for layer in layers:
        c.add_polygon(points, layer=layer)
    return c
def test_connect_bundle_optical3():
    """ connect 4 waveguides into a 4x1 component """
    c = pp.Component()

    w = c << pp.c.waveguide_array(n_waveguides=4, spacing=200)
    d = c << pp.c.nxn(west=4, east=1)
    d.y = w.y
    d.xmin = w.xmax + 200

    ports1 = w.get_ports_list(prefix="E")
    ports2 = d.get_ports_list(prefix="W")

    routes = pp.routing.link_optical_ports(ports1, ports2, sort_ports=True)

    lengths = [
        489.416,
        290.749,
        290.749,
        489.416,
    ]

    for route, length in zip(routes, lengths):
        # print(route["settings"]["length"])
        c.add(route["references"])
        assert np.isclose(route["settings"]["length"], length)
    return c
Example #20
0
def _TRCH_DASH_DUO(length=20.0,
                   gap=2.0,
                   width=0.5,
                   separation=4.0,
                   n=3,
                   x_offset=0.0,
                   label=""):

    _trench = _TRCH_DASH_ISO(length=length,
                             width=width,
                             n=n,
                             separation=separation)
    dx = x_offset
    dy = gap + width
    c = pp.Component()
    t1 = c.add_ref(_trench)
    t2 = c.add_ref(_trench)
    t2.move((dy, dx))
    c.absorb(t1)
    c.absorb(t2)

    if label:
        marker_label = manhattan_text(text=label, size=0.4, layer=LAYER.WG)
        _marker_label = c.add_ref(marker_label)
        _marker_label.movey((n - 1) * (length + separation + 4.0) + length / 2)
        c.absorb(_marker_label)

    return c
def test_connect_bundle_waypointsA():
    import pp
    from pp.component import Port

    xs1 = np.arange(10) * 5 - 500.0

    N = xs1.size
    ys2 = np.array([0, 5, 10, 20, 25, 30, 40, 55, 60, 75]) + 500.0

    ports1 = [Port("A_{}".format(i), (xs1[i], 0), 0.5, 90) for i in range(N)]
    ports2 = [Port("B_{}".format(i), (0, ys2[i]), 0.5, 180) for i in range(N)]

    top_cell = pp.Component()
    p0 = ports1[0].position + (22, 0)
    way_points = [
        p0,
        p0 + (0, 100),
        p0 + (200, 100),
        p0 + (200, -200),
        p0 + (0, -200),
        p0 + (0, -350),
        p0 + (400, -350),
        (p0[0] + 400, ports2[-1].y),
        ports2[-1].position,
    ]

    elements = connect_bundle_waypoints(ports1, ports2, way_points)
    top_cell.add(elements)

    return top_cell
Example #22
0
def snapping_error(gap=1e-3):
    c = pp.Component()
    r1 = c << pp.c.rectangle(size=(1, 1), layer=layer)
    r2 = c << pp.c.rectangle(size=(1, 1), layer=layer)
    r1.xmax = 0
    r2.xmin = gap
    return c
def test_connect_bundle_waypointsC():
    import pp
    from pp.component import Port

    ys1 = np.array([0, 5, 10, 15, 20, 60, 70, 80, 120, 125])
    ys2 = np.array([0, 5, 10, 20, 25, 30, 40, 55, 60, 65]) - 500.0
    N = ys1.size

    ports1 = [Port("A_{}".format(i), (0, ys1[i]), 0.5, 0) for i in range(N)]
    ports2 = [
        Port("B_{}".format(i), (600, ys2[i]), 0.5, 180) for i in range(N)
    ]

    top_cell = pp.Component()
    way_points = [
        ports1[0].position,
        ports1[0].position + (200, 0),
        ports1[0].position + (200, -200),
        ports1[0].position + (400, -200),
        (ports1[0].x + 400, ports2[0].y),
        ports2[0].position,
    ]

    elements = connect_bundle_waypoints(ports1, ports2, way_points)
    top_cell.add(elements)

    return top_cell
Example #24
0
def _via_iterable(via_spacing, wire_width, wiring1_layer, wiring2_layer,
                  via_layer, via_width):
    VI = pp.Component()
    wire1 = VI.add_ref(
        pc.compass(size=(via_spacing, wire_width), layer=wiring1_layer))
    wire2 = VI.add_ref(
        pc.compass(size=(via_spacing, wire_width), layer=wiring2_layer))
    via1 = VI.add_ref(pc.compass(size=(via_width, via_width), layer=via_layer))
    via2 = VI.add_ref(pc.compass(size=(via_width, via_width), layer=via_layer))
    wire1.connect(port="E", destination=wire2.ports["W"], overlap=wire_width)
    via1.connect(port="W",
                 destination=wire1.ports["E"],
                 overlap=(wire_width + via_width) / 2)
    via2.connect(port="W",
                 destination=wire2.ports["E"],
                 overlap=(wire_width + via_width) / 2)
    VI.add_port(name="W", port=wire1.ports["W"])
    VI.add_port(name="E", port=wire2.ports["E"])
    VI.add_port(
        name="S",
        midpoint=[(1 * wire_width) + wire_width / 2, -wire_width / 2],
        width=wire_width,
        orientation=-90,
    )
    VI.add_port(
        name="N",
        midpoint=[(1 * wire_width) + wire_width / 2, wire_width / 2],
        width=wire_width,
        orientation=90,
    )

    return VI
Example #25
0
def gap_min(gap=0.1):
    c = pp.Component()
    r1 = c << pp.c.rectangle(size=(1, 1), layer=layer)
    r2 = c << pp.c.rectangle(size=(1, 1), layer=layer)
    r1.xmax = 0
    r2.xmin = gap
    return c
Example #26
0
def githash(text=[], size=0.4, hash_length=6, layer=LAYER.WG):
    """ returns the photonics_pdk git hash
    allows a list of text, that will print on separate lines ::

    text = [
        "sw_{}".format(Repo(CONFIG["repo"]).head.object.hexsha[:length]),
        "ap_{}".format(Repo(ap.CONFIG["repo"]).head.object.hexsha[:length]),
        "mm_{}".format(Repo(mm.CONFIG["repo"]).head.object.hexsha[:length]),
    ]
    c = githash(text=text)
    pp.write_gds(c)
    pp.show(c)

    """
    try:
        git_hash = "pp_{}".format(pp.CONFIG["repo"][:hash_length])
    except Exception:
        git_hash = "pp_{}".format(pp.__version__)

    c = pp.Component()
    t = manhattan_text(text=git_hash, size=size, layer=layer)
    tref = c.add_ref(t)
    c.absorb(tref)

    for i, texti in enumerate(text):
        t = manhattan_text(text=texti, size=size, layer=layer)
        tref = c.add_ref(t)
        tref.movey(-6 * size * (i + 1))
        c.absorb(tref)
    return c
Example #27
0
def align_cryo_top_left(x=60, y=60, s=0.2, layer=1):
    c = pp.Component()
    points = [[0, 0], [s, 0], [x - s, y - s], [x - s, y], [0, y]]
    c.add_polygon(points, layer=layer)
    cc = add_frame(component=c)
    cc.name = "align_cryo_top_left"
    return cc
Example #28
0
def cdsem_straight_density(wg_width=0.372,
                           trench_width=0.304,
                           x=500,
                           y=50.0,
                           margin=2.0):
    """ horizontal grating etch lines

    TE: 676nm pitch, 304nm gap, 372nm line
    TM: 1110nm pitch, 506nm gap, 604nm line

    Args:
        w: wg_width
        s: trench_width
    """
    c = pp.Component()
    period = wg_width + trench_width
    n_o_lines = int((y - 2 * margin) / period)
    length = x - 2 * margin

    slab = pp.c.rectangle_centered(x=x, y=y, layer=LAYER.WG)
    slab_ref = c.add_ref(slab)
    c.absorb(slab_ref)

    tooth = pp.c.rectangle_centered(x=length,
                                    y=trench_width,
                                    layer=LAYER.SLAB150)

    for i in range(n_o_lines):
        _tooth = c.add_ref(tooth)
        _tooth.movey((-n_o_lines / 2 + 0.5 + i) * period)
        c.absorb(_tooth)

    c.move(c.size_info.cc, (0, 0))
    return c
Example #29
0
def add_frame(component, width=10, spacing=10, layer=pp.LAYER.WG):
    """ returns component with a frame around it
    """
    c = pp.Component()
    cref = c.add_ref(component)
    cref.move(-c.size_info.center)
    b = component.size_info.height / 2 + spacing + width / 2
    w = width

    rh = rectangle(size=(2 * b + w, w), layer=layer, centered=True)
    rtop = c.add_ref(rh)
    rbot = c.add_ref(rh)
    rtop.movey(+b)
    rbot.movey(-b)

    rv = rectangle(size=(w, 2 * b), layer=layer, centered=True)
    rl = c.add_ref(rv)
    rr = c.add_ref(rv)
    rl.movex(-b)
    rr.movex(+b)
    c.absorb(cref)

    rc = rectangle(
        size=(2 * (b + spacing), 2 * (b + spacing)),
        layer=pp.LAYER.NO_TILE_SI,
        centered=True,
    )
    c.add_ref(rc)
    return c
Example #30
0
def test_connect_bundle_u_indirect(dy=-200, angle=180):

    xs1 = [-100, -90, -80, -55, -35] + [200, 210, 240]

    axis = "X" if angle in [0, 180] else "Y"

    pitch = 10.0
    N = len(xs1)
    xs2 = [50 + i * pitch for i in range(N)]

    a1 = angle
    a2 = a1 + 180

    if axis == "X":
        ports1 = [Port("top_{}".format(i), (0, xs1[i]), 0.5, a1) for i in range(N)]

        ports2 = [Port("bottom_{}".format(i), (dy, xs2[i]), 0.5, a2) for i in range(N)]

    else:
        ports1 = [Port("top_{}".format(i), (xs1[i], 0), 0.5, a1) for i in range(N)]

        ports2 = [Port("bottom_{}".format(i), (xs2[i], dy), 0.5, a2) for i in range(N)]

    top_cell = pp.Component()
    elements = connect_bundle(ports1, ports2)
    for e in elements:
        top_cell.add(e)

    return top_cell