Ejemplo n.º 1
0
def wg_deep_rib(width=0.5,
                layer=pp.layer("slab90"),
                layer_cladding=pp.layer("slab90clad"),
                **kwargs):
    width = pp.bias.width(width)
    return waveguide(width=width,
                     layer=layer,
                     layer_cladding=layer_cladding,
                     **kwargs)
Ejemplo n.º 2
0
def waveguide_trenches(
        length=10.0,
        width=0.5,
        layer=pp.layer("wgcore"),
        trench_width=3.0,
        trench_offset=0.2,
        trench_layer=pp.layer("slab90"),
):
    width = pp.bias.width(width)
    w = width / 2
    ww = w + trench_width
    wt = ww + trench_offset
    windows = [(-ww, ww, layer), (-wt, -w, trench_layer),
               (w, wt, trench_layer)]
    return _arbitrary_straight_waveguide(length=length, windows=windows)
Ejemplo n.º 3
0
def align_wafer(
    width=10,
    spacing=10,
    cross_length=80,
    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.fidutial()
      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

    c.add

    rh = rectangle_centered(w=2 * b + w, h=w, layer=layer)
    rtop = c.add_ref(rh)
    rbot = c.add_ref(rh)
    rtop.movey(+b)
    rbot.movey(-b)

    rv = rectangle_centered(w=w, h=2 * b, layer=layer)
    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_centered(w=wsq, h=wsq, layer=layer)
    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_centered(w=2 * (b + spacing),
                                          h=2 * (b + spacing),
                                          layer=pp.layer("no_tile_si"))
        c.add_ref(rc_tile_excl)

    return c
Ejemplo n.º 4
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_centered(w=2 * b + w, h=w, layer=layer)
    rtop = c.add_ref(rh)
    rbot = c.add_ref(rh)
    rtop.movey(+b)
    rbot.movey(-b)

    rv = rectangle_centered(w=w, h=2 * b, layer=layer)
    rl = c.add_ref(rv)
    rr = c.add_ref(rv)
    rl.movex(-b)
    rr.movex(+b)
    c.absorb(cref)

    rc = rectangle_centered(w=2 * (b + spacing),
                            h=2 * (b + spacing),
                            layer=pp.layer("no_tile_si"))
    c.add_ref(rc)
    return c
Ejemplo n.º 5
0
def taper_from_csv(csv_path,
                   wg_layer=1,
                   clad_offset=3,
                   clad_layer=pp.layer("wgclad")):
    taper_data = pp.load_csv(csv_path)
    # taper_data = pd.read_csv(csv_path)
    # print(taper_data)
    xs = taper_data["x"] * 1e6
    ys = taper_data["width"] * 1e6 / 2.0
    ys_trench = ys + clad_offset

    c = pp.Component()
    c.add_polygon(list(zip(xs, ys)) + list(zip(xs, -ys))[::-1], layer=wg_layer)
    c.add_polygon(list(zip(xs, ys_trench)) + list(zip(xs, -ys_trench))[::-1],
                  layer=clad_layer)

    c.add_port(
        name="W0",
        midpoint=(xs[0], 0),
        width=2 * ys[0],
        orientation=180,
        port_type="optical",
    )
    c.add_port(
        name="E0",
        midpoint=(xs[-1], 0),
        width=2 * ys[-1],
        orientation=0,
        port_type="optical",
    )
    return c
Ejemplo n.º 6
0
def waveguide_slot(length=10.0, width=0.5, gap=0.2, layer=pp.layer("wgcore")):
    width = pp.bias.width(width)
    gap = pp.bias.gap(gap)
    a = width / 2
    d = a + gap / 2

    windows = [(-a - d, a - d, layer), (-a + d, a + d, layer)]
    return _arbitrary_straight_waveguide(length=length, windows=windows)
Ejemplo n.º 7
0
def waveguide_slab(length=10.0,
                   width=0.5,
                   cladding=2.0,
                   slab_layer=pp.layer("slab90")):
    width = pp.bias.width(width)
    ymin = width / 2
    ymax = ymin + cladding
    windows = [(-ymin, ymin, pp.layer["wgcore"]), (-ymax, ymax, slab_layer)]
    return _arbitrary_straight_waveguide(length=length, windows=windows)
Ejemplo n.º 8
0
def waveguide(
        length=10,
        width=0.5,
        layer=pp.layer("wgcore"),
        layer_cladding=pp.layer("wgclad"),
        cladding_offset=3,
):
    """ straight waveguide

    Args:
        length: in X direction
        width: in Y direction

    .. plot::
      :include-source:

      import pp

      c = pp.c.waveguide(length=10, width=0.5)
      pp.plotgds(c)

    """
    c = pp.Component()
    w = width / 2
    wc = w + cladding_offset
    c.add_polygon([(0, -w), (length, -w), (length, w), (0, w)], layer=layer)
    if layer_cladding is not None:
        c.add_polygon([(0, -wc), (length, -wc), (length, wc), (0, wc)],
                      layer=layer_cladding)

    c.add_port(name="W0",
               midpoint=[0, 0],
               width=width,
               orientation=180,
               layer=layer)
    c.add_port(name="E0",
               midpoint=[length, 0],
               width=width,
               orientation=0,
               layer=layer)

    c.width = width
    c.length = length
    return c
Ejemplo n.º 9
0
def coupler_straight(
        length=10,
        width=0.5,
        gap=0.27,
        layer=pp.LAYER.WG,
        layer_cladding=pp.layer("wgclad"),
        cladding_offset=3,
):
    """ straight coupled waveguides. Two multimode ports

    .. plot::
      :include-source:

      import pp

      c = pp.c.coupler_straight()
      pp.plotgds(c)

    """

    c = Component()

    # Top path
    c.add_polygon([(0, 0), (length, 0), (length, width), (0, width)],
                  layer=layer)
    y = width + gap

    # Bottom path
    c.add_polygon([(0, y), (length, y), (length, width + y), (0, width + y)],
                  layer=layer)

    # One multimode port on each side
    port_w = width * 2 + gap

    c.add_port(name="W0",
               midpoint=[0, port_w / 2],
               width=port_w,
               orientation=180)
    c.add_port(name="E0",
               midpoint=[length, port_w / 2],
               width=port_w,
               orientation=0)

    c.width = width
    c.length = length

    # cladding
    ymax = 2 * width + gap + cladding_offset
    c.add_polygon(
        [(0, -cladding_offset), (length, -cladding_offset), (length, ymax),
         (0, ymax)],
        layer=layer_cladding,
    )

    return c
Ejemplo n.º 10
0
def test_label_move():
    """ test that when we move a device its label also moves """
    c = pp.Component("ellipse_with_label")
    c << pp.c.ellipse()
    c.label(text="demo", position=(10, 0), layer=pp.layer("TEXT"))
    c.movex(10)
    print(c.references)
    print(c.labels)
    # assert c.references[0].origin[0] == 10
    # assert c.labels[0].position[0] == 20
    return c
Ejemplo n.º 11
0
def add_padding(component, padding=50, layers=[pp.layer("padding")]):
    """ returns component width a padding layer on each side"""
    c = pp.Component(name=component.name + "_p")
    cr = c.add_ref(component)
    points = [
        [cr.xmin - padding, cr.ymin - padding],
        [cr.xmax + padding, cr.ymin - padding],
        [cr.xmax + padding, cr.ymax + padding],
        [cr.xmin - padding, cr.ymax + padding],
    ]
    for layer in layers:
        c.add_polygon(points, layer=layer)
    c.ports = cr.ports
    c.settings = component.settings
    return c
Ejemplo n.º 12
0
def add_padding_to_grid(component,
                        grid_size=127,
                        padding=10,
                        bottom_padding=5,
                        layers=[pp.layer("padding")]):
    """ returns component width a padding layer on each side
    matches a minimum size
    grating couplers are at ymin
    """
    c = component
    c = pp.Component(
        name=c.name + "_p",
        settings=c.get_settings(),
        test_protocol=c.test_protocol,
        data_analysis_protocol=c.data_analysis_protocol,
    )
    cr = c.add_ref(component)

    if c.size_info.height < grid_size:
        y_padding = grid_size - c.size_info.height
    else:
        n_grids = np.ceil(c.size_info.height / grid_size)
        y_padding = n_grids * grid_size - c.size_info.height

    if c.size_info.width < grid_size:
        x_padding = grid_size - c.size_info.width
    else:
        n_grids = np.ceil(c.size_info.width / grid_size)
        x_padding = n_grids * grid_size - c.size_info.width

    x_padding -= padding
    y_padding -= padding

    points = [
        [cr.xmin - x_padding / 2, cr.ymin - bottom_padding],
        [cr.xmax + x_padding / 2, cr.ymin - bottom_padding],
        [cr.xmax + x_padding / 2, cr.ymax + y_padding - bottom_padding],
        [cr.xmin - x_padding / 2, cr.ymax + y_padding - bottom_padding],
    ]
    for layer in layers:
        c.add_polygon(points, layer=layer)
    return c
Ejemplo n.º 13
0
def sims_pad(width=500, height=500, pad=100, layer=1):
    c = pp.Component()
    w = width
    h = height
    points = [
        [-w / 2.0, -h / 2.0],
        [-w / 2.0, h / 2],
        [w / 2, h / 2],
        [w / 2, -h / 2.0],
    ]
    c.add_polygon(points, layer=layer)
    w = width + 2 * pad
    h = height + 2 * pad
    points = [
        [-w / 2.0, -h / 2.0],
        [-w / 2.0, h / 2],
        [w / 2, h / 2],
        [w / 2, -h / 2.0],
    ]
    c.add_polygon(points, layer=pp.layer("padding"))
    return c
Ejemplo n.º 14
0
def text(t="U"):
    return pp.c.text(text=t, layer=pp.layer("wgcore"), size=5)
Ejemplo n.º 15
0
def cdsem_uturn(
        width=0.5,
        radius=10.0,
        symbol_bot="S",
        symbol_top="U",
        wg_length=LINE_LENGTH,
        waveguide_factory=pp.c.waveguide,
        bend90_factory=bend_circular,
        layer=pp.layer("wgcore"),
        layer_cladding=pp.layer("wgclad"),
        cladding_offset=3,
):
    """

    Args:
        width: of the line
        cladding_offset: 
        radius: bend radius
        wg_length

    """
    c = pp.Component()
    r = radius
    bend90 = bend90_factory(width=width,
                            radius=r,
                            layer=layer,
                            cladding_layer=layer_cladding)
    if wg_length is None:
        wg_length = 2 * r
    wg = waveguide_factory(
        width=width,
        length=wg_length,
        layer=layer,
        layer_cladding=layer_cladding,
        cladding_offset=cladding_offset,
    )

    # bend90.ports()
    rename_ports_by_orientation(bend90)

    # Add the U-turn on waveguide layer
    b1 = c.add_ref(bend90)
    b2 = c.add_ref(bend90)

    b2.connect("N0", b1.ports["W0"])

    wg1 = c.add_ref(wg)
    wg1.connect("W0", b1.ports["N0"])

    wg2 = c.add_ref(wg)
    wg2.connect("W0", b2.ports["W0"])

    # Add symbols

    sym1 = c.add_ref(CENTER_SHAPES_MAP[symbol_bot]())
    sym1.rotate(-90)
    sym1.movey(r)
    sym2 = c.add_ref(CENTER_SHAPES_MAP[symbol_top]())
    sym2.rotate(-90)
    sym2.movey(2 * r)
    c.absorb(sym1)
    c.absorb(sym2)

    c.rotate(angle=90)
    # print(c._bb_valid)
    # print(c.size_info)
    c.move(c.size_info.cc, (0, 0))
    return c
Ejemplo n.º 16
0
def add_gratings_and_loop_back(
    component,
    grating_coupler=grating_coupler_te,
    excluded_ports=[],
    grating_separation=127.0,
    bend_radius_align_ports=10.0,
    gc_port_name=None,
    gc_rotation=-90,
    waveguide_separation=5.0,
    bend_factory=bend_circular,
    waveguide_factory=waveguide,
    layer_label=pp.layer("TEXT"),
    # input_port_indexes=[0],
    name=None,
    component_name=None,
):
    """ returns a component with grating_couplers and loopback
    """

    direction = "S"
    component_name = component.name
    name = name or component_name or f"{component_name}_c"
    c = pp.Component(name=name)
    c.add_ref(component)
    gc = pp.call_if_func(grating_coupler)

    # Find grating port name if not specified
    if gc_port_name is None:
        gc_port_name = list(gc.ports.values())[0].name

    # List the optical ports to connect
    optical_ports = component.get_optical_ports()
    optical_ports = [p for p in optical_ports if p.name not in excluded_ports]
    optical_ports = direction_ports_from_list_ports(optical_ports)[direction]

    # Check if the ports are equally spaced
    grating_separation_extracted = check_ports_have_equal_spacing(
        optical_ports)
    if grating_separation_extracted != grating_separation:
        raise ValueError("Grating separation must be {}. Got {}".format(
            grating_separation, grating_separation_extracted))

    # Add grating couplers
    couplers = []
    for port in optical_ports:
        coupler_ref = c.add_ref(gc)
        coupler_ref.connect(list(coupler_ref.ports.values())[0].name, port)
        couplers += [coupler_ref]

    # add labels
    for i, optical_port in enumerate(optical_ports):
        label = get_input_label(
            optical_port,
            couplers[i],
            i,
            component_name=component_name,
            layer_label=layer_label,
        )
        c.add(label)

    # Add loopback
    y0 = couplers[0].ports[gc_port_name].y
    xs = [p.x for p in optical_ports]
    x0 = min(xs) - grating_separation
    x1 = max(xs) + grating_separation

    gca1, gca2 = [
        gc.ref(position=(x, y0), rotation=gc_rotation, port_id=gc_port_name)
        for x in [x0, x1]
    ]

    gsi = gc.size_info
    p0 = gca1.ports[gc_port_name].position
    p1 = gca2.ports[gc_port_name].position
    a = bend_radius_align_ports + 0.5
    b = max(2 * a, grating_separation / 2)
    y_bot_align_route = -gsi.width - waveguide_separation

    route = [
        p0,
        p0 + (0, a),
        p0 + (b, a),
        p0 + (b, y_bot_align_route),
        p1 + (-b, y_bot_align_route),
        p1 + (-b, a),
        p1 + (0, a),
        p1,
    ]
    bend90 = bend_factory(radius=bend_radius_align_ports)
    loop_back = round_corners(route, bend90, waveguide_factory)
    elements = [gca1, gca2, loop_back]
    c.add(elements)
    return c
Ejemplo n.º 17
0
def ppe(layer=pp.layer("wgcore"),
        layer_cladding=pp.layer("wgclad"),
        cladding_offset=3):
    """
    pattern placement error
    """
    D = pp.Component()

    # Define global variables
    xmax = 500
    ymax = 500
    xmin = 0
    ymin = 0
    xm = (xmax - xmin) / 2.0
    ym = (ymax - ymin) / 2.0
    o = cladding_offset

    # Cover the entire macro
    D.add_polygon(
        [
            (0, -o),
            (xmax + o, -o),
            (xmax + o, ymax + o),
            (0, ymax + o),
        ],
        layer=layer_cladding,
    )

    # Place the pattern rec
    Cross = cross(x0=xm, y0=ym, width=100, lw=10, layer=layer)
    Cross.rotate(45, center=[xm, ym])
    D.add_ref(Cross)

    # calculate offset due to the cross
    xoff = math.sqrt(100 * 50)
    yoff = math.sqrt(100 * 50)

    # Top left 1
    x0 = 10
    y0 = ym
    pitch = 20
    LS1 = linespace(
        x0=x0,
        y0=y0,
        width=240 - xoff,
        height=10,
        pitch=pitch,
        ymax=ym + yoff,
        layer=layer,
    )
    y0 = y0linespace(y0=y0, height=10, pitch=pitch, ymax=ym + yoff)
    D.add_ref(LS1)

    # Top left 2
    x0 = 10
    y0 = y0
    LS1 = linespace(x0=x0,
                    y0=y0,
                    width=240,
                    height=10,
                    pitch=20,
                    ymax=500,
                    layer=layer)
    D.add_ref(LS1)

    # Top right 1
    x0 = xm + xoff
    y0 = ym
    pitch = 30
    LS2 = linespace(
        x0=x0,
        y0=y0,
        width=240 - xoff + 10,
        height=10,
        pitch=pitch,
        ymax=ym + yoff,
        layer=layer,
    )
    y0 = y0linespace(y0=y0, height=10, pitch=pitch, ymax=ym + yoff)
    D.add_ref(LS2)

    # Top right 2
    x0 = xm + 10
    LS2 = linespace(x0=x0,
                    y0=y0,
                    width=240,
                    height=10,
                    pitch=30,
                    ymax=500,
                    layer=layer)
    D.add_ref(LS2)

    # Lower left 1
    x0 = 10
    y0 = 0
    pitch = 30
    LS3 = linespace(x0=x0,
                    y0=y0,
                    width=240,
                    height=10,
                    pitch=30,
                    ymax=xm - yoff,
                    layer=layer)
    D.add_ref(LS3)

    # Lower left 2
    x0 = 10
    y0 += pitch
    LS3 = linespace(x0=x0,
                    y0=y0,
                    width=240 - xoff,
                    height=10,
                    pitch=30,
                    ymax=240,
                    layer=layer)
    D.add_ref(LS3)

    # Lower right 1
    x0 = xm + 10
    y0 = 0
    pitch = 20
    LS4 = linespace(x0=x0,
                    y0=y0,
                    width=240,
                    height=10,
                    pitch=20,
                    ymax=xm - yoff,
                    layer=layer)
    D.add_ref(LS4)

    # Lower right 2
    x0 = xm + xoff
    y0 += pitch
    LS4 = linespace(x0=x0,
                    y0=y0,
                    width=240 - xoff + 10,
                    height=10,
                    pitch=20,
                    ymax=240,
                    layer=layer)
    D.add_ref(LS4)

    # Add NOOPC cover on the pattern rec
    xt = xoff - 10
    yt = yoff - 10
    D.add_polygon(
        [
            (xm - xt, ym - yt),
            (xm - xt, ym + yt),
            (xm + xt, ym + yt),
            (xm + xt, ym - yt),
        ],
        layer=layer_cladding,
    )
    return D
Ejemplo n.º 18
0
def bend_circular(
        radius=10.0,
        width=0.5,
        theta=-90,
        start_angle=0,
        angle_resolution=2.5,
        layer=LAYER.WG,
        cladding_layer=pp.layer("wgclad"),
        cladding_offset=3,
):
    """ Creates an arc of arclength ``theta`` starting at angle ``start_angle``

    Args:
        radius
        width: of the waveguide
        theta: arc length
        start_angle:
        angle_resolution
        layer

    .. plot::
      :include-source:

      import pp

      c = pp.c.bend_circular(
        radius=10,
        width=0.5,
        theta=-90,
        start_angle=0,
      )
      pp.plotgds(c)
    """
    component = pp.Component()

    # Core
    inner_radius = radius - width / 2
    outer_radius = radius + width / 2
    angle1 = (start_angle) * pi / 180
    angle2 = (start_angle + theta) * pi / 180
    t = np.linspace(angle1, angle2, int(abs(theta) / angle_resolution))
    inner_points_x = (inner_radius * cos(t)).tolist()
    inner_points_y = (inner_radius * sin(t)).tolist()
    outer_points_x = (outer_radius * cos(t)).tolist()
    outer_points_y = (outer_radius * sin(t)).tolist()
    xpts = inner_points_x + outer_points_x[::-1]
    ypts = inner_points_y + outer_points_y[::-1]

    component.add_polygon(points=(xpts, ypts), layer=layer)

    # Cladding
    w = width + 2 * cladding_offset
    inner_radius = radius - w / 2
    outer_radius = radius + w / 2
    angle1 = (start_angle) * pi / 180
    angle2 = (start_angle + theta) * pi / 180
    t = np.linspace(angle1, angle2, int(abs(theta) / angle_resolution))
    inner_points_x = (inner_radius * cos(t)).tolist()
    inner_points_y = (inner_radius * sin(t)).tolist()
    outer_points_x = (outer_radius * cos(t)).tolist()
    outer_points_y = (outer_radius * sin(t)).tolist()
    xpts = inner_points_x + outer_points_x[::-1]
    ypts = inner_points_y + outer_points_y[::-1]

    if cladding_layer is not None:
        component.add_polygon(points=(xpts, ypts), layer=cladding_layer)

    component.add_port(
        name="W0",
        midpoint=(radius * cos(angle1), radius * sin(angle1)),
        width=width,
        orientation=start_angle - 90 + 180 * (theta < 0),
        layer=layer,
    )
    component.add_port(
        name="N0",
        midpoint=(radius * cos(angle2), radius * sin(angle2)),
        width=width,
        orientation=start_angle + theta + 90 - 180 * (theta < 0),
        layer=layer,
    )
    component.info["length"] = (abs(theta) * pi / 180) * radius
    component.radius = radius
    component.width = width
    component.move((0, radius))

    pp.ports.port_naming.rename_ports_by_orientation(component)
    return component
Ejemplo n.º 19
0
def bend_circular_shallow_rib(layer=pp.layer("slab150"),
                              cladding_layer=pp.layer("slab150clad"),
                              **kwargs):
    return bend_circular(layer=layer, cladding_layer=cladding_layer, **kwargs)
Ejemplo n.º 20
0
def bend_circular_deep_rib(
        layer=pp.layer("slab90"), cladding_layer=pp.layer("slab90clad"),
        **kwargs):
    c = bend_circular(layer=layer, cladding_layer=cladding_layer, **kwargs)
    pp.ports.port_naming.rename_ports_by_orientation(c)
    return c