예제 #1
0
파일: pad.py 프로젝트: tvt173/gdsfactory
def pad_array(
    pad: ComponentOrFactory = pad,
    spacing: Tuple[float, float] = (150.0, 150.0),
    columns: int = 6,
    rows: int = 1,
    orientation: int = 270,
) -> Component:
    """Returns 2D array of pads

    Args:
        pad: pad element
        spacing: x, y pitch
        columns:
        rows:
        orientation: port orientation in deg
    """
    c = Component()
    pad = pad() if callable(pad) else pad
    size = pad.info.full.size
    c.info.size = size

    c.add_array(pad, columns=columns, rows=rows, spacing=spacing)
    width = size[0] if orientation in [90, 270] else size[1]

    for col in range(columns):
        for row in range(rows):
            c.add_port(
                name=f"e{row+1}{col+1}",
                midpoint=(col * spacing[0], row * spacing[1]),
                width=width,
                orientation=orientation,
                port_type="electrical",
                layer=pad.info["layer"],
            )
    return c
예제 #2
0
def fiber_array(
    n: int = 8,
    pitch: float = 127.0,
    core_diameter: float = 10,
    cladding_diameter: float = 125,
    layer_core: Tuple[int, int] = gf.LAYER.WG,
    layer_cladding: Tuple[int, int] = gf.LAYER.WGCLAD,
) -> Component:
    """Returns a fiber array

    .. code::

        pitch
         <->
        _________
       |         | lid
       | o o o o |
       |         | base
       |_________|
          length

    """
    c = Component()

    for i in range(n):
        core = c.add_ref(circle(radius=core_diameter / 2, layer=layer_core))
        cladding = c.add_ref(
            circle(radius=cladding_diameter / 2, layer=layer_cladding))
        core.movex(i * pitch)
        cladding.movex(i * pitch)
        c.add_port(name=f"F{i}", width=core_diameter, orientation=0)

    return c
예제 #3
0
def add_ports_from_labels(
    component: Component,
    port_width: float,
    port_layer: Layer,
    xcenter: Optional[float] = None,
    port_name_prefix: str = "o",
    port_type: str = "optical",
) -> Component:
    """Add ports from labels.
    Assumes that all ports have a label at the port center.
    """
    xc = xcenter or component.x
    yc = component.y
    for i, label in enumerate(component.labels):
        x, y = label.position
        port_name = f"{port_name_prefix}{i+1}" if port_name_prefix else i
        if x > xc:  # east
            orientation = 0
        elif x < xc:  # west
            orientation = 180
        elif y > yc:  # north
            orientation = 90
        elif y < yc:  # south
            orientation = 270

        component.add_port(
            name=port_name,
            midpoint=(x, y),
            width=port_width,
            orientation=orientation,
            port_type=port_type,
            layer=port_layer,
        )
    return component
예제 #4
0
def coupler_straight(length: float = 10.0,
                     gap: float = 0.27,
                     straight: ComponentFactory = straight_function,
                     **kwargs) -> Component:
    """Coupler_straight with two parallel straights.

    Args:
        length: of straight
        gap: between straights
        straight: straight waveguide function
        kwargs: cross_section settings
    """
    component = Component()

    straight_component = (straight(length=length, **kwargs)
                          if callable(straight) else straight)

    top = component << straight_component
    bot = component << straight_component

    # bot.ymax = 0
    # top.ymin = gap

    top.movey(straight_component.info.width + gap)

    component.add_port("o1", port=bot.ports["o1"])
    component.add_port("o2", port=top.ports["o1"])
    component.add_port("o3", port=bot.ports["o2"])
    component.add_port("o4", port=top.ports["o2"])
    component.auto_rename_ports()
    return component
예제 #5
0
def grating_coupler_array(
    grating_coupler: ComponentOrFactory = grating_coupler_circular,
    pitch: float = 127.0,
    n: int = 6,
    port_name: str = "o1",
    rotation: int = 0,
) -> Component:
    """Array of rectangular pads.

    Args:
        grating_coupler: ComponentOrFactory
        spacing: x spacing
        n: number of pads
        port_name: port name
        rotation: rotation angle for each reference

    """
    c = Component()
    grating_coupler = (grating_coupler()
                       if callable(grating_coupler) else grating_coupler)

    for i in range(n):
        gc = c << grating_coupler
        gc.rotate(rotation)
        gc.x = i * pitch
        port_name_new = f"o{i}"
        c.add_port(port=gc.ports[port_name], name=port_name_new)

    return c
예제 #6
0
def spiral_inner_io_fiber_single(
        cross_section: CrossSectionFactory = strip,
        cross_section_bend: Optional[CrossSectionFactory] = None,
        x_straight_inner_right: float = 40.0,
        x_straight_inner_left: float = 75.0,
        y_straight_inner_top: float = 10.0,
        y_straight_inner_bottom: float = 0.0,
        grating_spacing: float = 200.0,
        **kwargs):
    """Spiral with 0 and 270 degree ports."""
    c = Component()
    ref = c << spiral_inner_io(cross_section=cross_section,
                               cross_section_bend=cross_section_bend,
                               x_straight_inner_right=x_straight_inner_right,
                               x_straight_inner_left=x_straight_inner_left,
                               y_straight_inner_top=y_straight_inner_top,
                               y_straight_inner_bottom=y_straight_inner_bottom,
                               grating_spacing=grating_spacing,
                               **kwargs)
    ref.rotate(90)
    bend = bend_euler(cross_section=cross_section_bend or cross_section)
    btop = c << bend
    bbot = c << bend

    bbot.connect("o2", ref.ports["o1"])
    btop.connect("o1", ref.ports["o2"])
    c.add_port("o2", port=btop.ports["o2"])
    c.add_port("o1", port=bbot.ports["o1"])
    return c
예제 #7
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
예제 #8
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
예제 #9
0
def extend_ports_list(
    ports: List[Port],
    extension_factory: ComponentOrFactory,
    extension_port_name: Optional[str] = None,
) -> Component:
    """Returns a component with the extensions for a list of ports.

    Args:
        ports: list of ports
        extension_factory: function for extension
        extension_port_name: to connect extension

    """
    c = Component()
    extension = (extension_factory()
                 if callable(extension_factory) else extension_factory)

    extension_port_name = extension_port_name or list(
        extension.ports.keys())[0]

    for i, port in enumerate(ports):
        extension_ref = c << extension
        extension_ref.connect(extension_port_name, port)

        for port_name, port in extension_ref.ports.items():
            # if port_name not in extension_port_name:
            c.add_port(f"{i}_{port_name}", port=port)

    c.auto_rename_ports()
    return c
예제 #10
0
def grating_coupler_array(
    grating_coupler: ComponentOrFactory = grating_coupler_elliptical2,
    pitch: float = 127.0,
    n: int = 6,
    port_name: str = "o1",
) -> Component:
    """Array of rectangular pads.

    Args:
        grating_coupler: ComponentOrFactory
        spacing: x spacing
        n: number of pads
        port_list: list of port orientations (N, S, W, E) per pad

    """
    c = Component()
    grating_coupler = (grating_coupler()
                       if callable(grating_coupler) else grating_coupler)

    for i in range(n):
        gc = c << grating_coupler
        gc.x = i * pitch
        port_name_new = f"o{i}"
        c.add_port(port=gc.ports[port_name], name=port_name_new)

    return c
예제 #11
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
예제 #12
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
예제 #13
0
파일: ramp.py 프로젝트: tvt173/gdsfactory
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
예제 #14
0
파일: cell.py 프로젝트: tvt173/gdsfactory
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
예제 #15
0
def bend_euler_s(**kwargs) -> Component:
    """Sbend made of euler bends."""
    c = Component()
    b = bend_euler(**kwargs)
    b1 = c.add_ref(b)
    b2 = c.add_ref(b)
    b2.mirror()
    b2.connect("o1", b1.ports["o2"])
    c.add_port("o1", port=b1.ports["o1"])
    c.add_port("o2", port=b2.ports["o2"])
    return c
예제 #16
0
def spiral_inner_io_fiber_single(
        cross_section: CrossSectionFactory = strip,
        cross_section_bend: Optional[CrossSectionFactory] = None,
        cross_section_ports: Optional[CrossSectionFactory] = None,
        x_straight_inner_right: float = 40.0,
        x_straight_inner_left: float = 75.0,
        y_straight_inner_top: float = 10.0,
        y_straight_inner_bottom: float = 0.0,
        grating_spacing: float = 200.0,
        **kwargs):
    """Returns Spiral with 90 and 270 degree ports.
    You can add single fiber north and south grating couplers
    inside the spiral to save space

    Args:
        cross_section: for the straight sections in the spiral
        cross_section_bend: for the bends in the spiral
        cross_section_ports: for input/output ports
        x_straight_inner_right:
        x_straight_inner_left:
        y_straight_inner_top:
        y_straight_inner_bottom:
        grating_spacing:
        N: number of loops
        waveguide_spacing: center to center spacing
        bend90_function
        bend180_function
        straight: straight function
        length: computes spiral length from simple interpolation
        kwargs: cross_section settings
    """
    c = Component()
    spiral = spiral_inner_io(cross_section=cross_section,
                             cross_section_bend=cross_section_bend,
                             x_straight_inner_right=x_straight_inner_right,
                             x_straight_inner_left=x_straight_inner_left,
                             y_straight_inner_top=y_straight_inner_top,
                             y_straight_inner_bottom=y_straight_inner_bottom,
                             grating_spacing=grating_spacing,
                             **kwargs)
    ref = c << spiral
    ref.rotate(90)

    cross_section_ports = cross_section_ports or cross_section_bend or cross_section
    bend = bend_euler(cross_section=cross_section_ports)
    btop = c << bend
    bbot = c << bend
    c.copy_child_info(spiral)

    bbot.connect("o2", ref.ports["o1"])
    btop.connect("o1", ref.ports["o2"])
    c.add_port("o2", port=btop.ports["o2"])
    c.add_port("o1", port=bbot.ports["o1"])
    return c
예제 #17
0
def coupler90bend(
    radius: float = 10.0,
    gap: float = 0.2,
    bend: ComponentFactory = bend_euler,
    cross_section_inner: CrossSectionFactory = strip,
    cross_section_outer: CrossSectionFactory = strip,
) -> Component:
    r"""Returns 2 coupled bends.

    Args:
        radius: um
        gap: um
        bend: for bend
        cross_section_inner:
        cross_section_outer:


    .. code::

            r   3 4
            |   | |
            |  / /
            | / /
        2____/ /
        1_____/

    """

    c = Component()

    xi = cross_section_inner()
    xo = cross_section_outer()

    width = xo.info["width"] / 2 + xi.info["width"] / 2
    spacing = gap + width

    bend90_inner = bend(radius=radius, cross_section=cross_section_inner)
    bend90_outer = bend(radius=radius + spacing,
                        cross_section=cross_section_outer)
    bend_inner_ref = c << bend90_inner
    bend_outer_ref = c << bend90_outer

    pbw = bend_inner_ref.ports["o1"]
    bend_inner_ref.movey(pbw.midpoint[1] + spacing)

    # This component is a leaf cell => using absorb
    c.absorb(bend_outer_ref)
    c.absorb(bend_inner_ref)

    c.add_port("o1", port=bend_outer_ref.ports["o1"])
    c.add_port("o2", port=bend_inner_ref.ports["o1"])
    c.add_port("o3", port=bend_inner_ref.ports["o2"])
    c.add_port("o4", port=bend_outer_ref.ports["o2"])
    return c
예제 #18
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
예제 #19
0
파일: fiber.py 프로젝트: tvt173/gdsfactory
def fiber(
    core_diameter: float = 10,
    cladding_diameter: float = 125,
    layer_core: Tuple[int, int] = gf.LAYER.WG,
    layer_cladding: Tuple[int, int] = gf.LAYER.WGCLAD,
) -> Component:
    """Returns a fiber."""
    c = Component()
    c.add_ref(circle(radius=core_diameter / 2, layer=layer_core))
    c.add_ref(circle(radius=cladding_diameter / 2, layer=layer_cladding))
    c.add_port(name="F0", width=core_diameter, orientation=0)
    return c
예제 #20
0
def fanout_component(
    component: ComponentOrFactory,
    port_names: Tuple[str, ...],
    pitch: Tuple[float, float] = (0.0, 20.0),
    dx: float = 20.0,
    sort_ports: bool = True,
    **kwargs,
) -> Component:
    """Returns component with Sbend fanout routes.

    Args:
        component: to fanout ports
        port_names: list of port names
        pitch: target port spacing for new component
        dx: how far the fanout in x direction
        kwargs: for get_route_sbend
    """

    c = Component()
    comp = component() if callable(component) else component
    ref = c.add_ref(comp)
    ref.movey(-comp.y)

    for port_name in port_names:
        if port_name not in ref.ports:
            raise ValueError(f"{port_name} not in {list(ref.ports.keys())}")

    ports1 = [p for p in ref.ports.values() if p.name in port_names]
    port = ports1[0]
    port_extended_x = port.get_extended_midpoint(dx)[0]
    port_settings = port.settings.copy()

    port_settings.pop("name")
    port_settings.update(midpoint=(port_extended_x, 0))
    port_settings.update(orientation=(port.angle + 180) % 360)

    ports2 = port_array(n=len(ports1), pitch=pitch, **port_settings)

    if sort_ports:
        ports1, ports2 = sort_ports_function(ports1, ports2)

    for i, (p1, p2) in enumerate(zip(ports1, ports2)):
        route = get_route_sbend(port1=p1, port2=p2, **kwargs)
        c.add(route.references)
        c.add_port(f"new_{i}", port=flip(p2))

    for port in ref.ports.values():
        if port.name not in port_names:
            c.add_port(port.name, port=port)

    return c
예제 #21
0
def _sample_route_sides() -> Component:
    c = Component()
    _dummy_t = _sample_route_side()
    sides = ["north", "south", "east", "west"]
    positions = [(0, 0), (400, 0), (400, 400), (0, 400)]
    for pos, side in zip(positions, sides):
        dummy_ref = _dummy_t.ref(position=pos)
        c.add(dummy_ref)
        routes, ports = route_ports_to_side(dummy_ref, side, layer=(2, 0))
        for route in routes:
            c.add(route.references)
        for i, p in enumerate(ports):
            c.add_port(name=f"{side[0]}{i}", port=p)
    return c
예제 #22
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
예제 #23
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
예제 #24
0
def coupler90(gap: float = 0.2,
              radius: float = 10.0,
              bend: ComponentFactory = bend_euler,
              cross_section: CrossSectionFactory = strip,
              **kwargs) -> Component:
    r"""straight coupled to a bend.

    Args:
        gap: um
        radius: um
        straight: for straight
        bend: for bend
        cross_section:
        kwargs: cross_section settings

    .. code::

             3
             |
            /
           /
        2_/
        1____4

    """
    c = Component()
    x = cross_section(radius=radius, **kwargs)

    bend90 = (bend(cross_section=cross_section, radius=radius, **kwargs)
              if callable(bend) else bend)
    bend_ref = c << bend90
    straight_component = (straight(
        cross_section=cross_section,
        length=bend90.ports["o2"].midpoint[0] - bend90.ports["o1"].midpoint[0],
        **kwargs) if callable(straight) else straight)

    wg_ref = c << straight_component
    width = x.info["width"]

    pbw = bend_ref.ports["o1"]
    bend_ref.movey(pbw.midpoint[1] + gap + width)

    c.absorb(wg_ref)
    c.absorb(bend_ref)

    c.add_port("o1", port=wg_ref.ports["o1"])
    c.add_port("o4", port=wg_ref.ports["o2"])
    c.add_port("o2", port=bend_ref.ports["o1"])
    c.add_port("o3", port=bend_ref.ports["o2"])
    return c
예제 #25
0
def awg(
    arms: int = 10,
    outputs: int = 3,
    free_propagation_region_input_function=free_propagation_region_input,
    free_propagation_region_output_function=free_propagation_region_output,
    fpr_spacing: float = 50.0,
) -> Component:
    """Returns a basic Arrayed Waveguide grating.

    Args:
        arms: number of arms
        outputs: number of outputs
        free_propagation_region_input_function: for input
        free_propagation_region_output_function: for output
        fpr_spacing: x separation between input/output FPR

    """
    c = Component()
    fpr_in = free_propagation_region_input_function(
        inputs=1,
        outputs=arms,
    )
    fpr_out = free_propagation_region_output_function(
        inputs=outputs,
        outputs=arms,
    )

    fpr_in_ref = c.add_ref(fpr_in)
    fpr_out_ref = c.add_ref(fpr_out)

    fpr_in_ref.rotate(90)
    fpr_out_ref.rotate(90)

    fpr_out_ref.x += fpr_spacing
    routes = gf.routing.get_bundle(
        fpr_in_ref.get_ports_list(prefix="E"), fpr_out_ref.get_ports_list(prefix="E")
    )

    c.lengths = []
    for route in routes:
        c.add(route.references)
        c.lengths.append(route.length)

    c.add_port("o1", port=fpr_in_ref.ports["o1"])

    for i, port in enumerate(fpr_out_ref.get_ports_list(prefix="W")):
        c.add_port(f"E{i}", port=port)

    c.delta_length = np.mean(np.diff(c.lengths))
    return c
예제 #26
0
파일: array.py 프로젝트: tvt173/gdsfactory
def array(
    component: gf.types.ComponentOrFactory = straight,
    spacing: Tuple[float, float] = (150.0, 150.0),
    columns: int = 6,
    rows: int = 1,
) -> Component:
    """Returns an array of components.

    Args:
        component: to replicate
        spacing: x, y spacing
        columns: in x
        rows: in y

    Raises:
        ValueError: If columns > 1 and spacing[0] = 0
        ValueError: If rows > 1 and spacing[1] = 0

    .. code::

        2 rows x 4 columns
         ___        ___       ___          ___
        |   |      |   |     |   |        |   |
        |___|      |___|     |___|        |___|


         ___        ___       ___          ___
        |   |      |   |     |   |        |   |
        |___|      |___|     |___|        |___|


    """
    if rows > 1 and spacing[1] == 0:
        raise ValueError(f"rows = {rows} > 1 require spacing[1] > 0")

    if columns > 1 and spacing[0] == 0:
        raise ValueError(f"columns = {columns} > 1 require spacing[0] > 0")

    c = Component()
    component = component() if callable(component) else component
    c.add_array(component, columns=columns, rows=rows, spacing=spacing)

    for col in range(columns):
        for row in range(rows):
            for port in component.ports.values():
                name = f"{port.name}_{row+1}_{col+1}"
                c.add_port(name, port=port)
                c.ports[name].move((col * spacing[0], row * spacing[1]))
    return c
예제 #27
0
def crossing_from_taper(taper=lambda: taper(width2=2.5, length=3.0)):
    """
    Crossing based on a taper. The default is a dummy taper
    """
    taper = taper() if callable(taper) else taper

    c = Component()
    for i, a in enumerate([0, 90, 180, 270]):
        _taper = taper.ref(position=(0, 0), port_id="o2", rotation=a)
        c.add(_taper)
        c.add_port(name=i, port=_taper.ports["o1"])
        c.absorb(_taper)

    c.auto_rename_ports()
    return c
예제 #28
0
파일: copy.py 프로젝트: simbilod/gdsfactory
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
예제 #29
0
def crossing(arm: ComponentFactory = crossing_arm) -> Component:
    """Waveguide crossing"""
    cx = Component()
    arm = arm() if callable(arm) else 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=port_id, port=p)
            port_id += 1
    cx.auto_rename_ports()
    return cx
예제 #30
0
def add_ports_from_markers_square(
    component: Component,
    pin_layer: Layer = (69, 0),
    port_layer: Optional[Layer] = None,
    orientation: Optional[int] = 90,
    min_pin_area_um2: float = 0,
    max_pin_area_um2: float = 150 * 150,
    pin_extra_width: float = 0.0,
    port_names: Optional[Tuple[str, ...]] = None,
    port_name_prefix: str = "o",
) -> Component:
    """add ports from markers center in port_layer

    squared

    Args:
        component: to read polygons from and to write ports to
        pin_layer: for port markers
        port_layer: for the new created port
        orientation: in degrees 90: north, 0: east, 180: west, 270: south
        min_pin_area_um2: ignores pins with area smaller than min_pin_area_um2
        max_pin_area_um2: ignore pins for area above certain size
        pin_extra_width: 2*offset from pin to straight
        port_names: names of the ports (defaults to {i})

    """
    port_markers = read_port_markers(component, [pin_layer])
    port_names = port_names or [
        f"{port_name_prefix}{i+1}" for i in range(len(port_markers.polygons))
    ]
    layer = port_layer or pin_layer

    for port_name, p in zip(port_names, port_markers.polygons):
        dy = snap_to_grid(p.ymax - p.ymin)
        dx = snap_to_grid(p.xmax - p.xmin)
        x = p.x
        y = p.y
        if dx == dy and max_pin_area_um2 > dx * dy > min_pin_area_um2:
            component.add_port(
                port_name,
                midpoint=(x, y),
                width=dx - pin_extra_width,
                orientation=orientation,
                layer=layer,
            )
    return component