Esempio n. 1
0
def L(
    width: Union[int, float] = 1,
    size: Tuple[int, int] = (10, 20),
    layer: Tuple[int, int] = LAYER.M3,
    port_type: str = "electrical",
) -> Component:
    """Generates an 'L' geometry with ports on both ends. Based on phidl.

    Args:
        width: of the line
        size: length and height of the base
        layer:

    """
    D = Component()
    w = width / 2
    s1, s2 = size
    points = [(-w, -w), (s1, -w), (s1, w), (w, w), (w, s2), (-w, s2), (-w, -w)]
    D.add_polygon(points, layer=layer)
    D.add_port(name="e1",
               midpoint=(0, s2),
               width=width,
               orientation=90,
               port_type=port_type)
    D.add_port(name="e2",
               midpoint=(s1, 0),
               width=width,
               orientation=0,
               port_type=port_type)
    return D
Esempio n. 2
0
def extend_port(port: Port, length: float, layer: Optional[Layer] = None) -> Component:
    """Returns a straight extension component out of a port.

    Args:
        port: port to extend
        length: extension length
        layer: for the straight section
    """
    c = Component()
    layer = layer or port.layer

    # Generate a port extension
    p_start = port.midpoint
    angle = port.angle
    p_end = move_polar_rad_copy(p_start, angle * DEG2RAD, length)
    w = port.width

    _line = line(p_start, p_end, w)

    c.add_polygon(_line, layer=layer)
    c.add_port(name="original", port=port)

    port_settings = port.settings.copy()
    port_settings.update(midpoint=p_end)
    c.add_port(**port_settings)

    return c
Esempio n. 3
0
def add_keepout(
    component: Component,
    target_layers: Layers,
    keepout_layers: Layers,
    margin: float = 2.0,
) -> Component:
    """Adds keepout after Looking up all polygons in a cell.
    You can also use add_padding

    Args:
        component
        target_layers: list of layers to read
        keepout_layers: list of layers to add keepout
        margin: offset from tareget to keepout_layers
    """
    c = Component(f"{component.name}_ko")
    c << component
    for layer in target_layers:
        polygons = component.get_polygons(by_spec=layer)
        if polygons:
            for ko_layer in keepout_layers:
                ko_layer = _parse_layer(ko_layer)
                polygon_keepout = [
                    polygon_grow(polygon, margin) for polygon in polygons
                ]
                c.add_polygon(polygon_keepout, ko_layer)
    return c
Esempio n. 4
0
def ramp(
        length: float = 10.0,
        width1: float = 5.0,
        width2: Optional[float] = 8.0,
        layer: Layer = (1, 0),
) -> Component:
    """Return a ramp component. Based on phidl.

    Args:
        length: Length of the ramp section.
        width1: Width of the start of the ramp section.
        width2: Width of the end of the ramp section (defaults to width1).
        layer: Specific layer to put polygon geometry on.

    """
    if width2 is None:
        width2 = width1
    xpts = [0, length, length, 0]
    ypts = [width1, width2, 0, 0]
    c = Component()
    c.add_polygon([xpts, ypts], layer=layer)
    c.add_port(name="o1",
               midpoint=[0, width1 / 2],
               width=width1,
               orientation=180)
    c.add_port(name="o2",
               midpoint=[length, width2 / 2],
               width=width2,
               orientation=0)
    return c
Esempio n. 5
0
def C(
    width: float = 1.0,
    size: Tuple[float, float] = (10.0, 20.0),
    layer: Tuple[int, int] = LAYER.M3,
) -> Component:
    """Generates a 'C' geometry with ports on both ends. Adapted from phidl

    Args:
        width: of the line
        size: length and height of the base
        layer:

    """
    D = Component()
    w = width / 2
    s1, s2 = size
    points = [
        (-w, -w),
        (s1, -w),
        (s1, w),
        (w, w),
        (w, s2 - w),
        (s1, s2 - w),
        (s1, s2 + w),
        (-w, s2 + w),
        (-w, -w),
    ]
    D.add_polygon(points, layer=layer)
    D.add_port(name="o1", midpoint=(s1, s2), width=width, orientation=0)
    D.add_port(name="o2", midpoint=(s1, 0), width=width, orientation=0)
    return D
Esempio n. 6
0
def _sample_route_side() -> Component:
    c = Component()
    xs = [0.0, 10.0, 25.0, 50.0]
    ys = [0.0, 10.0, 25.0, 50.0]
    a = 5
    xl = min(xs) - a
    xr = max(xs) + a
    yb = min(ys) - a
    yt = max(ys) + a

    c.add_polygon([(xl, yb), (xl, yt), (xr, yt), (xr, yb)], LAYER.WG)

    for i, y in enumerate(ys):
        p0 = (xl, y)
        p1 = (xr, y)
        c.add_port(name="W{}".format(i),
                   midpoint=p0,
                   orientation=180,
                   width=0.5)
        c.add_port(name="E{}".format(i), midpoint=p1, orientation=0, width=0.5)

    for i, x in enumerate(xs):
        p0 = (x, yb)
        p1 = (x, yt)
        c.add_port(name="S{}".format(i),
                   midpoint=p0,
                   orientation=270,
                   width=0.5)
        c.add_port(name="N{}".format(i),
                   midpoint=p1,
                   orientation=90,
                   width=0.5)

    return c
Esempio n. 7
0
def from_np(
        ndarray: np.ndarray,
        nm_per_pixel: int = 20,
        layer: Tuple[int, int] = (1, 0),
        threshold: float = 0.99,
) -> Component:
    """Returns Component from a np.ndarray.
    Extracts contours skimage.measure.find_contours using `threshold`.

    Args:
        ndarray: 2D ndarray representing the device layout
        nm_per_pixel: scale_factor
        layer: layer tuple to output gds
        threshold: value along which to find contours in the array

    """
    c = Component()
    d = Component()
    ndarray = np.pad(ndarray, 2)
    contours = measure.find_contours(ndarray, threshold)
    assert len(contours) > 0, (
        f"no contours found for threshold = {threshold}, maybe you can reduce the"
        " threshold")

    for contour in contours:
        area = compute_area_signed(contour)
        points = contour * 1e-3 * nm_per_pixel
        if area < 0:
            c.add_polygon(points, layer=layer)
        else:
            d.add_polygon(points, layer=layer)

    c = boolean(c, d, operation="not", layer=layer)
    return c
Esempio n. 8
0
def crossing_arm(
    width: float = 0.5,
    r1: float = 3.0,
    r2: float = 1.1,
    w: float = 1.2,
    L: float = 3.4,
) -> Component:
    """arm of a crossing"""
    c = Component()
    _ellipse = ellipse(radii=(r1, r2), layer=LAYER.SLAB150).ref()
    c.add(_ellipse)
    c.absorb(_ellipse)

    a = np.round(L + w / 2, 3)
    h = width / 2

    taper_pts = [
        (-a, h),
        (-w / 2, w / 2),
        (w / 2, w / 2),
        (a, h),
        (a, -h),
        (w / 2, -w / 2),
        (-w / 2, -w / 2),
        (-a, -h),
    ]

    c.add_polygon(taper_pts, layer=LAYER.WG)
    c.add_port(
        name="o1", midpoint=(-a, 0), orientation=180, width=width, layer=LAYER.WG
    )

    c.add_port(name="o2", midpoint=(a, 0), orientation=0, width=width, layer=LAYER.WG)

    return c
Esempio n. 9
0
def add_padding_to_size(
    component: Component,
    layers: Tuple[Layer, ...] = (LAYER.PADDING, ),
    xsize: Optional[float] = None,
    ysize: Optional[float] = None,
    left: float = 0,
    bottom: float = 0,
) -> Component:
    """Returns component with padding layers on each side.

    New size is multiple of grid size
    """

    c = component
    top = abs(ysize - component.ysize) if ysize else 0
    right = abs(xsize - component.xsize) if xsize else 0
    points = [
        [c.xmin - left, c.ymin - bottom],
        [c.xmax + right, c.ymin - bottom],
        [c.xmax + right, c.ymax + top],
        [c.xmin - left, c.ymax + top],
    ]

    for layer in layers:
        component.add_polygon(points, layer=layer)

    return component
Esempio n. 10
0
def triangle(
        x: float = 10,
        xtop: float = 0,
        y: float = 20,
        ybot: float = 0,
        layer: Layer = (1, 0),
) -> Component:
    r"""
    Args:
        x: base xsize
        xtop: top xsize
        y: ysize
        ybot: bottom ysize
        layer:

    .. code::

        xtop
           _
          | \
          |  \
          |   \
         y|    \
          |     \
          |      \
          |______|ybot
              x
    """
    c = Component()
    points = [[0, 0], [x, 0], [x, ybot], [xtop, y], [0, y]]
    c.add_polygon(points, layer=layer)
    return c
Esempio n. 11
0
def add_padding(
        component: Component,
        layers: Tuple[Layer, ...] = (LAYER.PADDING, ),
        **kwargs,
) -> Component:
    """Adds padding layers to a component inside a container.

    Returns the same ports as the component.

    Args:
        component
        layers: list of layers
        new_component: returns a new component if True

    keyword Args:
        default: default padding
        top: north padding
        bottom: south padding
        right: east padding
        left: west padding
    """

    points = get_padding_points(component, **kwargs)
    for layer in layers:
        component.add_polygon(points, layer=layer)
    return component
Esempio n. 12
0
def add_padding_container(
        component: Component,
        layers: Tuple[Layer, ...] = (LAYER.PADDING, ),
        **kwargs,
) -> Component:
    """Returns new component with padding added.

    Args:
        component
        layers: list of layers
        default: default padding
        top: north padding
        bottom: south padding
        right: east padding
        left: west padding
    """

    c = Component()
    c.component = component
    cref = c << component

    points = get_padding_points(component, **kwargs)
    for layer in layers:
        c.add_polygon(points, layer=layer)
    c.ports = cref.ports
    c.copy_child_info(component)
    return c
Esempio n. 13
0
def pixel_array(
    pixels: str = character_a,
    pixel_size: float = 10.0,
    layer: Tuple[int, int] = LAYER.M1,
) -> Component:
    """Returns a pixel component from a string representing the pixels.

    Args:
        pixels: string representing the pixels
        pixel_size: widht/height for each pixel
        layer: layer for each pixel
    """
    component = Component()
    lines = [line for line in pixels.split("\n") if len(line) > 0]
    lines.reverse()
    j = 0
    i = 0
    i_max = 0
    a = pixel_size
    for line in lines:
        i = 0
        for c in line:
            if c in ["X", "1"]:
                p0 = np.array([i * a, j * a])
                pixel = [p0 + p for p in [(0, 0), (a, 0), (a, a), (0, a)]]
                component.add_polygon(pixel, layer=layer)
            i += 1
        i_max = max(i_max, i)
        j += 1

    return component
Esempio n. 14
0
def _add_pin_square(
    component: Component,
    port: Port,
    pin_length: float = 0.1,
    layer: Tuple[int, int] = LAYER.PORT,
    label_layer: Optional[Tuple[int, int]] = LAYER.PORT,
    port_margin: float = 0.0,
) -> None:
    """Add half out pin to a component.

    Args:
        component:
        port: Port
        pin_length: length of the pin marker for the port
        layer: for the pin marker
        label_layer: for the label
        port_margin: margin to port edge


    .. code::

           _______________
          |               |
          |               |
          |               |
         |||              |
         |||              |
          |               |
          |      __       |
          |_______________|
                 __

    """
    p = port
    a = p.orientation
    ca = np.cos(a * np.pi / 180)
    sa = np.sin(a * np.pi / 180)
    rot_mat = np.array([[ca, -sa], [sa, ca]])

    d = p.width / 2 + port_margin

    dbot = np.array([pin_length / 2, -d])
    dtop = np.array([pin_length / 2, d])
    dbotin = np.array([-pin_length / 2, -d])
    dtopin = np.array([-pin_length / 2, +d])

    p0 = p.position + _rotate(dbot, rot_mat)
    p1 = p.position + _rotate(dtop, rot_mat)
    ptopin = p.position + _rotate(dtopin, rot_mat)
    pbotin = p.position + _rotate(dbotin, rot_mat)
    polygon = [p0, p1, ptopin, pbotin]
    component.add_polygon(polygon, layer=layer)

    if label_layer:
        component.add_label(
            text=str(p.name),
            position=p.midpoint,
            layer=label_layer,
        )
Esempio n. 15
0
def wg(length: int = 3, width: float = 0.5) -> Component:
    from gdsfactory.component import Component

    c = Component("straight")
    w = width / 2
    layer = (1, 0)
    c.add_polygon([(0, -w), (length, -w), (length, w), (0, w)], layer=layer)
    c.add_port(name="o1", midpoint=[0, 0], width=width, orientation=180, layer=layer)
    c.add_port(name="o2", midpoint=[length, 0], width=width, orientation=0, layer=layer)
    return c
Esempio n. 16
0
def add_pin_square_inside(
    component: Component,
    port: Port,
    pin_length: float = 0.1,
    layer: Tuple[int, int] = LAYER.PORT,
    layer_label: Optional[Tuple[int, int]] = LAYER.TEXT,
) -> None:
    """Add square pin towards the inside of the port

    Args:
        component:
        port: Port
        pin_length: length of the pin marker for the port
        layer: for the pin marker
        layer_label: for the label

    .. code::

           _______________
          |               |
          |               |
          |               |
          ||              |
          ||              |
          |               |
          |      __       |
          |_______________|


    """
    p = port
    a = p.orientation
    ca = np.cos(a * np.pi / 180)
    sa = np.sin(a * np.pi / 180)
    rot_mat = np.array([[ca, -sa], [sa, ca]])

    d = p.width / 2

    dbot = np.array([0, -d])
    dtop = np.array([0, d])
    dbotin = np.array([-pin_length, -d])
    dtopin = np.array([-pin_length, +d])

    p0 = p.position + _rotate(dbot, rot_mat)
    p1 = p.position + _rotate(dtop, rot_mat)
    ptopin = p.position + _rotate(dtopin, rot_mat)
    pbotin = p.position + _rotate(dbotin, rot_mat)
    polygon = [p0, p1, ptopin, pbotin]
    component.add_polygon(polygon, layer=layer)
    if layer_label:
        component.add_label(
            text=str(p.name),
            position=p.midpoint,
            layer=layer_label,
        )
Esempio n. 17
0
def wg(length: int = 3, layer: Tuple[int, int] = (1, 0)) -> Component:
    """Dummy component for testing."""
    from gdsfactory.component import Component

    c = Component("straight")
    width = 0.5
    w = width / 2
    c.add_polygon([(0, -w), (length, -w), (length, w), (0, w)], layer=layer)
    c.add_port(name="o1", midpoint=[0, 0], width=width, orientation=180, layer=layer)
    c.add_port(name="o2", midpoint=[length, 0], width=width, orientation=0, layer=layer)
    return c
Esempio n. 18
0
def bend_s(size: Float2 = (10.0, 2.0),
           nb_points: int = 99,
           with_cladding_box: bool = True,
           cross_section: CrossSectionFactory = strip,
           **kwargs) -> Component:
    """S bend with bezier curve

    stores min_bend_radius property in self.info['min_bend_radius']
    min_bend_radius depends on height and length

    Args:
        size: in x and y direction
        nb_points: number of points
        with_cladding_box: square bounding box to avoid DRC errors
        cross_section: function
        kwargs: cross_section settings

    """
    dx, dy = size
    x = cross_section(**kwargs)
    width = x.info["width"]
    layer = x.info["layer"]

    c = Component()

    bend = bezier(
        width=width,
        control_points=[(0, 0), (dx / 2, 0), (dx / 2, dy), (dx, dy)],
        npoints=nb_points,
        layer=layer,
    )

    bend_ref = c << bend
    c.add_ports(bend_ref.ports)
    c.copy_child_info(bend)
    c.info.start_angle = bend.info.start_angle
    c.info.end_angle = bend.info.end_angle
    c.info.length = bend.info.length
    c.info.min_bend_radius = bend.info.min_bend_radius

    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            top=cladding_offset,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)

    auto_rename_ports(c)
    return c
Esempio n. 19
0
def bend_circular(angle: int = 90,
                  npoints: int = 720,
                  with_cladding_box: bool = True,
                  cross_section: CrossSectionOrFactory = strip,
                  **kwargs) -> Component:
    """Returns a radial arc.

    Args:
        angle: angle of arc (degrees)
        npoints: number of points
        with_cladding_box: square in layers_cladding to remove DRC
        cross_section:
        kwargs: cross_section settings


    .. code::

                  o2
                  |
                 /
                /
               /
       o1_____/

    """
    x = cross_section(**kwargs) if callable(cross_section) else cross_section
    radius = x.info["radius"]

    p = arc(radius=radius, angle=angle, npoints=npoints)
    c = Component()
    path = extrude(p, x)
    ref = c << path
    c.add_ports(ref.ports)

    c.info.length = snap_to_grid(p.length())
    c.info.dy = float(abs(p.points[0][0] - p.points[-1][0]))
    c.info.radius = float(radius)

    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        top = cladding_offset if angle == 180 else 0
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            right=cladding_offset,
            top=top,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)

    c.absorb(ref)
    return c
Esempio n. 20
0
def demo(length: int = 3, wg_width: float = 0.5) -> Component:
    """Demo Dummy cell"""
    c = Component()
    w = length
    h = wg_width
    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)
    return c
Esempio n. 21
0
def via(
    size: Tuple[float, float] = (0.7, 0.7),
    spacing: Tuple[float, float] = (2.0, 2.0),
    enclosure: float = 1.0,
    layer: Tuple[int, int] = LAYER.VIAC,
    layers_cladding: Optional[Tuple[Tuple[int, int], ...]] = None,
    cladding_offset: float = 0,
) -> Component:
    """Rectangular via. Defaults to a square via.

    Args:
        size: in x, y direction
        spacing: pitch_x, pitch_y
        enclosure: inclusion of via
        layer: via layer
        layers_cladding:
        cladding_offset

    .. code::

        enclosure
        _________________________________________
        |<--->                                  |
        |                      size[0]          |
        |                      <----->          |
        |      ______          ______           |
        |     |      |        |      |          |
        |     |      |        |      |  size[1] |
        |     |______|        |______|          |
        |      <------------->                  |
        |         spacing[0]                    |
        |_______________________________________|

    """
    c = Component()
    c.info["spacing"] = spacing
    c.info["enclosure"] = enclosure
    c.info["size"] = size

    width, height = size
    a = width / 2
    b = height / 2
    c.add_polygon([(-a, -b), (a, -b), (a, b), (-a, b)], layer=layer)

    layers_cladding = layers_cladding or []
    a = (width + cladding_offset) / 2
    b = (height + cladding_offset) / 2
    for layer in layers_cladding:
        c.add_polygon([(-a, -b), (a, -b), (a, b), (-a, b)], layer=layer)

    return c
Esempio n. 22
0
def crossing_arm(
    width: float = 0.5,
    r1: float = 3.0,
    r2: float = 1.1,
    w: float = 1.2,
    L: float = 3.4,
    layer_wg: Layer = LAYER.WG,
    layer_slab: Layer = LAYER.SLAB150,
    cross_section: CrossSectionFactory = strip,
) -> Component:
    """arm of a crossing"""
    c = Component()
    c << ellipse(radii=(r1, r2), layer=layer_slab)

    xs = cross_section()

    a = np.round(L + w / 2, 3)
    h = width / 2

    taper_pts = [
        (-a, h),
        (-w / 2, w / 2),
        (w / 2, w / 2),
        (a, h),
        (a, -h),
        (w / 2, -w / 2),
        (-w / 2, -w / 2),
        (-a, -h),
    ]

    c.add_polygon(taper_pts, layer=layer_wg)
    c.add_port(
        name="o1",
        midpoint=(-a, 0),
        orientation=180,
        width=width,
        layer=layer_wg,
        cross_section=xs,
    )

    c.add_port(
        name="o2",
        midpoint=(a, 0),
        orientation=0,
        width=width,
        layer=layer_wg,
        cross_section=xs,
    )

    return c
Esempio n. 23
0
def copy(D: Component,
         prefix: str = "",
         suffix: str = "_copy",
         cache: bool = True) -> Component:
    """returns a deep copy of a Component.
    based on phidl.geometry with CellArray support
    """
    D_copy = Component(name=f"{prefix}{D.name}{suffix}")
    D_copy.info = python_copy.deepcopy(D.info)
    for ref in D.references:
        if isinstance(ref, DeviceReference):
            new_ref = ComponentReference(
                ref.parent,
                origin=ref.origin,
                rotation=ref.rotation,
                magnification=ref.magnification,
                x_reflection=ref.x_reflection,
            )
            new_ref.owner = D_copy
        elif isinstance(ref, gdspy.CellArray):
            new_ref = CellArray(
                device=ref.parent,
                columns=ref.columns,
                rows=ref.rows,
                spacing=ref.spacing,
                origin=ref.origin,
                rotation=ref.rotation,
                magnification=ref.magnification,
                x_reflection=ref.x_reflection,
            )
        D_copy.add(new_ref)
        for alias_name, alias_ref in D.aliases.items():
            if alias_ref == ref:
                D_copy.aliases[alias_name] = new_ref

    for port in D.ports.values():
        D_copy.add_port(port=port)
    for poly in D.polygons:
        D_copy.add_polygon(poly)
    for label in D.labels:
        D_copy.add_label(
            text=label.text,
            position=label.position,
            layer=(label.layer, label.texttype),
        )
    if cache:
        D_copy = avoid_duplicated_cells(D_copy)
    return D_copy
Esempio n. 24
0
def union(
        component: Component,
        by_layer: bool = False,
        precision: float = 1e-4,
        join_first: bool = True,
        max_points: int = 4000,
        layer: Layer = (1, 0),
) -> Component:
    """Creates an inverted version of the input shapes with an additional
    border around the edges.

    adapted from phidl.geometry.invert

    Args:
        D: Component(/Reference), list of Component(/Reference), or Polygon
            A Component containing the polygons to perform union on.
        by_Layer: performs the union operation layer-wise so each layer can be
            individually combined.
        precision: Desired precision for rounding vertex coordinates.
        join_first: before offsetting to avoid unnecessary joins in adjacent polygon
        max_points: The maximum number of vertices within the resulting polygon.
        layer : Specific layer to put polygon geometry on.

    Returns
        Component containing the  union of the polygons
    """
    U = Component()

    if by_layer:
        all_polygons = component.get_polygons(by_spec=True)
        for layer, polygons in all_polygons.items():
            unioned_polygons = pg._union_polygons(polygons,
                                                  precision=precision,
                                                  max_points=max_points)
            U.add_polygon(unioned_polygons, layer=layer)
    else:
        all_polygons = component.get_polygons(by_spec=False)
        unioned_polygons = pg._union_polygons(all_polygons,
                                              precision=precision,
                                              max_points=max_points)
        U.add_polygon(unioned_polygons, layer=layer)
    return U
Esempio n. 25
0
def circle(
    radius: float = 10.0,
    angle_resolution: float = 2.5,
    layer: Tuple[int, int] = gf.LAYER.WG,
) -> Component:
    """Generate a circle geometry.

    Args:
        radius: of the circle.
        angle_resolution: number of degrees per point.
        layer: layer.

    """

    c = 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
Esempio n. 26
0
def add_pin_triangle(
    component: Component,
    port: Port,
    layer: Tuple[int, int] = LAYER.PORT,
    label_layer: Optional[Tuple[int, int]] = LAYER.TEXT,
) -> None:
    """Add triangle pin with a right angle, pointing out of the port

    Args:
        component:
        port: Port
        layer: for the pin marker
        label_layer: for the label
    """
    p = port

    a = p.orientation
    ca = np.cos(a * np.pi / 180)
    sa = np.sin(a * np.pi / 180)
    rot_mat = np.array([[ca, -sa], [sa, ca]])

    d = p.width / 2

    dbot = np.array([0, -d])
    dtop = np.array([0, d])
    dtip = np.array([d, 0])

    p0 = p.position + _rotate(dbot, rot_mat)
    p1 = p.position + _rotate(dtop, rot_mat)
    ptip = p.position + _rotate(dtip, rot_mat)
    polygon = [p0, p1, ptip]
    component.add_polygon(polygon, layer=layer)

    if label_layer:
        component.add_label(
            text=str(p.name),
            position=ptip,
            layer=label_layer,
        )
Esempio n. 27
0
def add_outline(
    component: Component,
    reference: Optional[ComponentReference] = None,
    layer: Tuple[int, int] = LAYER.DEVREC,
    **kwargs,
) -> None:
    """Adds devices outline bounding box in layer.

    Args:
        component: where to add the markers
        reference: to read outline from
        layer: to add padding
        default: default padding
        top: North padding
        bottom
        right
        left
    """
    c = reference or component
    if hasattr(component, "parent"):
        component = component.parent
    points = get_padding_points(component=c, default=0, **kwargs)
    component.add_polygon(points, layer=layer)
Esempio n. 28
0
def add_pin_triangle(
    component: Component,
    port: Port,
    layer: Tuple[int, int] = LAYER.PORT,
    layer_label: Optional[Tuple[int, int]] = LAYER.TEXT,
) -> None:
    """Add triangle pin with a right angle, pointing out of the port

    Args:
        component:
        port: Port
        layer: for the pin marker
        layer_label: for the label
    """
    polygon, ptip = get_pin_triangle_polygon_tip(port=port)
    component.add_polygon(polygon, layer=layer)

    if layer_label:
        component.add_label(
            text=str(port.name),
            position=ptip,
            layer=layer_label,
        )
Esempio n. 29
0
def add_padding_to_size_container(
    component: Component,
    layers: Tuple[Layer, ...] = (LAYER.PADDING, ),
    xsize: Optional[float] = None,
    ysize: Optional[float] = None,
    left: float = 0,
    bottom: float = 0,
) -> Component:
    """Returns new component with padding layers on each side.
    New size is multiple of grid size

    Args:
        component
        layers: list of layers
        xsize:
        ysize:
        left:
        bottom:
    """
    c = Component()
    cref = c << component

    top = abs(ysize - component.ysize) if ysize else 0
    right = abs(xsize - component.xsize) if xsize else 0
    points = [
        [cref.xmin - left, cref.ymin - bottom],
        [cref.xmax + right, cref.ymin - bottom],
        [cref.xmax + right, cref.ymax + top],
        [cref.xmin - left, cref.ymax + top],
    ]

    for layer in layers:
        c.add_polygon(points, layer=layer)

    c.ports = cref.ports
    c.copy_child_info(component)
    return c
Esempio n. 30
0
def wire_corner(cross_section: CrossSectionFactory = metal3,
                **kwargs) -> Component:
    """90 degrees electrical corner

    Args:
        waveguide:
        kwargs: cross_section settings

    """
    x = cross_section(**kwargs)
    layer = x.info["layer"]
    width = x.info["width"]

    c = Component()
    a = width / 2
    xpts = [-a, a, a, -a]
    ypts = [-a, -a, a, a]

    c.add_polygon([xpts, ypts], layer=layer)
    c.add_port(
        name="e1",
        midpoint=(-a, 0),
        width=width,
        orientation=180,
        layer=layer,
        port_type="electrical",
    )
    c.add_port(
        name="e2",
        midpoint=(0, a),
        width=width,
        orientation=90,
        layer=layer,
        port_type="electrical",
    )
    c.info.length = width
    return c