def text_rectangular_multi_layer( text: str = "abcd", layers: Layers = (LAYER.WG, LAYER.M1, LAYER.M2, LAYER.M3), text_factory: ComponentFactory = text_rectangular, **kwargs, ) -> Component: """Returns rectangular text in different layers Args: text: string of text layers: list of layers to replicate the text text_factory: function to create the text Components Keyword Args: size: pixel size position: coordinate justify: left, right or center font: function that returns dictionary of characters """ func = gf.partial( copy_layers, factory=gf.partial(text_factory, text=text, **kwargs), layers=layers, ) return func()
def test_partial_function(): mmi400 = gf.partial(gf.components.mmi1x2, width=0.4) mmi600 = gf.partial(gf.components.mmi1x2, width=0.6) mzi400 = gf.partial(gf.components.mzi, splitter=mmi400) mzi600 = gf.partial(gf.components.mzi, splitter=mmi600) c400 = mzi400() c600 = mzi600() assert c600.name != c400.name, print(c400.name, c600.name)
def test_compose1(): """Ensures the first level of composed function gets a unique name""" mzi500 = gf.partial(gf.components.mzi, straight=straigth_extended1) mzi900 = gf.partial(gf.components.mzi, straight=straigth_extended2) c500 = mzi500() c900 = mzi900() assert c900.name != c500.name, f"{c500.name} must be different from {c900.name}"
def test_partial_function_without_kwargs(): r1 = gf.partial(gf.c.rectangle, size=(4, 2)) r2 = gf.partial(gf.c.rectangle, size=(4, 2)) r3 = gf.partial(gf.c.rectangle, (4, 2)) c1 = r1() c2 = r2() c3 = r3() assert c1.name == c2.name == c3.name, f"{c1.name} == {c2.name} == {c3.name}"
def test_compose2(): """Ensures the second level of composed function gets a unique name. FIXME! this one does not work """ mzi500 = gf.partial(gf.components.mzi, straight=straigth_extended3) mzi900 = gf.partial(gf.components.mzi, straight=straigth_extended2) c500 = mzi500() c900 = mzi900() assert c900.name != c500.name, f"{c500.name} must be different from {c900.name}"
def _demo(): c = gf.Component("get_route_from_steps_sample") w = gf.components.array( gf.partial(gf.c.straight, layer=(2, 0)), rows=3, columns=1, spacing=(0, 50), ) left = c << w right = c << w right.move((200, 100)) p1 = left.get_ports_list(orientation=0) p2 = right.get_ports_list(orientation=180) routes = get_bundle_from_steps_electrical( p1, p2, steps=[{ "x": 150 }], ) for route in routes: c.add(route.references) c.show()
def test_get_bundle_udirect( data_regression: DataRegressionFixture, check: bool = True ) -> Component: c = gf.Component("test_get_bundle_udirect") pad = gf.partial(gf.c.pad, size=(10, 10)) pad_south = gf.components.pad_array(orientation=270, spacing=(15.0, 0), pad=pad) pt = c << pad_south pb = c << pad_south pb.rotate(90) pt.rotate(90) pb.move((0, -100)) pbports = pb.get_ports_list() ptports = pt.get_ports_list() pbports.reverse() routes = gf.routing.get_bundle(pbports, ptports, radius=5) lengths = {} for i, route in enumerate(routes): c.add(route.references) lengths[i] = route.length if check: data_regression.check(lengths) return c
def test_partial_function_with_kwargs(): mmi400 = gf.partial(gf.components.mmi1x2, width=0.4) mmi400_args = gf.partial(gf.components.mmi1x2, 0.4) mmi600 = gf.partial(gf.components.mmi1x2, width=0.6) mzi400 = gf.partial(gf.components.mzi, splitter=mmi400) mzi600 = gf.partial(gf.components.mzi, splitter=mmi600) c400 = mzi400() c600 = mzi600() assert c600.name != c400.name, f"{c600.name} must be different from {c400.name}" cmmi400 = mmi400() cmmi400_args = mmi400_args() assert (cmmi400_args.name == cmmi400.name ), f"{cmmi400_args.name} must be equal to {cmmi400.name}"
def test_route_error_bundle(): """Ensures that an impossible route raises value Error""" c = gf.Component("get_route_from_steps_sample") w = gf.components.array( gf.partial(gf.c.straight, layer=(2, 0)), rows=3, columns=1, spacing=(0, 50), ) left = c << w right = c << w right.move((200, 100)) p1 = left.get_ports_list(orientation=0) p2 = right.get_ports_list(orientation=180) with pytest.warns(RouteWarning): routes = gf.routing.get_bundle_from_steps( p1, p2, steps=[{ "x": 300 }, { "x": 301 }], ) for route in routes: c.add(route.references) return c
def test_get_bundle_west_to_north( data_regression: DataRegressionFixture, check: bool = True ) -> Component: lengths = {} c = gf.Component("test_get_bundle_west_to_north") pad = gf.partial(gf.c.pad, size=(10, 10)) c = gf.Component() pad_south = gf.components.pad_array(orientation=270, spacing=(15.0, 0.0), pad=pad) pad_north = gf.components.pad_array(orientation=90, spacing=(15.0, 0.0), pad=pad) pl = c << pad_south pb = c << pad_north pl.rotate(90) pb.move((100, -100)) pbports = pb.get_ports_list() ptports = pl.get_ports_list() c.add_ports(pbports, prefix="N") c.add_ports(ptports, prefix="S") routes = gf.routing.get_bundle( pbports, ptports, bend=gf.components.wire_corner, ) for i, route in enumerate(routes): c.add(route.references) lengths[i] = route.length if check: data_regression.check(lengths) return c
def find_coupling(gap: float = 0.2, mode_solver: ModeSolverFactory = get_mode_solver_coupler, find_modes: Callable = find_modes_function, power_ratio: float = 1.0, wavelength: float = 1.55, **kwargs) -> float: """ Returns the coupling length (um) of the directional coupler to achieve power_ratio Args: gap: in um mode_solver: function to get the mode solver find_modes: function to find the modes power_ratio: p2/p1, where 1 means 100% power transfer wavelength: in um keyword Args: nmodes: number of modes parity: for symmetries """ modes = find_modes(mode_solver=gf.partial(mode_solver, gaps=(gap, )), wavelength=wavelength, **kwargs) ne = modes[1].neff no = modes[2].neff return coupling_length(neff1=ne, neff2=no, power_ratio=power_ratio, wavelength=wavelength)
def test_extend_ports() -> Component: import gdsfactory as gf import gdsfactory.components as pc width = 0.5 xs_strip = gf.partial(gf.cross_section.strip, width=width) c = pc.cross(width=width, port_type="optical") c1 = extend_ports(component=c, cross_section=xs_strip) assert len(c.ports) == len(c1.ports) p = len(c1.polygons) assert p == 4, p c2 = extend_ports(component=c, cross_section=xs_strip, port_names=("o1", "o2")) p = len(c2.polygons) assert p == 2, p c3 = extend_ports(component=c, cross_section=xs_strip) p = len(c3.polygons) assert p == 4, p c4 = extend_ports(gf.c.cross(port_type="optical")) p = len(c4.polygons) assert p == 4, p return c4
def find_coupling_vs_gap( gap1: float = 0.2, gap2: float = 0.4, steps: int = 12, mode_solver: ModeSolverFactory = get_mode_solver_coupler, find_modes: Callable = find_modes_function, nmodes: int = 4, wavelength: float = 1.55, parity=mp.NO_PARITY, filepath: Optional[PathType] = None, overwrite: bool = False, **kwargs) -> pd.DataFrame: """ Returns coupling vs gap Args: gap1: gap2: steps: mode_solver: find_modes: nmodes: wavelength: parity: filepath: overwrite: """ if filepath and not overwrite and pathlib.Path(filepath).exists(): return pd.read_csv(filepath) gaps = np.linspace(gap1, gap2, steps) ne = [] no = [] gap_to_modes = {} for gap in gaps: modes = find_modes(mode_solver=gf.partial(mode_solver, gaps=(gap, ))) ne.append(modes[1].neff) no.append(modes[2].neff) gap_to_modes[gap] = modes lc = [ coupling_length(neff1=neff1, neff2=neff2) for gap, neff1, neff2 in zip(gaps, ne, no) ] df = pd.DataFrame(dict(gap=gaps, ne=ne, no=no, lc=lc)) if filepath: filepath = pathlib.Path(filepath) dirpath = filepath.parent dirpath.mkdir(exist_ok=True, parents=True) df.to_csv(filepath, index=False) return df
def test_get_route_auto_widen() -> gf.Component: c = gf.Component("test_get_route_auto_widen") route = gf.routing.get_route_from_waypoints( [(0, 0), (300, 0), (300, 300), (-600, 300), (-600, -300)], cross_section=xs_pin_m1, bend=gf.partial(gf.c.bend_euler, cross_section=xs_pin), taper=taper_pin, radius=30, ) c.add(route.references) difftest(c) return c
def test_name_partial_functions(): s1 = gf.partial(gf.c.straight) s2 = gf.partial(gf.c.straight, length=5) s3 = gf.partial(gf.c.straight, 5) m1 = gf.partial(gf.c.mzi, straight=s1)() m2 = gf.partial(gf.c.mzi, straight=s2)() m3 = gf.partial(gf.c.mzi, straight=s3)() # print(m1.name) # print(m2.name) # print(m3.name) assert ( m2.name == m3.name ), f"{m2.name} different from {m2.name} while they are the same function" assert ( m1.name != m2.name ), f"{m1.name} is the same {m2.name} while they are different functions" assert ( m1.name != m3.name ), f"{m1.name} is the same {m3.name} while they are different functions"
"""Lets add pins to each cell from the fab a PDK. """ import gdsfactory as gf from gdsfactory.add_pins import add_outline, add_pins from gdsfactory.cross_section import strip from gdsfactory.difftest import difftest from gdsfactory.tech import Library WIDTH = 2 LAYER = (30, 0) fab_a_metal = gf.partial(strip, width=WIDTH, layer=LAYER) fab_a_metal.__name__ = "fab_a_metal" def test_waveguide(): c = gf.components.straight(cross_section=fab_a_metal) difftest(c) def decorator(component) -> None: """Fab specific functions over a component.""" add_pins(component) add_outline(component) mmi2x2 = gf.partial(gf.components.mmi2x2, decorator=decorator) mmi1x2 = gf.partial(gf.components.mmi1x2, decorator=decorator) bend_euler = gf.partial(gf.components.bend_euler, decorator=decorator)
"""Straight Doped PIN waveguide.""" import gdsfactory as gf from gdsfactory.components.extension import extend_ports from gdsfactory.components.straight import straight from gdsfactory.components.taper import taper_strip_to_ridge from gdsfactory.cross_section import rib straight_rib = gf.partial(straight, cross_section=rib) straight_rib_tapered = gf.partial( extend_ports, component=straight_rib, extension_factory=taper_strip_to_ridge, port1="o2", port2="o1", ) if __name__ == "__main__": c = straight_rib() c = straight_rib_tapered() c.show()
import gdsfactory as gf from gdsfactory.component import Component from gdsfactory.components.bend_euler import bend_euler from gdsfactory.components.coupler_ring import coupler_ring from gdsfactory.components.straight import straight as straight_function from gdsfactory.components.taper import taper from gdsfactory.config import call_if_func from gdsfactory.snap import assert_on_2nm_grid taper2 = gf.partial(taper, width2=3) @gf.cell def ring_single_dut(component=taper2, wg_width=0.5, gap=0.2, length_x=4, radius=5, length_y=0, coupler=coupler_ring, straight=straight_function, bend=bend_euler, with_component=True, **kwargs): """Single bus ring made of two couplers (ct: top, cb: bottom) connected with two vertical straights (wyl: left, wyr: right) (Device Under Test) in the middle to extract loss from quality factor Args: with_component: if False changes component for just a straight
for i in range(columns): if i % 2 == 0: # even row s += "D-C-" * rows + "|" else: s += "C-D-" * rows + "|" s = s[:-1] # Create the component from the sequence c = component_sequence(sequence=s, symbol_to_component=symbol_to_component, start_orientation=0) c.info.n_bends = rows * columns * 2 + columns * 2 - 2 return c cutback_bend180circular = gf.partial(cutback_bend180, bend180=bend_circular180) cutback_bend90circular = gf.partial(cutback_bend90, bend90=bend_circular) if __name__ == "__main__": c = cutback_bend() # c = cutback_bend90() # c = cutback_bend_circular(rows=7, columns=4, radius=5) #62 # c = cutback_bend_circular(rows=14, columns=4) #118 # c = cutback_bend90() # c = cutback_bend180(rows=3, columns=1) # c = cutback_bend(rows=3, columns=2) # c = cutback_bend90(rows=3, columns=2) # c = cutback_bend180(rows=2, columns=2) # c = cutback_bend(rows=3, columns=2) c.show()
Lets say that the waveguides are defined in layer (2, 0) and are 0.3um wide """ import gdsfactory as gf from gdsfactory.cross_section import strip from gdsfactory.difftest import difftest WIDTH = 0.3 LAYER = (2, 0) LAYERS_CLADDING = ((71, 0), (68, 0)) fab_b_metal = gf.partial( strip, width=WIDTH, layer=LAYER, layers_cladding=LAYERS_CLADDING, ) fab_b_metal.__name__ = "fab_b_metal" straight = gf.partial(gf.components.straight, cross_section=fab_b_metal) bend_euler = gf.partial(gf.components.bend_euler, cross_section=fab_b_metal) mmi1x2 = gf.partial( gf.components.mmi1x2, cross_section=fab_b_metal, width=WIDTH, width_taper=WIDTH, width_mmi=3 * WIDTH, ) mzi = gf.partial(gf.components.mzi, cross_section=fab_b_metal, splitter=mmi1x2) gc = gf.partial(gf.components.grating_coupler_elliptical_te,
ref = c.add_array( via, columns=nb_vias_x, rows=nb_vias_y, spacing=(pitch_x, pitch_y) ) cw = (width - (nb_vias_x - 1) * pitch_x - w) / 2 ch = (height - (nb_vias_y - 1) * pitch_y - h) / 2 x0 = -a + cw + w / 2 y0 = -b + ch + h / 2 ref.move((x0, y0)) return c contact_metal = gf.partial( contact, layers=(LAYER.M1, LAYER.M2, LAYER.M3), vias=(via1, via2), ) contact_slab = gf.partial( contact, layers=(LAYER.SLAB90, LAYER.M1, LAYER.M2, LAYER.M3), vias=(viac, via1, via2), ) contact_npp = gf.partial( contact, layers=(LAYER.WG, LAYER.NPP, LAYER.M1), vias=(None, None, viac), ) contact_slab_npp = gf.partial( contact,
| |_ - |__| |<-dx->| """ import gdsfactory as gf from gdsfactory.components.mmi2x2 import mmi2x2 from gdsfactory.components.mzi import mzi1x2_2x2 from gdsfactory.components.splitter_tree import splitter_tree from gdsfactory.components.straight_heater_metal import straight_heater_metal mzi = gf.partial( mzi1x2_2x2, combiner=mmi2x2, delta_length=0, straight_x_top=straight_heater_metal, length_x=None, ) switch_tree = gf.partial(splitter_tree, coupler=mzi, spacing=(500, 100)) if __name__ == "__main__": # c = mzi() c = switch_tree(noutputs=16) c.show()
monitor_indices=monitor_indices, **settings, )) df = pd.DataFrame(sp) df["wavelengths"] = np.linspace(wl_min, wl_max, wl_steps) df["freqs"] = 1 / df["wavelengths"] df.to_csv(filepath, index=False) logger.info(f"Write simulation results to {filepath!r}") filepath_sim_settings.write_text(OmegaConf.to_yaml(sim_settings)) logger.info(f"Write simulation settings to {filepath_sim_settings!r}") return df write_sparameters_meep_lr = gf.partial(write_sparameters_meep, ymargin_top=3, ymargin_bot=3) write_sparameters_meep_lt = gf.partial(write_sparameters_meep, ymargin_bot=3, xmargin_right=3) if __name__ == "__main__": c = gf.components.straight(length=2) # p = 2 # c = gf.add_padding_container(c0, default=0, top=p, bottom=p) # write_sparameters_meep(c, run=False) write_sparameters_meep_lr(c, run=False) plt.show()
c = Component() extension = (extension_factory() if callable(extension_factory) else extension_factory) extension_port_name = extension_port_name or list( extension.ports.keys())[0] for i, port in enumerate(ports): extension_ref = c << extension extension_ref.connect(extension_port_name, port) for port_name, port in extension_ref.ports.items(): # if port_name not in extension_port_name: c.add_port(f"{i}_{port_name}", port=port) c.auto_rename_ports() return c if __name__ == "__main__": import gdsfactory as gf c = gf.components.mmi1x2() t = gf.partial(gf.c.taper, width2=0.1) cr = extend_ports_list(ports=c.get_ports_list(), extension_factory=t, extension_port_name="o1") c.add_ref(cr) c.show()
""" c = Component() c.info["spacing"] = spacing c.info["enclosure"] = enclosure c.info["size"] = size width, height = size a = width / 2 b = height / 2 c.add_polygon([(-a, -b), (a, -b), (a, b), (-a, b)], layer=layer) layers_cladding = layers_cladding or [] a = (width + cladding_offset) / 2 b = (height + cladding_offset) / 2 for layer in layers_cladding: c.add_polygon([(-a, -b), (a, -b), (a, b), (-a, b)], layer=layer) return c viac = gf.partial(via, layer=LAYER.VIAC) via1 = gf.partial(via, layer=LAYER.VIA1, enclosure=2) via2 = gf.partial(via, layer=LAYER.VIA2) if __name__ == "__main__": c = via() # c.pprint print(c) c.show()
cross_section .. code:: |<------width------>| ____________ ___________________ ______________ | | | undoped Si | | | |layer_heater| | intrinsic region |<----------->| layer_heater | |____________| |___________________| |______________| <------------> heater_gap heater_width """ import gdsfactory as gf from gdsfactory.components.contact import contact_npp from gdsfactory.components.straight_heater_doped_rib import straight_heater_doped_rib from gdsfactory.cross_section import strip_heater_doped straight_heater_doped_strip = gf.partial( straight_heater_doped_rib, cross_section_heater=strip_heater_doped, contact_contact=contact_npp, ) if __name__ == "__main__": # c = straight_heater_doped_strip(length=100) # c = test_straight_heater_doped_strip_ports() c = straight_heater_doped_strip(contact_contact=None) c.show()
from typing import Tuple import numpy as np import gdsfactory as gf from gdsfactory.add_grating_couplers import ( add_grating_couplers_with_loopback_fiber_array, ) from gdsfactory.component import Component from gdsfactory.config import CONFIG from gdsfactory.mask.write_labels import write_labels layer_label = (200, 0) add_te = gf.partial( gf.routing.add_fiber_array, grating_coupler=gf.components.grating_coupler_elliptical_te, layer_label=layer_label, ) add_tm = gf.partial( gf.routing.add_fiber_array, grating_coupler=gf.components.grating_coupler_elliptical_tm, bend_radius=20, layer_label=layer_label, ) @gf.cell def coupler_te( gap: float, length: int, ) -> Component:
def round_corners( points: Coordinates, straight: ComponentFactory = straight_function, bend: ComponentFactory = bend_euler, bend_s_factory: Optional[ComponentFactory] = bend_s, taper: Optional[ComponentFactory] = None, straight_fall_back_no_taper: Optional[ComponentFactory] = None, mirror_straight: bool = False, straight_ports: Optional[List[str]] = None, cross_section: CrossSectionFactory = strip, on_route_error: Callable = get_route_error, with_point_markers: bool = False, snap_to_grid_nm: Optional[int] = 1, **kwargs, ) -> Route: """Returns Route: - references list with rounded straight route from a list of manhattan points. - ports: Tuple of ports - length: route length (float) Args: points: manhattan route defined by waypoints bend90: the bend to use for 90Deg turns straight: the straight library to use to generate straight portions taper: taper for straight portions. If None, no tapering straight_fall_back_no_taper: in case there is no space for two tapers mirror_straight: mirror_straight waveguide straight_ports: port names for straights. If None finds them automatically. cross_section: on_route_error: function to run when route fails with_point_markers: add route points markers (easy for debugging) snap_to_grid_nm: nm to snap to grid kwargs: cross_section settings """ x = cross_section(**kwargs) points = (gf.snap.snap_to_grid(points, nm=snap_to_grid_nm) if snap_to_grid_nm else points) auto_widen = x.info.get("auto_widen", False) auto_widen_minimum_length = x.info.get("auto_widen_minimum_length", 200.0) taper_length = x.info.get("taper_length", 10.0) width = x.info.get("width", 2.0) width_wide = x.info.get("width_wide", None) references = [] bend90 = bend(cross_section=cross_section, ** kwargs) if callable(bend) else bend # bsx = bsy = _get_bend_size(bend90) taper = taper or taper_function( cross_section=cross_section, width1=width, width2=width_wide, length=taper_length, ) taper = taper(cross_section=cross_section, ** kwargs) if callable(taper) else taper # If there is a taper, make sure its length is known if taper and isinstance(taper, Component): if "length" not in taper.info: _taper_ports = list(taper.ports.values()) taper.info["length"] = _taper_ports[-1].x - _taper_ports[0].x straight_fall_back_no_taper = straight_fall_back_no_taper or straight # Remove any flat angle, otherwise the algorithm won't work points = remove_flat_angles(points) points = np.array(points) straight_sections = [] # (p0, angle, length) p0_straight = points[0] p1 = points[1] total_length = 0 # Keep track of the total path length if not hasattr(bend90.info, "length"): raise ValueError( f"bend {bend90} needs to have bend.info.length defined") bend_length = bend90.info.length dp = p1 - p0_straight bend_orientation = None if _is_vertical(p0_straight, p1): if dp[1] > 0: bend_orientation = 90 elif dp[1] < 0: bend_orientation = 270 elif _is_horizontal(p0_straight, p1): if dp[0] > 0: bend_orientation = 0 elif dp[0] < 0: bend_orientation = 180 if bend_orientation is None: return on_route_error(points=points, cross_section=x) layer = x.info["layer"] try: pname_west, pname_north = [ p.name for p in _get_bend_ports(bend=bend90, layer=layer) ] except ValueError as exc: raise ValueError( f"Did not find 2 ports on layer {layer}. Got {list(bend90.ports.values())}" ) from exc n_o_bends = points.shape[0] - 2 total_length += n_o_bends * bend_length previous_port_point = points[0] bend_points = [previous_port_point] # Add bend sections and record straight-section information for i in range(1, points.shape[0] - 1): bend_origin, rotation, x_reflection = _get_bend_reference_parameters( points[i - 1], points[i], points[i + 1], bend90, x.info["layer"]) bend_ref = gen_sref(bend90, rotation, x_reflection, pname_west, bend_origin) references.append(bend_ref) dx_points = points[i][0] - points[i - 1][0] dy_points = points[i][1] - points[i - 1][1] if abs(dx_points) < TOLERANCE: matching_ports = [ port for port in bend_ref.ports.values() if np.isclose(port.x, points[i][0]) ] if abs(dy_points) < TOLERANCE: matching_ports = [ port for port in bend_ref.ports.values() if np.isclose(port.y, points[i][1]) ] if matching_ports: next_port = matching_ports[0] other_port_name = set(bend_ref.ports.keys()) - {next_port.name} other_port = bend_ref.ports[list(other_port_name)[0]] bend_points.append(next_port.midpoint) bend_points.append(other_port.midpoint) previous_port_point = other_port.midpoint try: straight_sections += [( p0_straight, bend_orientation, get_straight_distance(p0_straight, bend_origin), )] except RouteError: on_route_error( points=(p0_straight, bend_origin), cross_section=x, references=references, ) p0_straight = bend_ref.ports[pname_north].midpoint bend_orientation = bend_ref.ports[pname_north].orientation bend_points.append(points[-1]) try: straight_sections += [( p0_straight, bend_orientation, get_straight_distance(p0_straight, points[-1]), )] except RouteError: on_route_error( points=(p0_straight, points[-1]), cross_section=x, references=references, ) # with_point_markers=True # print() # for i, point in enumerate(points): # print(i, point) # print() # for i, point in enumerate(bend_points): # print(i, point) # ensure bend connectivity for i, point in enumerate(points[:-1]): sx = np.sign(points[i + 1][0] - point[0]) sy = np.sign(points[i + 1][1] - point[1]) bsx = np.sign(bend_points[2 * i + 1][0] - bend_points[2 * i][0]) bsy = np.sign(bend_points[2 * i + 1][1] - bend_points[2 * i][1]) if bsx * sx == -1 or bsy * sy == -1: return on_route_error(points=points, cross_section=x, references=references) wg_refs = [] for straight_origin, angle, length in straight_sections: with_taper = False # wg_width = list(bend90.ports.values())[0].width length = snap_to_grid(length) total_length += length if auto_widen and length > auto_widen_minimum_length and width_wide: # Taper starts where straight would have started with_taper = True length = length - 2 * taper_length taper_origin = straight_origin pname_west, pname_east = [ p.name for p in _get_straight_ports(taper, layer=x.info["layer"]) ] taper_ref = taper.ref(position=taper_origin, port_id=pname_west, rotation=angle) references.append(taper_ref) wg_refs += [taper_ref] # Update start straight position straight_origin = taper_ref.ports[pname_east].midpoint # Straight waveguide kwargs_wide = kwargs.copy() kwargs_wide.update(width=width_wide) cross_section_wide = gf.partial(cross_section, **kwargs_wide) wg = straight(length=length, cross_section=cross_section_wide) else: wg = straight_fall_back_no_taper(length=length, cross_section=cross_section, **kwargs) if straight_ports is None: straight_ports = [ p.name for p in _get_straight_ports(wg, layer=x.info["layer"]) ] pname_west, pname_east = straight_ports wg_ref = wg.ref() wg_ref.move(wg.ports[pname_west], (0, 0)) if mirror_straight: wg_ref.reflect_v(list(wg_ref.ports.values())[0].name) wg_ref.rotate(angle) wg_ref.move(straight_origin) if length > 0: references.append(wg_ref) wg_refs += [wg_ref] port_index_out = 1 if with_taper: # Second taper: # Origin at end of straight waveguide, starting from east side of taper taper_origin = wg_ref.ports[pname_east] pname_west, pname_east = [ p.name for p in _get_straight_ports(taper, layer=x.info["layer"]) ] taper_ref = taper.ref( position=taper_origin, port_id=pname_east, rotation=angle + 180, v_mirror=True, ) # references += [ # gf.Label( # text=f"a{angle}", # position=taper_ref.center, # layer=2, # texttype=0, # ) # ] references.append(taper_ref) wg_refs += [taper_ref] port_index_out = 0 if with_point_markers: route = get_route_error(points, cross_section=x) references += route.references port_input = list(wg_refs[0].ports.values())[0] port_output = list(wg_refs[-1].ports.values())[port_index_out] length = snap_to_grid(float(total_length)) return Route(references=references, ports=(port_input, port_output), length=length)
""" __ _| |_ __ | | |_ _ | |__| |__| | _| |__ |dy |__| | __ | |_| |_ | | |_ - |__| |<-dx->| """ import gdsfactory as gf from gdsfactory.components.mmi2x2 import mmi2x2 from gdsfactory.components.mzi_phase_shifter import mzi_phase_shifter from gdsfactory.components.splitter_tree import splitter_tree mzi = gf.partial(mzi_phase_shifter, combiner=mmi2x2, delta_length=0) switch_tree = gf.partial(splitter_tree, coupler=mzi, spacing=(500, 100)) if __name__ == "__main__": # c = mzi() c = switch_tree(noutputs=16) c.show()
import gdsfactory as gf from gdsfactory.component import Component from gdsfactory.components.rectangle import rectangle from gdsfactory.components.triangle import triangle from gdsfactory.tech import LAYER from gdsfactory.types import ComponentFactory, Float2, Layer triangle_metal = gf.partial(triangle, layer=LAYER.M3, xtop=2) @gf.cell def dicing_lane( size: Float2 = (50, 300), marker: ComponentFactory = triangle_metal, layer_dicing: Layer = (100, 0), ) -> Component: """Dicing lane with triangular markers on both sides. Args: size: (tuple) Width and height of rectangle. marker: function to generate the dicing lane markers layer_dicing: Specific layer to put polygon geometry on. """ c = Component() r = c << rectangle(size=size, layer=layer_dicing) m = marker() mbr = c << m mbr.xmin = r.xmax