Source code for gdsfactory.components.add_grating_couplers

"""Add grating_couplers to a component."""

from __future__ import annotations

from collections.abc import Callable
from functools import partial

import numpy as np

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.components.bend_euler import bend_euler
from gdsfactory.components.grating_coupler_elliptical_trenches import grating_coupler_te
from gdsfactory.components.straight import straight
from gdsfactory.cross_section import strip
from gdsfactory.port import select_ports_optical
from gdsfactory.routing.manhattan import round_corners
from gdsfactory.routing.utils import (
    check_ports_have_equal_spacing,
    direction_ports_from_list_ports,
)
from gdsfactory.typings import (
    ComponentSpec,
    CrossSectionSpec,
    PortsDict,
)


[docs] @gf.cell_with_child def add_grating_couplers( component: ComponentSpec = straight, grating_coupler: ComponentSpec = grating_coupler_te, gc_port_name: str = "o1", select_ports: Callable[..., PortsDict] = select_ports_optical, ) -> Component: """Returns new component with grating couplers and labels. Args: component: to add grating_couplers. grating_coupler: grating_coupler spec. gc_port_name: where to add label. select_ports: for selecting optical_ports. """ c = Component() component = gf.get_component(component) c.add_ref(component) grating_coupler = gf.get_component(grating_coupler) c.info["polarization"] = grating_coupler.info["polarization"] c.info["wavelength"] = grating_coupler.info["wavelength"] io_gratings = [] optical_ports = select_ports(component.ports) optical_ports = list(optical_ports.values()) for port in optical_ports: gc_ref = grating_coupler.ref() gc_port = gc_ref.ports[gc_port_name] gc_ref.connect(gc_port, port) io_gratings.append(gc_ref) c.add(gc_ref) c.copy_child_info(component) return c
[docs] @gf.cell_with_child def add_grating_couplers_with_loopback_fiber_single( component: ComponentSpec = "spiral_inner_io_fiber_single", grating_coupler: ComponentSpec = grating_coupler_te, gc_port_name: str = "o1", select_ports: Callable[..., PortsDict] = select_ports_optical, with_loopback: bool = True, cross_section: CrossSectionSpec = strip, loopback_xspacing: float = 5.0, rotation: int = 90, ) -> Component: """Returns new component with all ports terminated with grating couplers. Args: component: to add grating_couplers. grating_coupler: grating_coupler spec function, string or dict. gc_port_name: grating_coupler port name. select_ports: function to select ports. with_loopback: adds a reference loopback. cross_section: for routing. loopback_xspacing: in um. rotation: in degrees, 90 for North South devices, 0 for East-West. """ c = Component() component = gf.get_component(component) c.add_ref(component) grating_coupler = gf.get_component(grating_coupler) c.info["polarization"] = grating_coupler.info["polarization"] c.info["wavelength"] = grating_coupler.info["wavelength"] io_gratings = [] optical_ports = select_ports(component.ports) optical_ports = list(optical_ports.values()) for port in optical_ports: gc_ref = grating_coupler.ref() gc_port = gc_ref.ports[gc_port_name] gc_ref.connect(gc_port, port) io_gratings.append(gc_ref) c.add(gc_ref) c.add_port(name=port.name, port=port) p2 = optical_ports[0] p1 = optical_ports[-1] if with_loopback: if rotation in {0, 180}: length = np.round(abs(p2.x - p1.x), 3) wg = c << straight(length=length, cross_section=cross_section) wg.rotate(rotation) wg.xmin = p2.x wg.ymin = c.ymax + grating_coupler.ysize / 2 + loopback_xspacing else: length = np.round(abs(p2.y - p1.y), 3) wg = c << straight(length=length, cross_section=cross_section) wg.rotate(rotation) wg.ymin = p1.y wg.xmin = c.xmax + grating_coupler.ysize / 2 + loopback_xspacing gci = c << grating_coupler gco = c << grating_coupler gci.connect(gc_port_name, wg.ports["o1"]) gco.connect(gc_port_name, wg.ports["o2"]) p1 = c.add_port(name="loopback1", port=wg.ports["o1"]) p1.snap_to_grid() p2 = c.add_port(name="loopback2", port=wg.ports["o2"]) p2.snap_to_grid() c.copy_child_info(component) return c
_spiral_inner_io_2cm = dict(component="spiral_inner_io", settings=dict(length=2e4))
[docs] @gf.cell_with_child def add_grating_couplers_with_loopback_fiber_array( component: ComponentSpec = _spiral_inner_io_2cm, grating_coupler: ComponentSpec = grating_coupler_te, excluded_ports: list[str] | None = None, grating_separation: float = 127.0, gc_port_name: str = "o1", gc_rotation: int = -90, straight_separation: float = 5.0, bend: ComponentSpec = bend_euler, with_loopback: bool = True, cross_section: CrossSectionSpec = "xs_sc", select_ports: Callable = select_ports_optical, loopback_yspacing: float = 4.0, ) -> Component: """Returns a component with grating_couplers and optional reference loopback. Args: component: to add grating_couplers. grating_coupler: grating_coupler. excluded_ports: list of ports to exclude. grating_separation: in um. gc_port_name: optional grating coupler name. gc_rotation: grating coupler rotation in degrees. straight_separation: in um. bend: bend spec. with_loopback: If True, add compact loopback alignment ports. cross_section: CrossSectionSpec. select_ports: function to select ports. loopback_yspacing: in um. """ component = gf.get_component(component) x = gf.get_cross_section(cross_section) bend_radius_loopback = x.radius excluded_ports = excluded_ports or [] gc = gf.get_component(grating_coupler) direction = "S" c = Component() c.copy_child_info(component) c.info["polarization"] = gc.info["polarization"] c.info["wavelength"] = gc.info["wavelength"] c.add_ref(component) # 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 = select_ports(component.ports) optical_ports = list(optical_ports.values()) 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( f"Grating separation must be {grating_separation}. " f"Got {grating_separation_extracted}" ) # Add grating references references = [] for port in optical_ports: gc_ref = c.add_ref(gc) gc_ref.connect(gc.ports[gc_port_name].name, port) references += [gc_ref] if with_loopback: y0 = references[0].ports[gc_port_name].y - loopback_yspacing 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 port0 = gca1.ports[gc_port_name] port1 = gca2.ports[gc_port_name] p0 = port0.center p1 = port1.center a = bend_radius_loopback + 0.5 b = max(2 * a, grating_separation / 2) y_bot_align_route = -gsi.width - straight_separation points = np.array( ( 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(cross_section=cross_section) loopback_route = round_corners( points=points, bend=bend90, cross_section=cross_section, ) c.add([gca1, gca2]) c.add(loopback_route.references) c.add_port(name="loopback1", port=port0) c.add_port(name="loopback2", port=port1) ports = [p.flip() for p in component.ports.values()] c.add_ports(ports) c.copy_child_info(component) return c
add_grating_couplers_fiber_array = partial( add_grating_couplers_with_loopback_fiber_array, with_loopback=False ) if __name__ == "__main__": # from gdsfactory.add_labels import get_optical_text # c = gf.components.grating_coupler_elliptical_te() # print(c.wavelength) # print(c.get_property('wavelength')) # c = gf.components.straight() # c = gf.components.mzi_phase_shifter() # c = add_grating_couplers_with_loopback_fiber_single(component=c, rotation=0) # c = gf.components.spiral_inner_io() # c = add_grating_couplers_with_loopback_fiber_array(component=c) # c = add_grating_couplers(c) # c = add_grating_couplers_with_loopback_fiber_array() c = add_grating_couplers_with_loopback_fiber_single() c.pprint_ports() c.show(show_ports=True) c.assert_ports_on_grid()