Routing#

Optical and high-speed RF ports have specific orientation requirements to ensure that routes avoid sharp turns, which can cause signal reflections.

We offer routing functions tailored for these requirements:

  • route_single: Routes a single connection between two ports.

  • route_bundle: Routes multiple connections between two port groups using a bundle/river/bus router. It also accommodates waypoints and routing steps.

The most versatile function is route_bundle, as it handles both single and grouped routes with length matching, ensuring all routes are of equal length.

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.port import Port
c = gf.Component()
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((100, 50))
c
../_images/eaea4916a9980065626104f6668ebbe798dbf5e52ad50da496c44ef11f21be81.png

route_single#

route_single returns a Manhattan route between 2 ports

help(gf.routing.route_single)
Help on function route_single in module gdsfactory.routing.route_single:

route_single(component: 'Component', port1: 'Port', port2: 'Port', cross_section: 'CrossSectionSpec | None' = None, layer: 'LayerSpec | None' = None, bend: 'ComponentSpec' = 'bend_euler', straight: 'ComponentSpec' = 'straight', start_straight_length: 'float' = 0.0, end_straight_length: 'float' = 0.0, waypoints: 'WayPoints | None' = None, steps: "Sequence[Mapping[Literal['x', 'y', 'dx', 'dy'], int | float]] | None" = None, port_type: 'str | None' = None, allow_width_mismatch: 'bool' = False, radius: 'float | None' = None, route_width: 'float | None' = None, auto_taper: 'bool' = True) -> 'ManhattanRoute'
    Returns a Manhattan Route between 2 ports.
    
    The references are straights, bends and tapers.
    `route_single` is an automatic version of `route_single_from_steps`.
    
    Args:
        component: to place the route into.
        port1: start port.
        port2: end port.
        cross_section: spec.
        layer: layer spec.
        bend: bend spec.
        straight: straight spec.
        start_straight_length: length of starting straight.
        end_straight_length: length of end straight.
        waypoints: optional list of points to pass through.
        steps: optional list of steps to pass through.
        port_type: port type to route.
        allow_width_mismatch: allow different port widths.
        radius: bend radius. If None, defaults to cross_section.radius.
        route_width: width of the route in um. If None, defaults to cross_section.width.
        auto_taper: add auto tapers.
    
    .. plot::
        :include-source:
    
        import gdsfactory as gf
    
        c = gf.Component()
        mmi1 = c << gf.components.mmi1x2()
        mmi2 = c << gf.components.mmi1x2()
        mmi2.dmove((40, 20))
        gf.routing.route_single(c, mmi1.ports["o2"], mmi2.ports["o1"], radius=5, cross_section="strip")
        c.plot()
c = gf.Component()
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((100, 50))
route = gf.routing.route_single(
    c,
    port1=mmi1.ports["o2"],
    port2=mmi2.ports["o1"],
    cross_section=gf.cross_section.strip,
)
c
../_images/4e9180f80cc9d74264bd1d5ea34f802fd3d3c16c2bc6cf5d47c0a31e969a4381.png
route
ManhattanRoute(backbone=[15500,625, 25500,625, 25500,50000, 90000,50000], start_port=Port(, dwidth: 0.5, trans: r180 *1 15.5,0.625, layer: WG (1/0), port_type: optical), end_port=Port(, dwidth: 0.5, trans: r0 *1 90,50, layer: WG (1/0), port_type: optical), instances=[Unnamed_4: ports ['o1', 'o2'], vinsts=[] info=Info(length=16.637, dy=10.0, min_bend_radius=7.061, radius=10.0, width=0.5, route_info_type='strip', route_info_length=16.637, route_info_weight=16.637, route_info_strip_length=16.637, route_info_n_bend_90=1.0, route_info_min_bend_radius=7.061) kcl=KCLayout(name='DEFAULT', layout=<klayout.dbcore.Layout object at 0x7f788d420230>, layer_enclosures=LayerEnclosureModel(root={'78687732': LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure')}), cross_sections={'78687732_500': SymmetricalCrossSection(width=500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_500'), '78687732_1000': SymmetricalCrossSection(width=1000, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_1000'), '78687732_2500': SymmetricalCrossSection(width=2500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_2500')}, enclosure=KCellEnclosure(enclosures=LayerEnclosureCollection(enclosures=[])), library=<klayout.dbcore.Library object at 0x7f788d4202d0>, factories={'taper': <function taper at 0x7f7877e08540>, 'bend_s_bezier': <function bend_s_bezier_factory.<locals>.bend_s_bezier at 0x7f7883695e40>, 'bend_circular': <function bend_circular at 0x7f7877fe2980>, 'bend_euler': <function bend_euler at 0x7f7877fe3380>, 'bend_s_euler': <function bend_s_euler_factory.<locals>.bend_s_euler at 0x7f7882088fe0>, 'straight': <function straight at 0x7f7877e6bce0>, 'rotate': <function rotate at 0x7f7880381120>, 'from_image': <function from_image at 0x7f78802cf600>, 'floorplan_with_block_letters': <function floorplan_with_block_letters at 0x7f7877f5dd00>, 'bend_circular_heater': <function bend_circular_heater at 0x7f7877fe2c00>, 'bend_euler_s': <function bend_euler_s at 0x7f7877fe3240>, 'bezier': <function bezier at 0x7f7877fe3920>, 'bend_s': <function bend_s at 0x7f7877fe3b00>, 'add_fiber_array_optical_south_electrical_north': <function add_fiber_array_optical_south_electrical_north at 0x7f7877fe3d80>, 'ramp': <function ramp at 0x7f7877e082c0>, 'taper_strip_to_ridge': <function taper_strip_to_ridge at 0x7f7877e085e0>, 'taper_strip_to_ridge_trenches': <function taper_strip_to_ridge_trenches at 0x7f7877e08860>, 'taper_sc_nc': <function taper_sc_nc at 0x7f7877e089a0>, 'taper_adiabatic': <function taper_adiabatic at 0x7f7877e08cc0>, 'taper_cross_section': <function taper_cross_section at 0x7f7877e08ea0>, 'taper_from_csv': <function taper_from_csv at 0x7f7877e09080>, 'taper_parabolic': <function taper_parabolic at 0x7f7877e091c0>, 'add_termination': <function add_termination at 0x7f7877fe3ec0>, 'add_trenches': <function add_trenches at 0x7f7877e08fe0>, 'array': <function array at 0x7f7877e093a0>, 'copy_layers': <function copy_layers at 0x7f7877e098a0>, 'extend_ports_list': <function extend_ports_list at 0x7f7877e099e0>, 'extend_ports': <function extend_ports at 0x7f7877e09d00>, 'pack_doe': <function pack_doe at 0x7f7877e0a520>, 'pack_doe_grid': <function pack_doe_grid at 0x7f7877e0a660>, 'splitter_chain': <function splitter_chain at 0x7f7877e0a7a0>, 'mzi': <function mzi at 0x7f7877e0ad40>, 'mzi_lattice': <function mzi_lattice at 0x7f7877e0b060>, 'mzi_lattice_mmi': <function mzi_lattice_mmi at 0x7f7877e0b1a0>, 'mzi_pads_center': <function mzi_pads_center at 0x7f7877e0b420>, 'mzit': <function mzit at 0x7f7877e0b600>, 'mzit_lattice': <function mzit_lattice at 0x7f7877e0b740>, 'splitter_tree': <function splitter_tree at 0x7f7877e0b2e0>, 'coupler_symmetric': <function coupler_symmetric at 0x7f7877e0b920>, 'coupler_straight': <function coupler_straight at 0x7f7877e0ba60>, 'coupler': <function coupler at 0x7f7877e0bba0>, 'coupler90': <function coupler90 at 0x7f7877e0bd80>, 'coupler90bend': <function coupler90bend at 0x7f7877e0be20>, 'coupler_adiabatic': <function coupler_adiabatic at 0x7f7877e38180>, 'coupler_asymmetric': <function coupler_asymmetric at 0x7f7877e38400>, 'coupler_bent_half': <function coupler_bent_half at 0x7f7877e38720>, 'coupler_bent': <function coupler_bent at 0x7f7877e38860>, 'coupler_broadband': <function coupler_broadband at 0x7f7877e38ae0>, 'coupler_full': <function coupler_full at 0x7f7877e38cc0>, 'coupler_ring': <function coupler_ring at 0x7f7877e38f40>, 'coupler_straight_asymmetric': <function coupler_straight_asymmetric at 0x7f7877e391c0>, 'align_wafer': <function align_wafer at 0x7f7877e39580>, 'add_frame': <function add_frame at 0x7f7877e39620>, 'die': <function die at 0x7f7877e39940>, 'die_with_pads': <function die_with_pads at 0x7f7877e39b20>, 'seal_ring': <function seal_ring at 0x7f7877e39d00>, 'seal_ring_segmented': <function seal_ring_segmented at 0x7f7877e39e40>, 'wafer': <function wafer at 0x7f7877e3a020>, 'free_propagation_region': <function free_propagation_region at 0x7f7877e3a480>, 'awg': <function awg at 0x7f7877e3a520>, 'dbr_cell': <function dbr_cell at 0x7f7877e3a840>, 'dbr': <function dbr at 0x7f7877e3a980>, 'dbr_tapered': <function dbr_tapered at 0x7f7877e3ac00>, 'bbox': <function bbox at 0x7f7877e3b380>, 'C': <function C at 0x7f7877e3b560>, 'circle': <function circle at 0x7f7877e3b740>, 'compass': <function compass at 0x7f7877e3b9c0>, 'cross': <function cross at 0x7f7877e3bba0>, 'ellipse': <function ellipse at 0x7f7877e3bd80>, 'fiducial_squares': <function fiducial_squares at 0x7f7877e3bec0>, 'L': <function L at 0x7f7877e680e0>, 'nxn': <function nxn at 0x7f7877e682c0>, 'rectangle': <function rectangle at 0x7f7877e684a0>, 'rectangles': <function rectangles at 0x7f7877e685e0>, 'regular_polygon': <function regular_polygon at 0x7f7877e68720>, 'triangle': <function triangle at 0x7f7877e68900>, 'triangle2': <function triangle2 at 0x7f7877e68a40>, 'triangle4': <function triangle4 at 0x7f7877e68b80>, 'fiber': <function fiber at 0x7f7877e3af20>, 'fiber_array': <function fiber_array at 0x7f7877e68c20>, 'crossing_arm': <function crossing_arm at 0x7f7877e6b600>, 'crossing': <function crossing at 0x7f7877e6b740>, 'crossing_linear_taper': <function crossing_linear_taper at 0x7f7877e6b880>, 'crossing_etched': <function crossing_etched at 0x7f7877e6b9c0>, 'crossing45': <function crossing45 at 0x7f7877e6bb00>, 'straight_array': <function straight_array at 0x7f7877e6bf60>, 'wire_straight': <function wire_straight at 0x7f7877e9c0e0>, 'straight_heater_doped_rib': <function straight_heater_doped_rib at 0x7f7877e9c4a0>, 'straight_heater_doped_strip': <function straight_heater_doped_strip at 0x7f7877e9c680>, 'straight_heater_meander': <function straight_heater_meander at 0x7f7877e9c9a0>, 'via': <function via at 0x7f7877e9d1c0>, 'via_circular': <function via_circular at 0x7f7877e9d300>, 'via_chain': <function via_chain at 0x7f7877e9d620>, 'via_corner': <function via_corner at 0x7f7877e9d800>, 'via_stack': <function via_stack at 0x7f7877e9d9e0>, 'via_stack_corner45': <function via_stack_corner45 at 0x7f7877e9db20>, 'via_stack_corner45_extended': <function via_stack_corner45_extended at 0x7f7877e9dc60>, 'via_stack_with_offset': <function via_stack_with_offset at 0x7f7877e9dda0>, 'straight_heater_meander_doped': <function straight_heater_meander_doped at 0x7f7877e9cea0>, 'straight_heater_metal_undercut': <function straight_heater_metal_undercut at 0x7f7877e9dd00>, 'straight_heater_metal_simple': <function straight_heater_metal_simple at 0x7f7877e9e020>, 'straight_piecewise': <function straight_piecewise at 0x7f7877e9e160>, 'straight_pin': <function straight_pin at 0x7f7877e9e200>, 'straight_pin_slot': <function straight_pin_slot at 0x7f7877e9e480>, 'wire_corner': <function wire_corner at 0x7f7877e9e700>, 'wire_corner45': <function wire_corner45 at 0x7f7877e9e840>, 'wire_corner_sections': <function wire_corner_sections at 0x7f7877e9e8e0>, 'loop_mirror': <function loop_mirror at 0x7f7877e68ae0>, 'mode_converter': <function mode_converter at 0x7f7877ec4360>, 'polarization_splitter_rotator': <function polarization_splitter_rotator at 0x7f7877ec4680>, 'terminator': <function terminator at 0x7f7877ec4c20>, 'grating_coupler_array': <function grating_coupler_array at 0x7f7877ec4ea0>, 'grating_coupler_dual_pol': <function grating_coupler_dual_pol at 0x7f7877ec51c0>, 'grating_coupler_elliptical': <function grating_coupler_elliptical at 0x7f7877ec5800>, 'grating_coupler_elliptical_arbitrary': <function grating_coupler_elliptical_arbitrary at 0x7f7877ec5a80>, 'grating_coupler_elliptical_uniform': <function grating_coupler_elliptical_uniform at 0x7f7877ec5d00>, 'grating_coupler_elliptical_lumerical': <function grating_coupler_elliptical_lumerical at 0x7f7877ec5e40>, 'grating_coupler_elliptical_trenches': <function grating_coupler_elliptical_trenches at 0x7f7877ec5ee0>, 'grating_coupler_loss': <function grating_coupler_loss at 0x7f7877ec62a0>, 'grating_coupler_rectangular': <function grating_coupler_rectangular at 0x7f7877ec6480>, 'grating_coupler_rectangular_arbitrary': <function grating_coupler_rectangular_arbitrary at 0x7f7877ec6700>, 'grating_coupler_tree': <function grating_coupler_tree at 0x7f7877ec6980>, 'mmi': <function mmi at 0x7f7877ec6ca0>, 'mmi1x2': <function mmi1x2 at 0x7f7877ec6fc0>, 'mmi1x2_with_sbend': <function mmi1x2_with_sbend at 0x7f7877ec71a0>, 'mmi2x2': <function mmi2x2 at 0x7f7877ec74c0>, 'mmi2x2_with_sbend': <function mmi2x2_with_sbend at 0x7f7877ec7600>, 'mmi_90degree_hybrid': <function mmi_90degree_hybrid at 0x7f7877ec77e0>, 'mmi_tapered': <function mmi_tapered at 0x7f7877ec7b00>, 'pad': <function pad at 0x7f7877ec7d80>, 'pad_array': <function pad_array at 0x7f7877ec7f60>, 'pad_gsg_short': <function pad_gsg_short at 0x7f7877d002c0>, 'pads_shorted': <function pads_shorted at 0x7f7877d00540>, 'rectangle_with_slits': <function rectangle_with_slits at 0x7f7877d00680>, 'cavity': <function cavity at 0x7f7877d00900>, 'cdsem_all': <function cdsem_all at 0x7f7877d00b80>, 'cdsem_bend180': <function cdsem_bend180 at 0x7f7877d00d60>, 'cdsem_coupler': <function cdsem_coupler at 0x7f7877d00ea0>, 'cdsem_straight': <function cdsem_straight at 0x7f7877d011c0>, 'cdsem_straight_density': <function cdsem_straight_density at 0x7f7877d01300>, '_bendu_double': <function _bendu_double at 0x7f7877d01580>, '_straight_double': <function _straight_double at 0x7f7877d016c0>, 'cutback_2x2': <function cutback_2x2 at 0x7f7877d01800>, 'cutback_bend': <function cutback_bend at 0x7f7877d01bc0>, 'cutback_bend90': <function cutback_bend90 at 0x7f7877d01d00>, 'staircase': <function staircase at 0x7f7877d01e40>, 'cutback_bend180': <function cutback_bend180 at 0x7f7877d01f80>, 'cutback_component': <function cutback_component at 0x7f7877d020c0>, 'cutback_splitter': <function cutback_splitter at 0x7f7877d02480>, 'greek_cross': <function greek_cross at 0x7f7877d025c0>, 'greek_cross_with_pads': <function greek_cross_with_pads at 0x7f7877d02840>, 'litho_calipers': <function litho_calipers at 0x7f7877d02a20>, 'litho_ruler': <function litho_ruler at 0x7f7877d02d40>, 'litho_steps': <function litho_steps at 0x7f7877d02f20>, 'resistance_meander': <function resistance_meander at 0x7f7877d03060>, 'resistance_sheet': <function resistance_sheet at 0x7f7877d03240>, 'verniers': <function verniers at 0x7f7877d03420>, 'text': <function text at 0x7f7877d50180>, 'text_lines': <function text_lines at 0x7f7877d50360>, 'text_klayout': <function text_klayout at 0x7f7877d504a0>, 'text_freetype': <function text_freetype at 0x7f7877d507c0>, 'pixel_array': <function pixel_array at 0x7f7877d50a40>, 'text_rectangular': <function text_rectangular at 0x7f7877d50b80>, 'text_rectangular_multi_layer': <function text_rectangular_multi_layer at 0x7f7877d50cc0>, 'pixel': <function pixel at 0x7f7877d03740>, 'qrcode': <function qrcode at 0x7f7877d509a0>, 'version_stamp': <function version_stamp at 0x7f7877d50d60>, 'disk': <function disk at 0x7f7877d51300>, 'disk_heater': <function disk_heater at 0x7f7877d51440>, 'ring': <function ring at 0x7f7877d516c0>, 'ring_crow': <function ring_crow at 0x7f7877d518a0>, 'ring_crow_couplers': <function ring_crow_couplers at 0x7f7877d519e0>, 'ring_double': <function ring_double at 0x7f7877d51bc0>, 'ring_double_bend_coupler': <function ring_double_bend_coupler at 0x7f7877d51ee0>, 'ring_double_heater': <function ring_double_heater at 0x7f7877d52020>, 'ring_double_pn': <function ring_double_pn at 0x7f7877d52340>, 'ring_single_pn': <function ring_single_pn at 0x7f7877d52480>, 'ring_single': <function ring_single at 0x7f7877d52660>, 'ring_single_array': <function ring_single_array at 0x7f7877d527a0>, 'coupler_bend': <function coupler_bend at 0x7f7877d528e0>, 'coupler_ring_bend': <function coupler_ring_bend at 0x7f7877d52a20>, 'ring_single_bend_coupler': <function ring_single_bend_coupler at 0x7f7877d52b60>, 'ring_single_dut': <function ring_single_dut at 0x7f7877d52d40>, 'delay_snake': <function delay_snake at 0x7f7877d52fc0>, 'delay_snake2': <function delay_snake2 at 0x7f7877d531a0>, 'delay_snake_sbend': <function delay_snake_sbend at 0x7f7877d53420>, 'spiral': <function spiral at 0x7f7877d536a0>, 'spiral_double': <function spiral_double at 0x7f7877d53880>, 'spiral_racetrack': <function spiral_racetrack at 0x7f7877d53b00>, 'spiral_racetrack_fixed_length': <function spiral_racetrack_fixed_length at 0x7f7877d53c40>, 'spiral_racetrack_heater_metal': <function spiral_racetrack_heater_metal at 0x7f7877d53e20>, 'spiral_racetrack_heater_doped': <function spiral_racetrack_heater_doped at 0x7f7877d53f60>, 'spiral_inductor': <function spiral_inductor at 0x7f7877d900e0>, 'hline': <function hline at 0x7f7877d90360>, 'optimal_90deg': <function optimal_90deg at 0x7f7877d904a0>, 'optimal_hairpin': <function optimal_hairpin at 0x7f7877d907c0>, 'optimal_step': <function optimal_step at 0x7f7877d90900>, 'snspd': <function snspd at 0x7f7877d90ae0>, 'interdigital_capacitor': <function interdigital_capacitor at 0x7f7877d90cc0>, 'ge_detector_straight_si_contacts': <function ge_detector_straight_si_contacts at 0x7f7877d90f40>, 'edge_coupler_silicon': <function edge_coupler_silicon at 0x7f7877d911c0>, 'edge_coupler_array': <function edge_coupler_array at 0x7f7877d91300>, 'edge_coupler_array_with_loopback': <function edge_coupler_array_with_loopback at 0x7f7877d91440>}, virtual_factories={'virtual_bend_circular': <function virtual_bend_circular_factory.<locals>.virtual_bend_circular at 0x7f7882089ee0>, 'bend_euler': <function virtual_bend_euler_factory.<locals>.bend_euler at 0x7f788208a160>, 'virtual_straight': <function virtual_straight_factory.<locals>.virtual_straight at 0x7f788208a3e0>, 'bend_circular_all_angle': <function bend_circular_all_angle at 0x7f7877fe2ac0>, 'bend_euler_all_angle': <function bend_euler_all_angle at 0x7f7877fe3600>, 'straight_all_angle': <function straight_all_angle at 0x7f7877e6be20>}, kcells={0: Unnamed_0: ports [], 2 instances, 1: mmi1x2_WNone_WT1_LT10_L_4e0f7121: ports ['o1', 'o2', 'o3'], 0 instances, 2: taper_L10_W0p5_W1_LNone_456c7208: ports ['o1', 'o2'], 0 instances, 3: straight_L5p5_N2_CSxs_5_d3ec67bc: ports ['o1', 'o2'], 0 instances, 4: Unnamed_4: ports [], 6 instances, 5: bend_euler_R10_A90_P0p5_2f1f5c6d: ports ['o1', 'o2'], 0 instances, 6: straight_L29p375_N2_CSs_6ed2bfdd: ports ['o1', 'o2'], 0 instances, 7: straight_L54p5_N2_CSstrip_WNone: ports ['o1', 'o2'], 0 instances}, layers=<aenum 'LAYER'>, infos=LayerInfos(), layer_stack=LayerStack(layers={}), netlist_layer_mapping={}, sparameters_path=None, interconnect_cml_path=None, constants=Constants(), rename_function=<function rename_clockwise_multi at 0x7f788d99f240>, info=Info(), settings=KCellSettings(version='0.23.2', klayout_version='0.29.11', meta_format='v3'), future_cell_name=None, decorators=<kfactory.decorators.Decorators object at 0x7f788d43c490>) function_name='bend_euler' basename=None boundary=None insts=<gdsfactory.component.ComponentReferences object at 0x7f7860767550> size_info=<kfactory.kcell.SizeInfo object at 0x7f7860dd0b10> dsize_info=<kfactory.kcell.DSizeInfo object at 0x7f78750f7890> routes={}, Unnamed_4: ports ['o1', 'o2'], vinsts=[] info=Info(length=29.375, width=0.5, route_info_type='strip', route_info_length=29.375, route_info_weight=29.375, route_info_strip_length=29.375) kcl=KCLayout(name='DEFAULT', layout=<klayout.dbcore.Layout object at 0x7f788d420230>, layer_enclosures=LayerEnclosureModel(root={'78687732': LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure')}), cross_sections={'78687732_500': SymmetricalCrossSection(width=500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_500'), '78687732_1000': SymmetricalCrossSection(width=1000, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_1000'), '78687732_2500': SymmetricalCrossSection(width=2500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_2500')}, enclosure=KCellEnclosure(enclosures=LayerEnclosureCollection(enclosures=[])), library=<klayout.dbcore.Library object at 0x7f788d4202d0>, factories={'taper': <function taper at 0x7f7877e08540>, 'bend_s_bezier': <function bend_s_bezier_factory.<locals>.bend_s_bezier at 0x7f7883695e40>, 'bend_circular': <function bend_circular at 0x7f7877fe2980>, 'bend_euler': <function bend_euler at 0x7f7877fe3380>, 'bend_s_euler': <function bend_s_euler_factory.<locals>.bend_s_euler at 0x7f7882088fe0>, 'straight': <function straight at 0x7f7877e6bce0>, 'rotate': <function rotate at 0x7f7880381120>, 'from_image': <function from_image at 0x7f78802cf600>, 'floorplan_with_block_letters': <function floorplan_with_block_letters at 0x7f7877f5dd00>, 'bend_circular_heater': <function bend_circular_heater at 0x7f7877fe2c00>, 'bend_euler_s': <function bend_euler_s at 0x7f7877fe3240>, 'bezier': <function bezier at 0x7f7877fe3920>, 'bend_s': <function bend_s at 0x7f7877fe3b00>, 'add_fiber_array_optical_south_electrical_north': <function add_fiber_array_optical_south_electrical_north at 0x7f7877fe3d80>, 'ramp': <function ramp at 0x7f7877e082c0>, 'taper_strip_to_ridge': <function taper_strip_to_ridge at 0x7f7877e085e0>, 'taper_strip_to_ridge_trenches': <function taper_strip_to_ridge_trenches at 0x7f7877e08860>, 'taper_sc_nc': <function taper_sc_nc at 0x7f7877e089a0>, 'taper_adiabatic': <function taper_adiabatic at 0x7f7877e08cc0>, 'taper_cross_section': <function taper_cross_section at 0x7f7877e08ea0>, 'taper_from_csv': <function taper_from_csv at 0x7f7877e09080>, 'taper_parabolic': <function taper_parabolic at 0x7f7877e091c0>, 'add_termination': <function add_termination at 0x7f7877fe3ec0>, 'add_trenches': <function add_trenches at 0x7f7877e08fe0>, 'array': <function array at 0x7f7877e093a0>, 'copy_layers': <function copy_layers at 0x7f7877e098a0>, 'extend_ports_list': <function extend_ports_list at 0x7f7877e099e0>, 'extend_ports': <function extend_ports at 0x7f7877e09d00>, 'pack_doe': <function pack_doe at 0x7f7877e0a520>, 'pack_doe_grid': <function pack_doe_grid at 0x7f7877e0a660>, 'splitter_chain': <function splitter_chain at 0x7f7877e0a7a0>, 'mzi': <function mzi at 0x7f7877e0ad40>, 'mzi_lattice': <function mzi_lattice at 0x7f7877e0b060>, 'mzi_lattice_mmi': <function mzi_lattice_mmi at 0x7f7877e0b1a0>, 'mzi_pads_center': <function mzi_pads_center at 0x7f7877e0b420>, 'mzit': <function mzit at 0x7f7877e0b600>, 'mzit_lattice': <function mzit_lattice at 0x7f7877e0b740>, 'splitter_tree': <function splitter_tree at 0x7f7877e0b2e0>, 'coupler_symmetric': <function coupler_symmetric at 0x7f7877e0b920>, 'coupler_straight': <function coupler_straight at 0x7f7877e0ba60>, 'coupler': <function coupler at 0x7f7877e0bba0>, 'coupler90': <function coupler90 at 0x7f7877e0bd80>, 'coupler90bend': <function coupler90bend at 0x7f7877e0be20>, 'coupler_adiabatic': <function coupler_adiabatic at 0x7f7877e38180>, 'coupler_asymmetric': <function coupler_asymmetric at 0x7f7877e38400>, 'coupler_bent_half': <function coupler_bent_half at 0x7f7877e38720>, 'coupler_bent': <function coupler_bent at 0x7f7877e38860>, 'coupler_broadband': <function coupler_broadband at 0x7f7877e38ae0>, 'coupler_full': <function coupler_full at 0x7f7877e38cc0>, 'coupler_ring': <function coupler_ring at 0x7f7877e38f40>, 'coupler_straight_asymmetric': <function coupler_straight_asymmetric at 0x7f7877e391c0>, 'align_wafer': <function align_wafer at 0x7f7877e39580>, 'add_frame': <function add_frame at 0x7f7877e39620>, 'die': <function die at 0x7f7877e39940>, 'die_with_pads': <function die_with_pads at 0x7f7877e39b20>, 'seal_ring': <function seal_ring at 0x7f7877e39d00>, 'seal_ring_segmented': <function seal_ring_segmented at 0x7f7877e39e40>, 'wafer': <function wafer at 0x7f7877e3a020>, 'free_propagation_region': <function free_propagation_region at 0x7f7877e3a480>, 'awg': <function awg at 0x7f7877e3a520>, 'dbr_cell': <function dbr_cell at 0x7f7877e3a840>, 'dbr': <function dbr at 0x7f7877e3a980>, 'dbr_tapered': <function dbr_tapered at 0x7f7877e3ac00>, 'bbox': <function bbox at 0x7f7877e3b380>, 'C': <function C at 0x7f7877e3b560>, 'circle': <function circle at 0x7f7877e3b740>, 'compass': <function compass at 0x7f7877e3b9c0>, 'cross': <function cross at 0x7f7877e3bba0>, 'ellipse': <function ellipse at 0x7f7877e3bd80>, 'fiducial_squares': <function fiducial_squares at 0x7f7877e3bec0>, 'L': <function L at 0x7f7877e680e0>, 'nxn': <function nxn at 0x7f7877e682c0>, 'rectangle': <function rectangle at 0x7f7877e684a0>, 'rectangles': <function rectangles at 0x7f7877e685e0>, 'regular_polygon': <function regular_polygon at 0x7f7877e68720>, 'triangle': <function triangle at 0x7f7877e68900>, 'triangle2': <function triangle2 at 0x7f7877e68a40>, 'triangle4': <function triangle4 at 0x7f7877e68b80>, 'fiber': <function fiber at 0x7f7877e3af20>, 'fiber_array': <function fiber_array at 0x7f7877e68c20>, 'crossing_arm': <function crossing_arm at 0x7f7877e6b600>, 'crossing': <function crossing at 0x7f7877e6b740>, 'crossing_linear_taper': <function crossing_linear_taper at 0x7f7877e6b880>, 'crossing_etched': <function crossing_etched at 0x7f7877e6b9c0>, 'crossing45': <function crossing45 at 0x7f7877e6bb00>, 'straight_array': <function straight_array at 0x7f7877e6bf60>, 'wire_straight': <function wire_straight at 0x7f7877e9c0e0>, 'straight_heater_doped_rib': <function straight_heater_doped_rib at 0x7f7877e9c4a0>, 'straight_heater_doped_strip': <function straight_heater_doped_strip at 0x7f7877e9c680>, 'straight_heater_meander': <function straight_heater_meander at 0x7f7877e9c9a0>, 'via': <function via at 0x7f7877e9d1c0>, 'via_circular': <function via_circular at 0x7f7877e9d300>, 'via_chain': <function via_chain at 0x7f7877e9d620>, 'via_corner': <function via_corner at 0x7f7877e9d800>, 'via_stack': <function via_stack at 0x7f7877e9d9e0>, 'via_stack_corner45': <function via_stack_corner45 at 0x7f7877e9db20>, 'via_stack_corner45_extended': <function via_stack_corner45_extended at 0x7f7877e9dc60>, 'via_stack_with_offset': <function via_stack_with_offset at 0x7f7877e9dda0>, 'straight_heater_meander_doped': <function straight_heater_meander_doped at 0x7f7877e9cea0>, 'straight_heater_metal_undercut': <function straight_heater_metal_undercut at 0x7f7877e9dd00>, 'straight_heater_metal_simple': <function straight_heater_metal_simple at 0x7f7877e9e020>, 'straight_piecewise': <function straight_piecewise at 0x7f7877e9e160>, 'straight_pin': <function straight_pin at 0x7f7877e9e200>, 'straight_pin_slot': <function straight_pin_slot at 0x7f7877e9e480>, 'wire_corner': <function wire_corner at 0x7f7877e9e700>, 'wire_corner45': <function wire_corner45 at 0x7f7877e9e840>, 'wire_corner_sections': <function wire_corner_sections at 0x7f7877e9e8e0>, 'loop_mirror': <function loop_mirror at 0x7f7877e68ae0>, 'mode_converter': <function mode_converter at 0x7f7877ec4360>, 'polarization_splitter_rotator': <function polarization_splitter_rotator at 0x7f7877ec4680>, 'terminator': <function terminator at 0x7f7877ec4c20>, 'grating_coupler_array': <function grating_coupler_array at 0x7f7877ec4ea0>, 'grating_coupler_dual_pol': <function grating_coupler_dual_pol at 0x7f7877ec51c0>, 'grating_coupler_elliptical': <function grating_coupler_elliptical at 0x7f7877ec5800>, 'grating_coupler_elliptical_arbitrary': <function grating_coupler_elliptical_arbitrary at 0x7f7877ec5a80>, 'grating_coupler_elliptical_uniform': <function grating_coupler_elliptical_uniform at 0x7f7877ec5d00>, 'grating_coupler_elliptical_lumerical': <function grating_coupler_elliptical_lumerical at 0x7f7877ec5e40>, 'grating_coupler_elliptical_trenches': <function grating_coupler_elliptical_trenches at 0x7f7877ec5ee0>, 'grating_coupler_loss': <function grating_coupler_loss at 0x7f7877ec62a0>, 'grating_coupler_rectangular': <function grating_coupler_rectangular at 0x7f7877ec6480>, 'grating_coupler_rectangular_arbitrary': <function grating_coupler_rectangular_arbitrary at 0x7f7877ec6700>, 'grating_coupler_tree': <function grating_coupler_tree at 0x7f7877ec6980>, 'mmi': <function mmi at 0x7f7877ec6ca0>, 'mmi1x2': <function mmi1x2 at 0x7f7877ec6fc0>, 'mmi1x2_with_sbend': <function mmi1x2_with_sbend at 0x7f7877ec71a0>, 'mmi2x2': <function mmi2x2 at 0x7f7877ec74c0>, 'mmi2x2_with_sbend': <function mmi2x2_with_sbend at 0x7f7877ec7600>, 'mmi_90degree_hybrid': <function mmi_90degree_hybrid at 0x7f7877ec77e0>, 'mmi_tapered': <function mmi_tapered at 0x7f7877ec7b00>, 'pad': <function pad at 0x7f7877ec7d80>, 'pad_array': <function pad_array at 0x7f7877ec7f60>, 'pad_gsg_short': <function pad_gsg_short at 0x7f7877d002c0>, 'pads_shorted': <function pads_shorted at 0x7f7877d00540>, 'rectangle_with_slits': <function rectangle_with_slits at 0x7f7877d00680>, 'cavity': <function cavity at 0x7f7877d00900>, 'cdsem_all': <function cdsem_all at 0x7f7877d00b80>, 'cdsem_bend180': <function cdsem_bend180 at 0x7f7877d00d60>, 'cdsem_coupler': <function cdsem_coupler at 0x7f7877d00ea0>, 'cdsem_straight': <function cdsem_straight at 0x7f7877d011c0>, 'cdsem_straight_density': <function cdsem_straight_density at 0x7f7877d01300>, '_bendu_double': <function _bendu_double at 0x7f7877d01580>, '_straight_double': <function _straight_double at 0x7f7877d016c0>, 'cutback_2x2': <function cutback_2x2 at 0x7f7877d01800>, 'cutback_bend': <function cutback_bend at 0x7f7877d01bc0>, 'cutback_bend90': <function cutback_bend90 at 0x7f7877d01d00>, 'staircase': <function staircase at 0x7f7877d01e40>, 'cutback_bend180': <function cutback_bend180 at 0x7f7877d01f80>, 'cutback_component': <function cutback_component at 0x7f7877d020c0>, 'cutback_splitter': <function cutback_splitter at 0x7f7877d02480>, 'greek_cross': <function greek_cross at 0x7f7877d025c0>, 'greek_cross_with_pads': <function greek_cross_with_pads at 0x7f7877d02840>, 'litho_calipers': <function litho_calipers at 0x7f7877d02a20>, 'litho_ruler': <function litho_ruler at 0x7f7877d02d40>, 'litho_steps': <function litho_steps at 0x7f7877d02f20>, 'resistance_meander': <function resistance_meander at 0x7f7877d03060>, 'resistance_sheet': <function resistance_sheet at 0x7f7877d03240>, 'verniers': <function verniers at 0x7f7877d03420>, 'text': <function text at 0x7f7877d50180>, 'text_lines': <function text_lines at 0x7f7877d50360>, 'text_klayout': <function text_klayout at 0x7f7877d504a0>, 'text_freetype': <function text_freetype at 0x7f7877d507c0>, 'pixel_array': <function pixel_array at 0x7f7877d50a40>, 'text_rectangular': <function text_rectangular at 0x7f7877d50b80>, 'text_rectangular_multi_layer': <function text_rectangular_multi_layer at 0x7f7877d50cc0>, 'pixel': <function pixel at 0x7f7877d03740>, 'qrcode': <function qrcode at 0x7f7877d509a0>, 'version_stamp': <function version_stamp at 0x7f7877d50d60>, 'disk': <function disk at 0x7f7877d51300>, 'disk_heater': <function disk_heater at 0x7f7877d51440>, 'ring': <function ring at 0x7f7877d516c0>, 'ring_crow': <function ring_crow at 0x7f7877d518a0>, 'ring_crow_couplers': <function ring_crow_couplers at 0x7f7877d519e0>, 'ring_double': <function ring_double at 0x7f7877d51bc0>, 'ring_double_bend_coupler': <function ring_double_bend_coupler at 0x7f7877d51ee0>, 'ring_double_heater': <function ring_double_heater at 0x7f7877d52020>, 'ring_double_pn': <function ring_double_pn at 0x7f7877d52340>, 'ring_single_pn': <function ring_single_pn at 0x7f7877d52480>, 'ring_single': <function ring_single at 0x7f7877d52660>, 'ring_single_array': <function ring_single_array at 0x7f7877d527a0>, 'coupler_bend': <function coupler_bend at 0x7f7877d528e0>, 'coupler_ring_bend': <function coupler_ring_bend at 0x7f7877d52a20>, 'ring_single_bend_coupler': <function ring_single_bend_coupler at 0x7f7877d52b60>, 'ring_single_dut': <function ring_single_dut at 0x7f7877d52d40>, 'delay_snake': <function delay_snake at 0x7f7877d52fc0>, 'delay_snake2': <function delay_snake2 at 0x7f7877d531a0>, 'delay_snake_sbend': <function delay_snake_sbend at 0x7f7877d53420>, 'spiral': <function spiral at 0x7f7877d536a0>, 'spiral_double': <function spiral_double at 0x7f7877d53880>, 'spiral_racetrack': <function spiral_racetrack at 0x7f7877d53b00>, 'spiral_racetrack_fixed_length': <function spiral_racetrack_fixed_length at 0x7f7877d53c40>, 'spiral_racetrack_heater_metal': <function spiral_racetrack_heater_metal at 0x7f7877d53e20>, 'spiral_racetrack_heater_doped': <function spiral_racetrack_heater_doped at 0x7f7877d53f60>, 'spiral_inductor': <function spiral_inductor at 0x7f7877d900e0>, 'hline': <function hline at 0x7f7877d90360>, 'optimal_90deg': <function optimal_90deg at 0x7f7877d904a0>, 'optimal_hairpin': <function optimal_hairpin at 0x7f7877d907c0>, 'optimal_step': <function optimal_step at 0x7f7877d90900>, 'snspd': <function snspd at 0x7f7877d90ae0>, 'interdigital_capacitor': <function interdigital_capacitor at 0x7f7877d90cc0>, 'ge_detector_straight_si_contacts': <function ge_detector_straight_si_contacts at 0x7f7877d90f40>, 'edge_coupler_silicon': <function edge_coupler_silicon at 0x7f7877d911c0>, 'edge_coupler_array': <function edge_coupler_array at 0x7f7877d91300>, 'edge_coupler_array_with_loopback': <function edge_coupler_array_with_loopback at 0x7f7877d91440>}, virtual_factories={'virtual_bend_circular': <function virtual_bend_circular_factory.<locals>.virtual_bend_circular at 0x7f7882089ee0>, 'bend_euler': <function virtual_bend_euler_factory.<locals>.bend_euler at 0x7f788208a160>, 'virtual_straight': <function virtual_straight_factory.<locals>.virtual_straight at 0x7f788208a3e0>, 'bend_circular_all_angle': <function bend_circular_all_angle at 0x7f7877fe2ac0>, 'bend_euler_all_angle': <function bend_euler_all_angle at 0x7f7877fe3600>, 'straight_all_angle': <function straight_all_angle at 0x7f7877e6be20>}, kcells={0: Unnamed_0: ports [], 2 instances, 1: mmi1x2_WNone_WT1_LT10_L_4e0f7121: ports ['o1', 'o2', 'o3'], 0 instances, 2: taper_L10_W0p5_W1_LNone_456c7208: ports ['o1', 'o2'], 0 instances, 3: straight_L5p5_N2_CSxs_5_d3ec67bc: ports ['o1', 'o2'], 0 instances, 4: Unnamed_4: ports [], 6 instances, 5: bend_euler_R10_A90_P0p5_2f1f5c6d: ports ['o1', 'o2'], 0 instances, 6: straight_L29p375_N2_CSs_6ed2bfdd: ports ['o1', 'o2'], 0 instances, 7: straight_L54p5_N2_CSstrip_WNone: ports ['o1', 'o2'], 0 instances}, layers=<aenum 'LAYER'>, infos=LayerInfos(), layer_stack=LayerStack(layers={}), netlist_layer_mapping={}, sparameters_path=None, interconnect_cml_path=None, constants=Constants(), rename_function=<function rename_clockwise_multi at 0x7f788d99f240>, info=Info(), settings=KCellSettings(version='0.23.2', klayout_version='0.29.11', meta_format='v3'), future_cell_name=None, decorators=<kfactory.decorators.Decorators object at 0x7f788d43c490>) function_name='straight' basename=None boundary=None insts=<gdsfactory.component.ComponentReferences object at 0x7f7860780250> size_info=<kfactory.kcell.SizeInfo object at 0x7f786119c510> dsize_info=<kfactory.kcell.DSizeInfo object at 0x7f7863befc10> routes={}, Unnamed_4: ports ['o1', 'o2'], vinsts=[] info=Info(length=16.637, dy=10.0, min_bend_radius=7.061, radius=10.0, width=0.5, route_info_type='strip', route_info_length=16.637, route_info_weight=16.637, route_info_strip_length=16.637, route_info_n_bend_90=1.0, route_info_min_bend_radius=7.061) kcl=KCLayout(name='DEFAULT', layout=<klayout.dbcore.Layout object at 0x7f788d420230>, layer_enclosures=LayerEnclosureModel(root={'78687732': LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure')}), cross_sections={'78687732_500': SymmetricalCrossSection(width=500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_500'), '78687732_1000': SymmetricalCrossSection(width=1000, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_1000'), '78687732_2500': SymmetricalCrossSection(width=2500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_2500')}, enclosure=KCellEnclosure(enclosures=LayerEnclosureCollection(enclosures=[])), library=<klayout.dbcore.Library object at 0x7f788d4202d0>, factories={'taper': <function taper at 0x7f7877e08540>, 'bend_s_bezier': <function bend_s_bezier_factory.<locals>.bend_s_bezier at 0x7f7883695e40>, 'bend_circular': <function bend_circular at 0x7f7877fe2980>, 'bend_euler': <function bend_euler at 0x7f7877fe3380>, 'bend_s_euler': <function bend_s_euler_factory.<locals>.bend_s_euler at 0x7f7882088fe0>, 'straight': <function straight at 0x7f7877e6bce0>, 'rotate': <function rotate at 0x7f7880381120>, 'from_image': <function from_image at 0x7f78802cf600>, 'floorplan_with_block_letters': <function floorplan_with_block_letters at 0x7f7877f5dd00>, 'bend_circular_heater': <function bend_circular_heater at 0x7f7877fe2c00>, 'bend_euler_s': <function bend_euler_s at 0x7f7877fe3240>, 'bezier': <function bezier at 0x7f7877fe3920>, 'bend_s': <function bend_s at 0x7f7877fe3b00>, 'add_fiber_array_optical_south_electrical_north': <function add_fiber_array_optical_south_electrical_north at 0x7f7877fe3d80>, 'ramp': <function ramp at 0x7f7877e082c0>, 'taper_strip_to_ridge': <function taper_strip_to_ridge at 0x7f7877e085e0>, 'taper_strip_to_ridge_trenches': <function taper_strip_to_ridge_trenches at 0x7f7877e08860>, 'taper_sc_nc': <function taper_sc_nc at 0x7f7877e089a0>, 'taper_adiabatic': <function taper_adiabatic at 0x7f7877e08cc0>, 'taper_cross_section': <function taper_cross_section at 0x7f7877e08ea0>, 'taper_from_csv': <function taper_from_csv at 0x7f7877e09080>, 'taper_parabolic': <function taper_parabolic at 0x7f7877e091c0>, 'add_termination': <function add_termination at 0x7f7877fe3ec0>, 'add_trenches': <function add_trenches at 0x7f7877e08fe0>, 'array': <function array at 0x7f7877e093a0>, 'copy_layers': <function copy_layers at 0x7f7877e098a0>, 'extend_ports_list': <function extend_ports_list at 0x7f7877e099e0>, 'extend_ports': <function extend_ports at 0x7f7877e09d00>, 'pack_doe': <function pack_doe at 0x7f7877e0a520>, 'pack_doe_grid': <function pack_doe_grid at 0x7f7877e0a660>, 'splitter_chain': <function splitter_chain at 0x7f7877e0a7a0>, 'mzi': <function mzi at 0x7f7877e0ad40>, 'mzi_lattice': <function mzi_lattice at 0x7f7877e0b060>, 'mzi_lattice_mmi': <function mzi_lattice_mmi at 0x7f7877e0b1a0>, 'mzi_pads_center': <function mzi_pads_center at 0x7f7877e0b420>, 'mzit': <function mzit at 0x7f7877e0b600>, 'mzit_lattice': <function mzit_lattice at 0x7f7877e0b740>, 'splitter_tree': <function splitter_tree at 0x7f7877e0b2e0>, 'coupler_symmetric': <function coupler_symmetric at 0x7f7877e0b920>, 'coupler_straight': <function coupler_straight at 0x7f7877e0ba60>, 'coupler': <function coupler at 0x7f7877e0bba0>, 'coupler90': <function coupler90 at 0x7f7877e0bd80>, 'coupler90bend': <function coupler90bend at 0x7f7877e0be20>, 'coupler_adiabatic': <function coupler_adiabatic at 0x7f7877e38180>, 'coupler_asymmetric': <function coupler_asymmetric at 0x7f7877e38400>, 'coupler_bent_half': <function coupler_bent_half at 0x7f7877e38720>, 'coupler_bent': <function coupler_bent at 0x7f7877e38860>, 'coupler_broadband': <function coupler_broadband at 0x7f7877e38ae0>, 'coupler_full': <function coupler_full at 0x7f7877e38cc0>, 'coupler_ring': <function coupler_ring at 0x7f7877e38f40>, 'coupler_straight_asymmetric': <function coupler_straight_asymmetric at 0x7f7877e391c0>, 'align_wafer': <function align_wafer at 0x7f7877e39580>, 'add_frame': <function add_frame at 0x7f7877e39620>, 'die': <function die at 0x7f7877e39940>, 'die_with_pads': <function die_with_pads at 0x7f7877e39b20>, 'seal_ring': <function seal_ring at 0x7f7877e39d00>, 'seal_ring_segmented': <function seal_ring_segmented at 0x7f7877e39e40>, 'wafer': <function wafer at 0x7f7877e3a020>, 'free_propagation_region': <function free_propagation_region at 0x7f7877e3a480>, 'awg': <function awg at 0x7f7877e3a520>, 'dbr_cell': <function dbr_cell at 0x7f7877e3a840>, 'dbr': <function dbr at 0x7f7877e3a980>, 'dbr_tapered': <function dbr_tapered at 0x7f7877e3ac00>, 'bbox': <function bbox at 0x7f7877e3b380>, 'C': <function C at 0x7f7877e3b560>, 'circle': <function circle at 0x7f7877e3b740>, 'compass': <function compass at 0x7f7877e3b9c0>, 'cross': <function cross at 0x7f7877e3bba0>, 'ellipse': <function ellipse at 0x7f7877e3bd80>, 'fiducial_squares': <function fiducial_squares at 0x7f7877e3bec0>, 'L': <function L at 0x7f7877e680e0>, 'nxn': <function nxn at 0x7f7877e682c0>, 'rectangle': <function rectangle at 0x7f7877e684a0>, 'rectangles': <function rectangles at 0x7f7877e685e0>, 'regular_polygon': <function regular_polygon at 0x7f7877e68720>, 'triangle': <function triangle at 0x7f7877e68900>, 'triangle2': <function triangle2 at 0x7f7877e68a40>, 'triangle4': <function triangle4 at 0x7f7877e68b80>, 'fiber': <function fiber at 0x7f7877e3af20>, 'fiber_array': <function fiber_array at 0x7f7877e68c20>, 'crossing_arm': <function crossing_arm at 0x7f7877e6b600>, 'crossing': <function crossing at 0x7f7877e6b740>, 'crossing_linear_taper': <function crossing_linear_taper at 0x7f7877e6b880>, 'crossing_etched': <function crossing_etched at 0x7f7877e6b9c0>, 'crossing45': <function crossing45 at 0x7f7877e6bb00>, 'straight_array': <function straight_array at 0x7f7877e6bf60>, 'wire_straight': <function wire_straight at 0x7f7877e9c0e0>, 'straight_heater_doped_rib': <function straight_heater_doped_rib at 0x7f7877e9c4a0>, 'straight_heater_doped_strip': <function straight_heater_doped_strip at 0x7f7877e9c680>, 'straight_heater_meander': <function straight_heater_meander at 0x7f7877e9c9a0>, 'via': <function via at 0x7f7877e9d1c0>, 'via_circular': <function via_circular at 0x7f7877e9d300>, 'via_chain': <function via_chain at 0x7f7877e9d620>, 'via_corner': <function via_corner at 0x7f7877e9d800>, 'via_stack': <function via_stack at 0x7f7877e9d9e0>, 'via_stack_corner45': <function via_stack_corner45 at 0x7f7877e9db20>, 'via_stack_corner45_extended': <function via_stack_corner45_extended at 0x7f7877e9dc60>, 'via_stack_with_offset': <function via_stack_with_offset at 0x7f7877e9dda0>, 'straight_heater_meander_doped': <function straight_heater_meander_doped at 0x7f7877e9cea0>, 'straight_heater_metal_undercut': <function straight_heater_metal_undercut at 0x7f7877e9dd00>, 'straight_heater_metal_simple': <function straight_heater_metal_simple at 0x7f7877e9e020>, 'straight_piecewise': <function straight_piecewise at 0x7f7877e9e160>, 'straight_pin': <function straight_pin at 0x7f7877e9e200>, 'straight_pin_slot': <function straight_pin_slot at 0x7f7877e9e480>, 'wire_corner': <function wire_corner at 0x7f7877e9e700>, 'wire_corner45': <function wire_corner45 at 0x7f7877e9e840>, 'wire_corner_sections': <function wire_corner_sections at 0x7f7877e9e8e0>, 'loop_mirror': <function loop_mirror at 0x7f7877e68ae0>, 'mode_converter': <function mode_converter at 0x7f7877ec4360>, 'polarization_splitter_rotator': <function polarization_splitter_rotator at 0x7f7877ec4680>, 'terminator': <function terminator at 0x7f7877ec4c20>, 'grating_coupler_array': <function grating_coupler_array at 0x7f7877ec4ea0>, 'grating_coupler_dual_pol': <function grating_coupler_dual_pol at 0x7f7877ec51c0>, 'grating_coupler_elliptical': <function grating_coupler_elliptical at 0x7f7877ec5800>, 'grating_coupler_elliptical_arbitrary': <function grating_coupler_elliptical_arbitrary at 0x7f7877ec5a80>, 'grating_coupler_elliptical_uniform': <function grating_coupler_elliptical_uniform at 0x7f7877ec5d00>, 'grating_coupler_elliptical_lumerical': <function grating_coupler_elliptical_lumerical at 0x7f7877ec5e40>, 'grating_coupler_elliptical_trenches': <function grating_coupler_elliptical_trenches at 0x7f7877ec5ee0>, 'grating_coupler_loss': <function grating_coupler_loss at 0x7f7877ec62a0>, 'grating_coupler_rectangular': <function grating_coupler_rectangular at 0x7f7877ec6480>, 'grating_coupler_rectangular_arbitrary': <function grating_coupler_rectangular_arbitrary at 0x7f7877ec6700>, 'grating_coupler_tree': <function grating_coupler_tree at 0x7f7877ec6980>, 'mmi': <function mmi at 0x7f7877ec6ca0>, 'mmi1x2': <function mmi1x2 at 0x7f7877ec6fc0>, 'mmi1x2_with_sbend': <function mmi1x2_with_sbend at 0x7f7877ec71a0>, 'mmi2x2': <function mmi2x2 at 0x7f7877ec74c0>, 'mmi2x2_with_sbend': <function mmi2x2_with_sbend at 0x7f7877ec7600>, 'mmi_90degree_hybrid': <function mmi_90degree_hybrid at 0x7f7877ec77e0>, 'mmi_tapered': <function mmi_tapered at 0x7f7877ec7b00>, 'pad': <function pad at 0x7f7877ec7d80>, 'pad_array': <function pad_array at 0x7f7877ec7f60>, 'pad_gsg_short': <function pad_gsg_short at 0x7f7877d002c0>, 'pads_shorted': <function pads_shorted at 0x7f7877d00540>, 'rectangle_with_slits': <function rectangle_with_slits at 0x7f7877d00680>, 'cavity': <function cavity at 0x7f7877d00900>, 'cdsem_all': <function cdsem_all at 0x7f7877d00b80>, 'cdsem_bend180': <function cdsem_bend180 at 0x7f7877d00d60>, 'cdsem_coupler': <function cdsem_coupler at 0x7f7877d00ea0>, 'cdsem_straight': <function cdsem_straight at 0x7f7877d011c0>, 'cdsem_straight_density': <function cdsem_straight_density at 0x7f7877d01300>, '_bendu_double': <function _bendu_double at 0x7f7877d01580>, '_straight_double': <function _straight_double at 0x7f7877d016c0>, 'cutback_2x2': <function cutback_2x2 at 0x7f7877d01800>, 'cutback_bend': <function cutback_bend at 0x7f7877d01bc0>, 'cutback_bend90': <function cutback_bend90 at 0x7f7877d01d00>, 'staircase': <function staircase at 0x7f7877d01e40>, 'cutback_bend180': <function cutback_bend180 at 0x7f7877d01f80>, 'cutback_component': <function cutback_component at 0x7f7877d020c0>, 'cutback_splitter': <function cutback_splitter at 0x7f7877d02480>, 'greek_cross': <function greek_cross at 0x7f7877d025c0>, 'greek_cross_with_pads': <function greek_cross_with_pads at 0x7f7877d02840>, 'litho_calipers': <function litho_calipers at 0x7f7877d02a20>, 'litho_ruler': <function litho_ruler at 0x7f7877d02d40>, 'litho_steps': <function litho_steps at 0x7f7877d02f20>, 'resistance_meander': <function resistance_meander at 0x7f7877d03060>, 'resistance_sheet': <function resistance_sheet at 0x7f7877d03240>, 'verniers': <function verniers at 0x7f7877d03420>, 'text': <function text at 0x7f7877d50180>, 'text_lines': <function text_lines at 0x7f7877d50360>, 'text_klayout': <function text_klayout at 0x7f7877d504a0>, 'text_freetype': <function text_freetype at 0x7f7877d507c0>, 'pixel_array': <function pixel_array at 0x7f7877d50a40>, 'text_rectangular': <function text_rectangular at 0x7f7877d50b80>, 'text_rectangular_multi_layer': <function text_rectangular_multi_layer at 0x7f7877d50cc0>, 'pixel': <function pixel at 0x7f7877d03740>, 'qrcode': <function qrcode at 0x7f7877d509a0>, 'version_stamp': <function version_stamp at 0x7f7877d50d60>, 'disk': <function disk at 0x7f7877d51300>, 'disk_heater': <function disk_heater at 0x7f7877d51440>, 'ring': <function ring at 0x7f7877d516c0>, 'ring_crow': <function ring_crow at 0x7f7877d518a0>, 'ring_crow_couplers': <function ring_crow_couplers at 0x7f7877d519e0>, 'ring_double': <function ring_double at 0x7f7877d51bc0>, 'ring_double_bend_coupler': <function ring_double_bend_coupler at 0x7f7877d51ee0>, 'ring_double_heater': <function ring_double_heater at 0x7f7877d52020>, 'ring_double_pn': <function ring_double_pn at 0x7f7877d52340>, 'ring_single_pn': <function ring_single_pn at 0x7f7877d52480>, 'ring_single': <function ring_single at 0x7f7877d52660>, 'ring_single_array': <function ring_single_array at 0x7f7877d527a0>, 'coupler_bend': <function coupler_bend at 0x7f7877d528e0>, 'coupler_ring_bend': <function coupler_ring_bend at 0x7f7877d52a20>, 'ring_single_bend_coupler': <function ring_single_bend_coupler at 0x7f7877d52b60>, 'ring_single_dut': <function ring_single_dut at 0x7f7877d52d40>, 'delay_snake': <function delay_snake at 0x7f7877d52fc0>, 'delay_snake2': <function delay_snake2 at 0x7f7877d531a0>, 'delay_snake_sbend': <function delay_snake_sbend at 0x7f7877d53420>, 'spiral': <function spiral at 0x7f7877d536a0>, 'spiral_double': <function spiral_double at 0x7f7877d53880>, 'spiral_racetrack': <function spiral_racetrack at 0x7f7877d53b00>, 'spiral_racetrack_fixed_length': <function spiral_racetrack_fixed_length at 0x7f7877d53c40>, 'spiral_racetrack_heater_metal': <function spiral_racetrack_heater_metal at 0x7f7877d53e20>, 'spiral_racetrack_heater_doped': <function spiral_racetrack_heater_doped at 0x7f7877d53f60>, 'spiral_inductor': <function spiral_inductor at 0x7f7877d900e0>, 'hline': <function hline at 0x7f7877d90360>, 'optimal_90deg': <function optimal_90deg at 0x7f7877d904a0>, 'optimal_hairpin': <function optimal_hairpin at 0x7f7877d907c0>, 'optimal_step': <function optimal_step at 0x7f7877d90900>, 'snspd': <function snspd at 0x7f7877d90ae0>, 'interdigital_capacitor': <function interdigital_capacitor at 0x7f7877d90cc0>, 'ge_detector_straight_si_contacts': <function ge_detector_straight_si_contacts at 0x7f7877d90f40>, 'edge_coupler_silicon': <function edge_coupler_silicon at 0x7f7877d911c0>, 'edge_coupler_array': <function edge_coupler_array at 0x7f7877d91300>, 'edge_coupler_array_with_loopback': <function edge_coupler_array_with_loopback at 0x7f7877d91440>}, virtual_factories={'virtual_bend_circular': <function virtual_bend_circular_factory.<locals>.virtual_bend_circular at 0x7f7882089ee0>, 'bend_euler': <function virtual_bend_euler_factory.<locals>.bend_euler at 0x7f788208a160>, 'virtual_straight': <function virtual_straight_factory.<locals>.virtual_straight at 0x7f788208a3e0>, 'bend_circular_all_angle': <function bend_circular_all_angle at 0x7f7877fe2ac0>, 'bend_euler_all_angle': <function bend_euler_all_angle at 0x7f7877fe3600>, 'straight_all_angle': <function straight_all_angle at 0x7f7877e6be20>}, kcells={0: Unnamed_0: ports [], 2 instances, 1: mmi1x2_WNone_WT1_LT10_L_4e0f7121: ports ['o1', 'o2', 'o3'], 0 instances, 2: taper_L10_W0p5_W1_LNone_456c7208: ports ['o1', 'o2'], 0 instances, 3: straight_L5p5_N2_CSxs_5_d3ec67bc: ports ['o1', 'o2'], 0 instances, 4: Unnamed_4: ports [], 6 instances, 5: bend_euler_R10_A90_P0p5_2f1f5c6d: ports ['o1', 'o2'], 0 instances, 6: straight_L29p375_N2_CSs_6ed2bfdd: ports ['o1', 'o2'], 0 instances, 7: straight_L54p5_N2_CSstrip_WNone: ports ['o1', 'o2'], 0 instances}, layers=<aenum 'LAYER'>, infos=LayerInfos(), layer_stack=LayerStack(layers={}), netlist_layer_mapping={}, sparameters_path=None, interconnect_cml_path=None, constants=Constants(), rename_function=<function rename_clockwise_multi at 0x7f788d99f240>, info=Info(), settings=KCellSettings(version='0.23.2', klayout_version='0.29.11', meta_format='v3'), future_cell_name=None, decorators=<kfactory.decorators.Decorators object at 0x7f788d43c490>) function_name='bend_euler' basename=None boundary=None insts=<gdsfactory.component.ComponentReferences object at 0x7f7860767550> size_info=<kfactory.kcell.SizeInfo object at 0x7f7860dd0b10> dsize_info=<kfactory.kcell.DSizeInfo object at 0x7f78750f7890> routes={}, Unnamed_4: ports ['o1', 'o2'], vinsts=[] info=Info(length=54.5, width=0.5, route_info_type='strip', route_info_length=54.5, route_info_weight=54.5, route_info_strip_length=54.5) kcl=KCLayout(name='DEFAULT', layout=<klayout.dbcore.Layout object at 0x7f788d420230>, layer_enclosures=LayerEnclosureModel(root={'78687732': LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure')}), cross_sections={'78687732_500': SymmetricalCrossSection(width=500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_500'), '78687732_1000': SymmetricalCrossSection(width=1000, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_1000'), '78687732_2500': SymmetricalCrossSection(width=2500, enclosure=LayerEnclosure(layer_sections={}, main_layer=WG (1/0), yaml_tag='!Enclosure'), name='78687732_2500')}, enclosure=KCellEnclosure(enclosures=LayerEnclosureCollection(enclosures=[])), library=<klayout.dbcore.Library object at 0x7f788d4202d0>, factories={'taper': <function taper at 0x7f7877e08540>, 'bend_s_bezier': <function bend_s_bezier_factory.<locals>.bend_s_bezier at 0x7f7883695e40>, 'bend_circular': <function bend_circular at 0x7f7877fe2980>, 'bend_euler': <function bend_euler at 0x7f7877fe3380>, 'bend_s_euler': <function bend_s_euler_factory.<locals>.bend_s_euler at 0x7f7882088fe0>, 'straight': <function straight at 0x7f7877e6bce0>, 'rotate': <function rotate at 0x7f7880381120>, 'from_image': <function from_image at 0x7f78802cf600>, 'floorplan_with_block_letters': <function floorplan_with_block_letters at 0x7f7877f5dd00>, 'bend_circular_heater': <function bend_circular_heater at 0x7f7877fe2c00>, 'bend_euler_s': <function bend_euler_s at 0x7f7877fe3240>, 'bezier': <function bezier at 0x7f7877fe3920>, 'bend_s': <function bend_s at 0x7f7877fe3b00>, 'add_fiber_array_optical_south_electrical_north': <function add_fiber_array_optical_south_electrical_north at 0x7f7877fe3d80>, 'ramp': <function ramp at 0x7f7877e082c0>, 'taper_strip_to_ridge': <function taper_strip_to_ridge at 0x7f7877e085e0>, 'taper_strip_to_ridge_trenches': <function taper_strip_to_ridge_trenches at 0x7f7877e08860>, 'taper_sc_nc': <function taper_sc_nc at 0x7f7877e089a0>, 'taper_adiabatic': <function taper_adiabatic at 0x7f7877e08cc0>, 'taper_cross_section': <function taper_cross_section at 0x7f7877e08ea0>, 'taper_from_csv': <function taper_from_csv at 0x7f7877e09080>, 'taper_parabolic': <function taper_parabolic at 0x7f7877e091c0>, 'add_termination': <function add_termination at 0x7f7877fe3ec0>, 'add_trenches': <function add_trenches at 0x7f7877e08fe0>, 'array': <function array at 0x7f7877e093a0>, 'copy_layers': <function copy_layers at 0x7f7877e098a0>, 'extend_ports_list': <function extend_ports_list at 0x7f7877e099e0>, 'extend_ports': <function extend_ports at 0x7f7877e09d00>, 'pack_doe': <function pack_doe at 0x7f7877e0a520>, 'pack_doe_grid': <function pack_doe_grid at 0x7f7877e0a660>, 'splitter_chain': <function splitter_chain at 0x7f7877e0a7a0>, 'mzi': <function mzi at 0x7f7877e0ad40>, 'mzi_lattice': <function mzi_lattice at 0x7f7877e0b060>, 'mzi_lattice_mmi': <function mzi_lattice_mmi at 0x7f7877e0b1a0>, 'mzi_pads_center': <function mzi_pads_center at 0x7f7877e0b420>, 'mzit': <function mzit at 0x7f7877e0b600>, 'mzit_lattice': <function mzit_lattice at 0x7f7877e0b740>, 'splitter_tree': <function splitter_tree at 0x7f7877e0b2e0>, 'coupler_symmetric': <function coupler_symmetric at 0x7f7877e0b920>, 'coupler_straight': <function coupler_straight at 0x7f7877e0ba60>, 'coupler': <function coupler at 0x7f7877e0bba0>, 'coupler90': <function coupler90 at 0x7f7877e0bd80>, 'coupler90bend': <function coupler90bend at 0x7f7877e0be20>, 'coupler_adiabatic': <function coupler_adiabatic at 0x7f7877e38180>, 'coupler_asymmetric': <function coupler_asymmetric at 0x7f7877e38400>, 'coupler_bent_half': <function coupler_bent_half at 0x7f7877e38720>, 'coupler_bent': <function coupler_bent at 0x7f7877e38860>, 'coupler_broadband': <function coupler_broadband at 0x7f7877e38ae0>, 'coupler_full': <function coupler_full at 0x7f7877e38cc0>, 'coupler_ring': <function coupler_ring at 0x7f7877e38f40>, 'coupler_straight_asymmetric': <function coupler_straight_asymmetric at 0x7f7877e391c0>, 'align_wafer': <function align_wafer at 0x7f7877e39580>, 'add_frame': <function add_frame at 0x7f7877e39620>, 'die': <function die at 0x7f7877e39940>, 'die_with_pads': <function die_with_pads at 0x7f7877e39b20>, 'seal_ring': <function seal_ring at 0x7f7877e39d00>, 'seal_ring_segmented': <function seal_ring_segmented at 0x7f7877e39e40>, 'wafer': <function wafer at 0x7f7877e3a020>, 'free_propagation_region': <function free_propagation_region at 0x7f7877e3a480>, 'awg': <function awg at 0x7f7877e3a520>, 'dbr_cell': <function dbr_cell at 0x7f7877e3a840>, 'dbr': <function dbr at 0x7f7877e3a980>, 'dbr_tapered': <function dbr_tapered at 0x7f7877e3ac00>, 'bbox': <function bbox at 0x7f7877e3b380>, 'C': <function C at 0x7f7877e3b560>, 'circle': <function circle at 0x7f7877e3b740>, 'compass': <function compass at 0x7f7877e3b9c0>, 'cross': <function cross at 0x7f7877e3bba0>, 'ellipse': <function ellipse at 0x7f7877e3bd80>, 'fiducial_squares': <function fiducial_squares at 0x7f7877e3bec0>, 'L': <function L at 0x7f7877e680e0>, 'nxn': <function nxn at 0x7f7877e682c0>, 'rectangle': <function rectangle at 0x7f7877e684a0>, 'rectangles': <function rectangles at 0x7f7877e685e0>, 'regular_polygon': <function regular_polygon at 0x7f7877e68720>, 'triangle': <function triangle at 0x7f7877e68900>, 'triangle2': <function triangle2 at 0x7f7877e68a40>, 'triangle4': <function triangle4 at 0x7f7877e68b80>, 'fiber': <function fiber at 0x7f7877e3af20>, 'fiber_array': <function fiber_array at 0x7f7877e68c20>, 'crossing_arm': <function crossing_arm at 0x7f7877e6b600>, 'crossing': <function crossing at 0x7f7877e6b740>, 'crossing_linear_taper': <function crossing_linear_taper at 0x7f7877e6b880>, 'crossing_etched': <function crossing_etched at 0x7f7877e6b9c0>, 'crossing45': <function crossing45 at 0x7f7877e6bb00>, 'straight_array': <function straight_array at 0x7f7877e6bf60>, 'wire_straight': <function wire_straight at 0x7f7877e9c0e0>, 'straight_heater_doped_rib': <function straight_heater_doped_rib at 0x7f7877e9c4a0>, 'straight_heater_doped_strip': <function straight_heater_doped_strip at 0x7f7877e9c680>, 'straight_heater_meander': <function straight_heater_meander at 0x7f7877e9c9a0>, 'via': <function via at 0x7f7877e9d1c0>, 'via_circular': <function via_circular at 0x7f7877e9d300>, 'via_chain': <function via_chain at 0x7f7877e9d620>, 'via_corner': <function via_corner at 0x7f7877e9d800>, 'via_stack': <function via_stack at 0x7f7877e9d9e0>, 'via_stack_corner45': <function via_stack_corner45 at 0x7f7877e9db20>, 'via_stack_corner45_extended': <function via_stack_corner45_extended at 0x7f7877e9dc60>, 'via_stack_with_offset': <function via_stack_with_offset at 0x7f7877e9dda0>, 'straight_heater_meander_doped': <function straight_heater_meander_doped at 0x7f7877e9cea0>, 'straight_heater_metal_undercut': <function straight_heater_metal_undercut at 0x7f7877e9dd00>, 'straight_heater_metal_simple': <function straight_heater_metal_simple at 0x7f7877e9e020>, 'straight_piecewise': <function straight_piecewise at 0x7f7877e9e160>, 'straight_pin': <function straight_pin at 0x7f7877e9e200>, 'straight_pin_slot': <function straight_pin_slot at 0x7f7877e9e480>, 'wire_corner': <function wire_corner at 0x7f7877e9e700>, 'wire_corner45': <function wire_corner45 at 0x7f7877e9e840>, 'wire_corner_sections': <function wire_corner_sections at 0x7f7877e9e8e0>, 'loop_mirror': <function loop_mirror at 0x7f7877e68ae0>, 'mode_converter': <function mode_converter at 0x7f7877ec4360>, 'polarization_splitter_rotator': <function polarization_splitter_rotator at 0x7f7877ec4680>, 'terminator': <function terminator at 0x7f7877ec4c20>, 'grating_coupler_array': <function grating_coupler_array at 0x7f7877ec4ea0>, 'grating_coupler_dual_pol': <function grating_coupler_dual_pol at 0x7f7877ec51c0>, 'grating_coupler_elliptical': <function grating_coupler_elliptical at 0x7f7877ec5800>, 'grating_coupler_elliptical_arbitrary': <function grating_coupler_elliptical_arbitrary at 0x7f7877ec5a80>, 'grating_coupler_elliptical_uniform': <function grating_coupler_elliptical_uniform at 0x7f7877ec5d00>, 'grating_coupler_elliptical_lumerical': <function grating_coupler_elliptical_lumerical at 0x7f7877ec5e40>, 'grating_coupler_elliptical_trenches': <function grating_coupler_elliptical_trenches at 0x7f7877ec5ee0>, 'grating_coupler_loss': <function grating_coupler_loss at 0x7f7877ec62a0>, 'grating_coupler_rectangular': <function grating_coupler_rectangular at 0x7f7877ec6480>, 'grating_coupler_rectangular_arbitrary': <function grating_coupler_rectangular_arbitrary at 0x7f7877ec6700>, 'grating_coupler_tree': <function grating_coupler_tree at 0x7f7877ec6980>, 'mmi': <function mmi at 0x7f7877ec6ca0>, 'mmi1x2': <function mmi1x2 at 0x7f7877ec6fc0>, 'mmi1x2_with_sbend': <function mmi1x2_with_sbend at 0x7f7877ec71a0>, 'mmi2x2': <function mmi2x2 at 0x7f7877ec74c0>, 'mmi2x2_with_sbend': <function mmi2x2_with_sbend at 0x7f7877ec7600>, 'mmi_90degree_hybrid': <function mmi_90degree_hybrid at 0x7f7877ec77e0>, 'mmi_tapered': <function mmi_tapered at 0x7f7877ec7b00>, 'pad': <function pad at 0x7f7877ec7d80>, 'pad_array': <function pad_array at 0x7f7877ec7f60>, 'pad_gsg_short': <function pad_gsg_short at 0x7f7877d002c0>, 'pads_shorted': <function pads_shorted at 0x7f7877d00540>, 'rectangle_with_slits': <function rectangle_with_slits at 0x7f7877d00680>, 'cavity': <function cavity at 0x7f7877d00900>, 'cdsem_all': <function cdsem_all at 0x7f7877d00b80>, 'cdsem_bend180': <function cdsem_bend180 at 0x7f7877d00d60>, 'cdsem_coupler': <function cdsem_coupler at 0x7f7877d00ea0>, 'cdsem_straight': <function cdsem_straight at 0x7f7877d011c0>, 'cdsem_straight_density': <function cdsem_straight_density at 0x7f7877d01300>, '_bendu_double': <function _bendu_double at 0x7f7877d01580>, '_straight_double': <function _straight_double at 0x7f7877d016c0>, 'cutback_2x2': <function cutback_2x2 at 0x7f7877d01800>, 'cutback_bend': <function cutback_bend at 0x7f7877d01bc0>, 'cutback_bend90': <function cutback_bend90 at 0x7f7877d01d00>, 'staircase': <function staircase at 0x7f7877d01e40>, 'cutback_bend180': <function cutback_bend180 at 0x7f7877d01f80>, 'cutback_component': <function cutback_component at 0x7f7877d020c0>, 'cutback_splitter': <function cutback_splitter at 0x7f7877d02480>, 'greek_cross': <function greek_cross at 0x7f7877d025c0>, 'greek_cross_with_pads': <function greek_cross_with_pads at 0x7f7877d02840>, 'litho_calipers': <function litho_calipers at 0x7f7877d02a20>, 'litho_ruler': <function litho_ruler at 0x7f7877d02d40>, 'litho_steps': <function litho_steps at 0x7f7877d02f20>, 'resistance_meander': <function resistance_meander at 0x7f7877d03060>, 'resistance_sheet': <function resistance_sheet at 0x7f7877d03240>, 'verniers': <function verniers at 0x7f7877d03420>, 'text': <function text at 0x7f7877d50180>, 'text_lines': <function text_lines at 0x7f7877d50360>, 'text_klayout': <function text_klayout at 0x7f7877d504a0>, 'text_freetype': <function text_freetype at 0x7f7877d507c0>, 'pixel_array': <function pixel_array at 0x7f7877d50a40>, 'text_rectangular': <function text_rectangular at 0x7f7877d50b80>, 'text_rectangular_multi_layer': <function text_rectangular_multi_layer at 0x7f7877d50cc0>, 'pixel': <function pixel at 0x7f7877d03740>, 'qrcode': <function qrcode at 0x7f7877d509a0>, 'version_stamp': <function version_stamp at 0x7f7877d50d60>, 'disk': <function disk at 0x7f7877d51300>, 'disk_heater': <function disk_heater at 0x7f7877d51440>, 'ring': <function ring at 0x7f7877d516c0>, 'ring_crow': <function ring_crow at 0x7f7877d518a0>, 'ring_crow_couplers': <function ring_crow_couplers at 0x7f7877d519e0>, 'ring_double': <function ring_double at 0x7f7877d51bc0>, 'ring_double_bend_coupler': <function ring_double_bend_coupler at 0x7f7877d51ee0>, 'ring_double_heater': <function ring_double_heater at 0x7f7877d52020>, 'ring_double_pn': <function ring_double_pn at 0x7f7877d52340>, 'ring_single_pn': <function ring_single_pn at 0x7f7877d52480>, 'ring_single': <function ring_single at 0x7f7877d52660>, 'ring_single_array': <function ring_single_array at 0x7f7877d527a0>, 'coupler_bend': <function coupler_bend at 0x7f7877d528e0>, 'coupler_ring_bend': <function coupler_ring_bend at 0x7f7877d52a20>, 'ring_single_bend_coupler': <function ring_single_bend_coupler at 0x7f7877d52b60>, 'ring_single_dut': <function ring_single_dut at 0x7f7877d52d40>, 'delay_snake': <function delay_snake at 0x7f7877d52fc0>, 'delay_snake2': <function delay_snake2 at 0x7f7877d531a0>, 'delay_snake_sbend': <function delay_snake_sbend at 0x7f7877d53420>, 'spiral': <function spiral at 0x7f7877d536a0>, 'spiral_double': <function spiral_double at 0x7f7877d53880>, 'spiral_racetrack': <function spiral_racetrack at 0x7f7877d53b00>, 'spiral_racetrack_fixed_length': <function spiral_racetrack_fixed_length at 0x7f7877d53c40>, 'spiral_racetrack_heater_metal': <function spiral_racetrack_heater_metal at 0x7f7877d53e20>, 'spiral_racetrack_heater_doped': <function spiral_racetrack_heater_doped at 0x7f7877d53f60>, 'spiral_inductor': <function spiral_inductor at 0x7f7877d900e0>, 'hline': <function hline at 0x7f7877d90360>, 'optimal_90deg': <function optimal_90deg at 0x7f7877d904a0>, 'optimal_hairpin': <function optimal_hairpin at 0x7f7877d907c0>, 'optimal_step': <function optimal_step at 0x7f7877d90900>, 'snspd': <function snspd at 0x7f7877d90ae0>, 'interdigital_capacitor': <function interdigital_capacitor at 0x7f7877d90cc0>, 'ge_detector_straight_si_contacts': <function ge_detector_straight_si_contacts at 0x7f7877d90f40>, 'edge_coupler_silicon': <function edge_coupler_silicon at 0x7f7877d911c0>, 'edge_coupler_array': <function edge_coupler_array at 0x7f7877d91300>, 'edge_coupler_array_with_loopback': <function edge_coupler_array_with_loopback at 0x7f7877d91440>}, virtual_factories={'virtual_bend_circular': <function virtual_bend_circular_factory.<locals>.virtual_bend_circular at 0x7f7882089ee0>, 'bend_euler': <function virtual_bend_euler_factory.<locals>.bend_euler at 0x7f788208a160>, 'virtual_straight': <function virtual_straight_factory.<locals>.virtual_straight at 0x7f788208a3e0>, 'bend_circular_all_angle': <function bend_circular_all_angle at 0x7f7877fe2ac0>, 'bend_euler_all_angle': <function bend_euler_all_angle at 0x7f7877fe3600>, 'straight_all_angle': <function straight_all_angle at 0x7f7877e6be20>}, kcells={0: Unnamed_0: ports [], 2 instances, 1: mmi1x2_WNone_WT1_LT10_L_4e0f7121: ports ['o1', 'o2', 'o3'], 0 instances, 2: taper_L10_W0p5_W1_LNone_456c7208: ports ['o1', 'o2'], 0 instances, 3: straight_L5p5_N2_CSxs_5_d3ec67bc: ports ['o1', 'o2'], 0 instances, 4: Unnamed_4: ports [], 6 instances, 5: bend_euler_R10_A90_P0p5_2f1f5c6d: ports ['o1', 'o2'], 0 instances, 6: straight_L29p375_N2_CSs_6ed2bfdd: ports ['o1', 'o2'], 0 instances, 7: straight_L54p5_N2_CSstrip_WNone: ports ['o1', 'o2'], 0 instances}, layers=<aenum 'LAYER'>, infos=LayerInfos(), layer_stack=LayerStack(layers={}), netlist_layer_mapping={}, sparameters_path=None, interconnect_cml_path=None, constants=Constants(), rename_function=<function rename_clockwise_multi at 0x7f788d99f240>, info=Info(), settings=KCellSettings(version='0.23.2', klayout_version='0.29.11', meta_format='v3'), future_cell_name=None, decorators=<kfactory.decorators.Decorators object at 0x7f788d43c490>) function_name='straight' basename=None boundary=None insts=<gdsfactory.component.ComponentReferences object at 0x7f7860773e10> size_info=<kfactory.kcell.SizeInfo object at 0x7f7875257310> dsize_info=<kfactory.kcell.DSizeInfo object at 0x7f7860773690> routes={}], n_bend90=2, n_taper=0, bend90_radius=10000, taper_length=0, length=83875, length_straights=83875, polygons={})

⚠️ Note: You can also get the route length, but keep the following in mind:

  • The route length is in DBU (Database Units). Usually, 1 DBU = 1 nm.

  • It only accounts for straight segments, not bends.

For the total length, including bends and straights, you can use Component.info['length'] or Instance.cell.info['length]

print(f"route length = {route.length} DBU, {route.length/1000} um")
route length = 83875 DBU, 83.875 um
route_length = 0
for instance in route.instances:
    route_length += instance.info['length']

print(f"total route length = {route_length} um")
total route length = 117.149 um
c = gf.Component()
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((100, 50))
route = gf.routing.route_single(
    c, port1=mmi1.ports["o2"], port2=mmi2.ports["o1"], layer=(1, 0), route_width=2
)
c
../_images/c9ed55ed63e0f9662882b21cb5136f2ef09285d8b4db6ffbd12f5e0f204c7e28.png

Problem: route_single with obstacles

sometimes there are obstacles that connect strip does not see!

c = gf.Component()
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((110, 50))
x = c << gf.components.cross(length=20)
x.move((135, 20))
route = gf.routing.route_single(
    c, mmi1.ports["o2"], mmi2.ports["o2"], cross_section="strip"
)
c
../_images/171cc7062424072d37aa6ec95808329bf5907eb225fdc1c4d1b729d7b020a49e.png

Solution: specify the route steps

route_single allows you to define relative or absolute steps x or y for the route as well as with increments dx or dy.

c = gf.Component()
w = gf.components.straight()
left = c << w
right = c << w
right.move((100, 80))

obstacle = gf.components.rectangle(size=(100, 10))
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle1.ymin = 40
obstacle2.xmin = 25

port1 = left.ports["o2"]
port2 = right.ports["o2"]

routes = gf.routing.route_single(
    c,
    port1=port1,
    port2=port2,
    cross_section="strip",
    steps=[
        {"x": 20, "y": 0},
        {"x": 20, "y": 20},
        {"x": 120, "y": 20},
        {"x": 120, "y": 80},
    ],
)
c
../_images/28a0e49ac9c9d710798d1fccc47be9ef1b43c19d3349ee481b3cac978f48609a.png
c = gf.Component()
w = gf.components.straight()
left = c << w
right = c << w
right.move((100, 80))

obstacle = gf.components.rectangle(size=(100, 10))
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle1.ymin = 40
obstacle2.xmin = 25

port1 = left.ports["o2"]
port2 = right.ports["o2"]

routes = gf.routing.route_single(
    c,
    port1=port1,
    port2=port2,
    cross_section="strip",
    steps=[
        {"x": 20},
        {"y": 20},
        {"x": 120},
        {"y": 80},
    ],
)
c
../_images/28a0e49ac9c9d710798d1fccc47be9ef1b43c19d3349ee481b3cac978f48609a.png

route_bundle#

To route groups of ports avoiding waveguide collisions, you should use route_bundle instead of route_single.

route_bundle uses a river/bundle/bus router.

At the moment it works only when each group of ports have the same orientation.

ys_right = [0, 10, 20, 40, 50, 80]
pitch = 127.0
N = len(ys_right)
ys_left = [(i - N / 2) * pitch for i in range(N)]
layer = (1, 0)

right_ports = [
    gf.Port(f"R_{i}", center=(0, ys_right[i]), width=0.5, orientation=180, layer=layer)
    for i in range(N)
]
left_ports = [
    gf.Port(f"L_{i}", center=(-200, ys_left[i]), width=0.5, orientation=0, layer=layer)
    for i in range(N)
]

# you can also mess up the port order and it will sort them by default
left_ports.reverse()

c = gf.Component()
routes = gf.routing.route_bundle(
    c,
    left_ports,
    right_ports,
    start_straight_length=50,
    sort_ports=True,
    cross_section="strip",
)
c.add_ports(left_ports)
c.add_ports(right_ports)
c
../_images/aecffb83cac9479f8f1044f59e8497949f7d187bef6babda4509bfe4bed1d593.png
xs_top = [0, 10, 20, 40, 50, 80]
pitch = 127.0
N = len(xs_top)
xs_bottom = [(i - N / 2) * pitch for i in range(N)]
layer = (1, 0)

top_ports = [
    gf.Port(f"top_{i}", center=(xs_top[i], 0), width=0.5, orientation=270, layer=layer)
    for i in range(N)
]

bot_ports = [
    gf.Port(
        f"bot_{i}",
        center=(xs_bottom[i], -300),
        width=0.5,
        orientation=90,
        layer=layer,
    )
    for i in range(N)
]

c = gf.Component()
routes = gf.routing.route_bundle(
    c,
    top_ports,
    bot_ports,
    separation=5.0,
    end_straight_length=100,
    cross_section="strip",
)
c
../_images/39ee24b42eca32fcd8cdb34154c9300bf16566c1099f5d432cc8ae4c12ce6e67.png

route_bundle can also route bundles through corners

@gf.cell(cache={})
def test_connect_corner(N=6, config="A"):
    d = 10.0
    sep = 5.0
    c = gf.Component()
    layer = (1, 0)

    if config in ["A", "B"]:
        a = 100.0
        ports_A_TR = [
            Port(
                f"A_TR_{i}",
                center=(d, a / 2 + i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_TL = [
            Port(
                f"A_TL_{i}",
                center=(-d, a / 2 + i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BR = [
            Port(
                f"A_BR_{i}",
                center=(d, -a / 2 - i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BL = [
            Port(
                f"A_BL_{i}",
                center=(-d, -a / 2 - i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A = [ports_A_TR, ports_A_TL, ports_A_BR, ports_A_BL]

        ports_B_TR = [
            Port(
                f"B_TR_{i}",
                center=(a / 2 + i * sep, d),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_TL = [
            Port(
                f"B_TL_{i}",
                center=(-a / 2 - i * sep, d),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BR = [
            Port(
                f"B_BR_{i}",
                center=(a / 2 + i * sep, -d),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BL = [
            Port(
                f"B_BL_{i}",
                center=(-a / 2 - i * sep, -d),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B = [ports_B_TR, ports_B_TL, ports_B_BR, ports_B_BL]

    elif config in ["C", "D"]:
        a = N * sep + 2 * d
        ports_A_TR = [
            Port(
                f"A_TR_{i}",
                center=(a, d + i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_TL = [
            Port(
                f"A_TL_{i}",
                center=(-a, d + i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BR = [
            Port(
                f"A_BR_{i}",
                center=(a, -d - i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BL = [
            Port(
                f"A_BL_{i}",
                center=(-a, -d - i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A = [ports_A_TR, ports_A_TL, ports_A_BR, ports_A_BL]

        ports_B_TR = [
            Port(
                f"B_TR_{i}",
                center=(d + i * sep, a),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_TL = [
            Port(
                f"B_TL_{i}",
                center=(-d - i * sep, a),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BR = [
            Port(
                f"B_BR_{i}",
                center=(d + i * sep, -a),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BL = [
            Port(
                f"B_BL_{i}",
                center=(-d - i * sep, -a),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B = [ports_B_TR, ports_B_TL, ports_B_BR, ports_B_BL]

    if config in ["A", "C"]:
        for ports1, ports2 in zip(ports_A, ports_B):
            gf.routing.route_bundle(
                c, ports1, ports2, radius=5, sort_ports=True, cross_section="strip"
            )

    elif config in ["B", "D"]:
        for ports1, ports2 in zip(ports_A, ports_B):
            gf.routing.route_bundle(
                c, ports2, ports1, radius=5, sort_ports=True, cross_section="strip"
            )

    return c


c = test_connect_corner(config="A")
c
../_images/0d9ce8bd9791f4548168af3c21a28784665b9617df6f6f39dfc146d9be5948e8.png
c = test_connect_corner(config="C")
c
../_images/cfea2260e2eb08932c93f6090f57cee0b48a2984c4453db5780681c03cc17d1a.png
@gf.cell(cache={})
def test_connect_bundle_udirect(dy=200, orientation=270, layer=(1, 0)):
    xs1 = [-100, -90, -80, -55, -35, 24, 0] + [200, 210, 240]
    axis = "X" if orientation in [0, 180] else "Y"
    pitch = 10.0
    N = len(xs1)
    xs2 = [70 + i * pitch for i in range(N)]

    if axis == "X":
        ports1 = [
            Port(
                f"top_{i}",
                center=(0, xs1[i]),
                width=0.5,
                orientation=orientation,
                layer=layer,
            )
            for i in range(N)
        ]

        ports2 = [
            Port(
                f"bottom_{i}",
                center=(dy, xs2[i]),
                width=0.5,
                orientation=orientation,
                layer=layer,
            )
            for i in range(N)
        ]

    else:
        ports1 = [
            Port(
                f"top_{i}",
                center=(xs1[i], 0),
                width=0.5,
                orientation=orientation,
                layer=layer,
            )
            for i in range(N)
        ]

        ports2 = [
            Port(
                f"bottom_{i}",
                center=(xs2[i], dy),
                width=0.5,
                orientation=orientation,
                layer=layer,
            )
            for i in range(N)
        ]

    c = Component()
    gf.routing.route_bundle(
        c, ports1, ports2, radius=10.0, sort_ports=True, cross_section="strip"
    )
    return c


c = test_connect_bundle_udirect()
c
../_images/9a901949219dbd823c819f4bb8a849eca0774e029e184e648e150af2c07bb17b.png
@gf.cell
def test_connect_bundle_u_indirect(dy=-200, orientation=180, layer=(1, 0)):
    xs1 = [-100, -90, -80, -55, -35] + [200, 210, 240]
    axis = "X" if orientation in [0, 180] else "Y"
    pitch = 10.0
    N = len(xs1)
    xs2 = [50 + i * pitch for i in range(N)]

    a1 = orientation
    a2 = a1 + 180

    if axis == "X":
        ports1 = [
            Port(f"top_{i}", center=(0, xs1[i]), width=0.5, orientation=a1, layer=layer)
            for i in range(N)
        ]

        ports2 = [
            Port(
                f"bot_{i}",
                center=(dy, xs2[i]),
                width=0.5,
                orientation=a2,
                layer=layer,
            )
            for i in range(N)
        ]

    else:
        ports1 = [
            Port(f"top_{i}", center=(xs1[i], 0), width=0.5, orientation=a1, layer=layer)
            for i in range(N)
        ]

        ports2 = [
            Port(
                f"bot_{i}",
                center=(xs2[i], dy),
                width=0.5,
                orientation=a2,
                layer=layer,
            )
            for i in range(N)
        ]

    c = Component()
    gf.routing.route_bundle(
        c,
        ports1,
        ports2,
        bend=gf.components.bend_euler,
        radius=5,
        cross_section="strip",
    )

    return c


c = test_connect_bundle_u_indirect(orientation=0)
c
../_images/ee4817bf020b045a3197939a617afb6516ac50578f4e783f93dbcf4c3d54adab.png
@gf.cell
def test_north_to_south(layer=(1, 0)):
    dy = 200.0
    xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650]

    pitch = 10.0
    N = len(xs1)
    xs2 = [-20 + i * pitch for i in range(N // 2)]
    xs2 += [400 + i * pitch for i in range(N // 2)]

    a1 = 90
    a2 = a1 + 180

    ports1 = [
        gf.Port(f"top_{i}", center=(xs1[i], 0), width=0.5, orientation=a1, layer=layer)
        for i in range(N)
    ]

    ports2 = [
        gf.Port(f"bot_{i}", center=(xs2[i], dy), width=0.5, orientation=a2, layer=layer)
        for i in range(N)
    ]

    c = gf.Component()
    gf.routing.route_bundle(c, ports1, ports2, cross_section="strip")
    return c


c = test_north_to_south()
c
../_images/0fd8e659665f8ce418a6b26df5a5d9eb921a3adec2256fc63780519cb87b90a8.png
@gf.cell
def demo_connect_bundle():
    """Combines all the connect_bundle tests."""
    y = 400.0
    x = 500
    y0 = 900
    dy = 200.0
    c = gf.Component()
    for j, s in enumerate([-1, 1]):
        for i, orientation in enumerate([0, 90, 180, 270]):
            ref = c << test_connect_bundle_u_indirect(
                dy=s * dy, orientation=orientation
            )
            ref.dcenter = (i * x, j * y)

            ref = c << test_connect_bundle_udirect(dy=s * dy, orientation=orientation)
            ref.dcenter = (i * x, j * y + y0)

    for i, config in enumerate(["A", "B", "C", "D"]):
        ref = c << test_connect_corner(config=config)
        ref.dcenter = (i * x, 1700)

    return c


c = demo_connect_bundle()
c.show()
c
../_images/d2e3be400100c4f26b3e1fcb70f385e2bef6acc6ba41ad6289a78566091eabd0.png
import gdsfactory as gf
c = gf.Component()
c1 = c << gf.components.mmi2x2()
c2 = c << gf.components.mmi2x2()

c2.move((100, 50))
routes = gf.routing.route_bundle(
    c,
    [c1.ports["o4"], c1.ports["o3"]],
    [c2.ports["o1"], c2.ports["o2"]],
    radius=5,
    cross_section="strip",
)
c
../_images/f75a8a55f00e3bca8f6ae53aea732421f8642491e089e95a3ad5bbe9148e0509.png
c = gf.Component()
c1 = c << gf.components.pad()
c2 = c << gf.components.pad()
c2.move((200, 100))
routes = gf.routing.route_bundle_electrical(
    c,
    [c1.ports["e3"]],
    [c2.ports["e1"]],
    cross_section=gf.cross_section.metal3,
)
c
../_images/569d0b124aae027c53e7e01ebebfafb18ee2a7564f2799f49192b271e19216a5.png

Problem

Sometimes 90 degrees routes do not have enough space for a Manhattan route

c = gf.Component()
c1 = c << gf.components.nxn(east=3, ysize=20)
c2 = c << gf.components.nxn(west=3)
c2.move((80, 0))
c
../_images/ce4567c53c45050a0a91216a903f4266d986a9bd83b961ef00068593e3044c1f.png
c = gf.Component()
c1 = c << gf.components.nxn(east=3, ysize=20)
c2 = c << gf.components.nxn(west=3)
c2.move((80, 0))
routes = gf.routing.route_bundle(
    c,
    list(c1.ports.filter(orientation=0)),
    list(c2.ports.filter(orientation=180)),
    on_collision=None,
    cross_section="strip",
)
c
../_images/24f54c4eaeff8f40e09df3e577cd9183ce558c448af6eb60fb1164a07ad5f460.png
c = gf.Component()
pitch = 2.0
ys_left = [0, 10, 20]
N = len(ys_left)
ys_right = [(i - N / 2) * pitch for i in range(N)]
layer = (1, 0)

right_ports = [
    gf.Port(f"R_{i}", center=(0, ys_right[i]), width=0.5, orientation=180, layer=layer)
    for i in range(N)
]
left_ports = [
    gf.Port(f"L_{i}", center=(-50, ys_left[i]), width=0.5, orientation=0, layer=layer)
    for i in range(N)
]
left_ports.reverse()
routes = gf.routing.route_bundle(
    c, right_ports, left_ports, radius=5, on_collision=None, cross_section="strip"
)

c
../_images/2ff984ada8a40043674a2ea3267aa5da154d51dfeb37814e61beb2e2287ae8bd.png

Solution

Add Sbend routes using route_bundle_sbend

c = gf.Component()
c1 = c << gf.components.nxn(east=3, ysize=20)
c2 = c << gf.components.nxn(west=3)
c2.move((80, 0))
routes = gf.routing.route_bundle_sbend(
    c,
    c1.ports.filter(orientation=0),
    c2.ports.filter(orientation=180),
    enforce_port_ordering=False,
)
c
../_images/81173a6cc98d3362290c3f4f5a060cf696cafec8f76d82231a049ba86cfff22c.png
import gdsfactory as gf
from gdsfactory.samples.big_device import big_device

c = gf.Component()
c1 = big_device()
c2 = gf.routing.add_fiber_array(c1)
c2.plot()
../_images/c9f4916b11d24275134e669a8a3b6ad1e5a2d049e6a4125a6ee1ecc51ae66ec6.png
c = gf.Component()
w = gf.components.straight()
left = c << w
right = c << w
right.move((100, 80))

obstacle = gf.components.rectangle(size=(100, 10))
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle1.ymin = 40
obstacle2.xmin = 25

port1 = left.ports["o2"]
port2 = right.ports["o2"]

routes = gf.routing.route_bundle(
    c,
    [port1],
    [port2],
    cross_section="strip",
    steps=[
        {"dy": 30, "dx": 50},
        {"dx": 100},
    ],
)
c
../_images/4af836465051c85a71a8e2d2d3be3b63470e08e107efe158b7422231f768788c.png
c = gf.Component()
w = gf.components.array(gf.c.straight, columns=1, rows=3, row_pitch=3)
left = c << w
right = c << w
right.move((100, 100))

obstacle = gf.components.rectangle(size=(100, 10))
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle1.ymin = 40
obstacle2.xmin = 35

ports1 = left.ports.filter(orientation=0)
ports2 = right.ports.filter(orientation=180)

routes = gf.routing.route_bundle(
    c,
    ports1,
    ports2,
    cross_section="strip",
    sort_ports=True,
    steps=[
        {"dy": 30, "dx": 50},
        {"dx": 90},
    ],
)
c
../_images/1b7b5a91a531bfa7579e1c143bf47456b3ba449347fc7f1fd4e28426d9334bcf.png

route_astar#

You can navigate around bounding boxes when routing if you pass the bboxes of all the objects that you want to avoid.

Currently the router only respects any (merged) bounding boxes which overlap with start or end port bundles

import gdsfactory as gf

c = gf.Component()
cross_section = "strip"
port_prefix = "o"
bend = gf.components.bend_euler

cross_section = gf.get_cross_section(cross_section, radius=5)
w = gf.components.straight(cross_section=cross_section)
left = c << w
right = c << w
right.rotate(90)
right.move((168, 63))

obstacle = gf.components.rectangle(size=(250, 3), layer="M2")
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle3 = c << obstacle
obstacle4 = c << obstacle
obstacle4.rotate(90)
obstacle1.ymin = 50
obstacle1.xmin = -10
obstacle2.xmin = 35
obstacle3.ymin = 42
obstacle3.xmin = 72.23
obstacle4.xmin = 200
obstacle4.ymin = 55
port1 = left.ports[f"{port_prefix}1"]
port2 = right.ports[f"{port_prefix}2"]

route = gf.routing.route_astar(
    component=c,
    port1=port1,
    port2=port2,
    cross_section=cross_section,
    resolution=15,
    distance=12,
    avoid_layers=("M2",),
    bend=bend,
)
c
../_images/b683cf619fa535d420abbdd05a1d3337d0d5c35ef73c6cc86d19c0b814cbdc42.png

route_bundle with collisions#

The route bundle with collision avoidance is not yet supported.

import gdsfactory as gf

c = gf.Component()
columns = 2
ptop = c << gf.components.pad_array(columns=columns, port_orientation=270)
pbot = c << gf.components.pad_array(port_orientation=270, columns=columns)
ptop.movex(300)
ptop.movey(300)

obstacle = c << gf.c.rectangle(size=(300, 100), layer="M3")
obstacle.ymin = pbot.ymax - 10
obstacle.xmin = pbot.xmax - 10


routes = gf.routing.route_bundle_electrical(
    c,
    pbot.ports,
    ptop.ports,
    start_straight_length=100,
    separation=20,
    cross_section="metal_routing",
    bboxes=[
        obstacle.bbox(),
        pbot.bbox(),
        ptop.bbox(),
    ],  # obstacles to avoid
    sort_ports=True,
)

c
../_images/efbf27812037715de1555523559591ca3ec97f6a0be8ba5ac3d18e4f485c0215.png
import gdsfactory as gf

c = gf.Component()
columns = 2
ptop = c << gf.components.pad_array(columns=columns, port_orientation=270)
pbot = c << gf.components.pad_array(port_orientation=270, columns=columns)
ptop.movex(300)
ptop.movey(300)

obstacle = c << gf.c.rectangle(size=(300, 100), layer="M3", centered=True)
obstacle.ymin = pbot.ymax - 10
obstacle.xmin = pbot.xmax + 10

c2 = gf.Component()  # create a dummy component to get the size of the obstacle
obstacle_sized = c2 << gf.c.rectangle(size=(340, 140), layer="M3", centered=True)
obstacle_sized.dcenter = obstacle.dcenter


routes = gf.routing.route_bundle_electrical(
    c,
    pbot.ports,
    ptop.ports,
    start_straight_length=100,
    separation=20,
    cross_section="metal_routing",
    bboxes=[
        obstacle_sized.bbox(),
        pbot.bbox(),
        ptop.bbox(),
    ],  # obstacles to avoid not working yet
    sort_ports=True,
)

c
../_images/437ea962654559566204a3aff1da32258a82f8a638ed36e5b8688efd49f581cf.png

route_bundle_all_angle#

You can also route using diagonal routes.

import gdsfactory as gf

c = gf.Component()
rows = 3
straight = gf.c.straight
w1 = c << gf.c.array(straight, rows=rows, columns=1, row_pitch=10)
w2 = c << gf.c.array(straight, rows=rows, columns=1, row_pitch=10)
w2.drotate(-30)
w2.movex(140)
p1 = list(w1.ports.filter(orientation=0))
p2 = list(w2.ports.filter(orientation=150))
p1.reverse()
p2.reverse()

gf.routing.route_bundle_all_angle(
    c,
    p1,
    p2,
    separation=3,
)
c
../_images/904423c15226c5d28afc9bd3e79852da51ca25d15c1c6bfbc5d3fdd10fa3ad28.png

You can also use it to connect rotated components that do not have a manhattan orientation (0, 90, 180, 270)

c = gf.Component()

mmi = gf.components.mmi2x2(width_mmi=10, gap_mmi=3)
mmi1 = c.create_vinst(mmi)  # create a virtual instance
mmi2 = c.create_vinst(mmi)  # create a virtual instance

mmi2.move((100, 10))
mmi2.drotate(30)

routes = gf.routing.route_bundle_all_angle(
    c,
    mmi1.ports.filter(orientation=0),
    [mmi2.ports["o2"], mmi2.ports["o1"]],
)
c.show()
c
../_images/239320a2e0b51f2991ce0c53e880c0a973b1138a74c8fb8a419eb7cb4a2a66c4.png

Dubin paths#

If you’re working with PIC layouts and looking for a straightforward way to optimize waveguide paths, Dubins paths offer an effective solution by ensuring the shortest path with minimal bending and loss.

Using Dubins paths for waveguide routing can simplify your design process significantly. Compared to traditional interconnects, Dubins paths offer shorter, more reliable routes that avoid unnecessary bending and intersections. For PIC layouts, this translates into denser, cleaner designs with improved performance.

See blog

c = gf.Component()

# Create two straight waveguides with different orientations
wg1 = c << gf.components.straight(length=100, width=3.2)
wg2 = c << gf.components.straight(length=100, width=3.2)

# Move and rotate the second waveguide
wg2.move((300, 50))
wg2.rotate(45)

# Route between the output of wg1 and input of wg2
route = gf.routing.route_dubin(
    c,
    port1=wg1.ports["o2"],
    port2=wg2.ports["o1"],
    cross_section=gf.cross_section.strip(width=3.2, radius=100),
)
c
../_images/911b75aae62e8d7cb279cf220981a71db3b457b6760cf9880df9561ac73d481a.png
c = gf.Component()

# Create two multi-port components
comp1 = c << gf.components.nxn(west=0, east=10, xsize=10, ysize=100, wg_width=3.2)
comp2 = c << gf.components.nxn(west=0, east=10, xsize=10, ysize=100, wg_width=3.2)

# Position second component
comp2.drotate(30)
comp2.move((500, -100))

# Route between corresponding ports
for i in range(10):
    port1_name = f"o{10-i}"  # Inverted port id for port1
    port2_name = f"o{i+1}"  # Adjusted to match available ports
    gf.routing.route_dubin(
        c,
        port1=comp1.ports[port1_name],
        port2=comp2.ports[port2_name],
        cross_section=gf.cross_section.strip(width=3.2, radius=100 + i * 10),
    )
c
../_images/f4da670cf38f657e1ca9cff06e667859b7e01d834c6c798a9abd1e89f956f5ca.png

auto_taper#

Both route_single and route_bundle have a auto_taper parameter.

For auto_taper to work you need to define how to transition different between different layers and widths.


layer_transitions = {
    LAYER.WG: partial(gf.c.taper, cross_section="strip", length=10),
    (LAYER.WG, LAYER.WGN): "taper_sc_nc",
    (LAYER.WGN, LAYER.WG): "taper_nc_sc",
    LAYER.M3: "taper_electrical",
}

return Pdk(
    name="generic",
    cells=cells,
    cross_sections=cross_sections,
    layers=LAYER,
    layer_stack=LAYER_STACK,
    layer_views=LAYER_VIEWS,
    layer_transitions=layer_transitions,
    materials_index=materials_index,
    constants=constants,
    connectivity=LAYER_CONNECTIVITY,
)

For example, in the code below if you have a width mismatch between two ports, the router will automatically add a taper to transition between the two widths, only if auto_taper=True, otherwise it will raise an error.

c = gf.Component()
s1 = c << gf.components.straight()
s2 = c << gf.components.straight(width=2)
s2.move((40, 50))
route = gf.routing.route_single(
    c,
    port1=s1.ports["o2"],
    port2=s2.ports["o1"],
    cross_section="strip",
    auto_taper=True,
)
c
../_images/5c97964681a0fbfcd33580ea775003d0b7572d4af7dd1f9f8f612e89dc0b8c9b.png
import gdsfactory as gf
from gdsfactory.routing.auto_taper import auto_taper_to_cross_section


@gf.cell
def silicon_nitride_strip(width_nitride: float = 1) -> gf.Component:
    c = gf.Component()
    ref = c << gf.c.straight(
        cross_section=gf.cross_section.nitride, width=width_nitride
    )
    port1 = auto_taper_to_cross_section(
        c, port=ref["o1"], cross_section=gf.cross_section.strip
    )
    c.add_port(name="o1", port=port1)
    c.add_port(name="o2", port=ref["o2"])
    return c


c = silicon_nitride_strip(width_nitride=1)
c
../_images/d511def72733a0bf468dd599a06eef8a8afefa3d1be12b5119992698bef6a5cc.png
c = silicon_nitride_strip(width_nitride=4)
c
../_images/eb815fb30ef52b1186fa2569a301b8b64f73fa7c23e8dc27fe5f414aceb070fc.png