diff --git a/cspdk/base_cell.py b/cspdk/base_cell.py deleted file mode 100644 index db0fb81..0000000 --- a/cspdk/base_cell.py +++ /dev/null @@ -1,37 +0,0 @@ -from collections.abc import Callable -from functools import partial -from typing import TypeVar - -import gdsfactory as gf -from kfactory import KCell - -F = TypeVar("F", bound=Callable[..., gf.Component] | partial[KCell]) - -# NOTE: in an upcoming version of kfactory cells will have a cell.factory_name -# property we'll have to start using that property everywhere in gdsfactory in -# stead of cell.function_name or cell.__name__ to ensure cells of partials get -# correctly registered. For now this slight hack works as well. - - -def base_cell(name: str, func: F, /) -> F: - if not isinstance(name, str): - raise ValueError( - "The first argument of `base_cell` should be a string " - "specifying the name of the function / factory. The given " - f"argument {name!r} is not a string." - ) - if not callable(func): - raise ValueError( - "The second argument of `base_cell` should be the function " - f"or partial being decorated. The given argument {func!r} " - "is not callable." - ) - - # this will ensure the .function_name attribute is correctly set. - func.__name__ = name # type: ignore - - # this is for testing purposes only. We want to ensure all partials - # in the Pdk are partials of a base cell. - func._base_cell = True # type: ignore - - return gf.cell(func) # type: ignore diff --git a/cspdk/si500/cells.py b/cspdk/si500/cells.py index 666201a..69cb868 100644 --- a/cspdk/si500/cells.py +++ b/cspdk/si500/cells.py @@ -7,7 +7,6 @@ from gdsfactory.port import Port from gdsfactory.typings import Component, ComponentSpec, CrossSectionSpec, LayerSpec -from cspdk.base_cell import base_cell from cspdk.si500.tech import LAYER ################ @@ -273,115 +272,22 @@ def taper( # MMIs ################ @gf.cell -def mmi1x2( - width: float | None = None, - width_taper: float = 1.5, - length_taper: float = 20.0, - length_mmi: float = 37.5, - width_mmi: float = 6.0, - gap_mmi: float = 1.47, - taper: ComponentSpec = taper, - straight: ComponentSpec = straight, - cross_section: CrossSectionSpec = "xs_rc", -) -> Component: - r"""1x2 MultiMode Interferometer (MMI). - - Args: - width: input and output straight width. Defaults to cross_section width. - width_taper: interface between input straights and mmi region. - length_taper: into the mmi region. - length_mmi: in x direction. - width_mmi: in y direction. - gap_mmi: gap between tapered wg. - taper: taper function. - straight: straight function. - cross_section: specification (CrossSection, string or dict). - - - .. code:: - - length_mmi - <------> - ________ - | | - | \__ - | __ o2 - __/ /_ _ _ _ - o1 __ | _ _ _ _| gap_mmi - \ \__ - | __ o3 - | / - |________| - - <-> - length_taper - - """ - c = Component() - gap_mmi = gf.snap.snap_to_grid(gap_mmi, grid_factor=2) - x = gf.get_cross_section(cross_section) - xs_mmi = gf.get_cross_section(cross_section, width=width_mmi) - width = width or x.width - - _taper = gf.get_component( - taper, - length=length_taper, - width1=width, - width2=width_taper, - cross_section=cross_section, +def mmi1x2() -> Component: + """1x2 MultiMode Interferometer (MMI).""" + return gf.c.mmi1x2( + width_taper=1.5, + length_taper=20.0, + length_mmi=37.5, + width_mmi=6.0, + gap_mmi=1.47, + taper=taper, + straight=straight, + cross_section="xs_rc", ) - a = gap_mmi / 2 + width_taper / 2 - _ = c << gf.get_component(straight, length=length_mmi, cross_section=xs_mmi) - - ports = [ - gf.Port( - "o1", - orientation=180, - center=(0, 0), - width=width_taper, - layer=x.layer, - cross_section=x, - ), - gf.Port( - "o2", - orientation=0, - center=(+length_mmi, +a), - width=width_taper, - layer=x.layer, - cross_section=x, - ), - gf.Port( - "o3", - orientation=0, - center=(+length_mmi, -a), - width=width_taper, - layer=x.layer, - cross_section=x, - ), - ] - - for port in ports: - taper_ref = c << _taper - taper_ref.connect(port="o2", other=port, allow_width_mismatch=True) - c.add_port(name=port.name, port=taper_ref.ports["o1"]) - - c.flatten() - return c - @gf.cell -def mmi2x2( - width: float | None = None, - width_taper: float = 1.5, - length_taper: float = 50.2, - length_mmi: float = 5.5, - width_mmi: float = 6.0, - gap_mmi: float = 0.4, - taper: ComponentSpec = taper, - straight: ComponentSpec = straight, - cross_section: CrossSectionSpec = "strip", -) -> Component: +def mmi2x2() -> Component: r"""Mmi 2x2. Args: @@ -415,52 +321,18 @@ def mmi2x2( length_taper """ - c = gf.Component() - gap_mmi = gf.snap.snap_to_grid(gap_mmi, grid_factor=2) - w_taper = width_taper - x = gf.get_cross_section(cross_section) - width = width or x.width - - _taper = gf.get_component( - taper, - length=length_taper, - width1=width, - width2=w_taper, - cross_section=cross_section, - ) - - a = gap_mmi / 2 + width_taper / 2 - _ = c << gf.get_component( - straight, length=length_mmi, width=width_mmi, cross_section=cross_section + return gf.c.mmi2x2( + width=None, + width_taper=1.5, + length_taper=50.2, + length_mmi=5.5, + width_mmi=6.0, + gap_mmi=0.4, + taper=taper, + straight=straight, + cross_section="xs_rc", ) - ports = [ - gf.Port("o1", orientation=180, center=(0, -a), width=w_taper, cross_section=x), - gf.Port("o2", orientation=180, center=(0, +a), width=w_taper, cross_section=x), - gf.Port( - "o3", - orientation=0, - center=(length_mmi, +a), - width=w_taper, - cross_section=x, - ), - gf.Port( - "o4", - orientation=0, - center=(length_mmi, -a), - width=w_taper, - cross_section=x, - ), - ] - - for port in ports: - taper_ref = c << _taper - taper_ref.connect(port="o2", other=port, allow_width_mismatch=True) - c.add_port(name=port.name, port=taper_ref.ports["o1"]) - - c.flatten() - return c - ############################## # Evanescent couplers @@ -789,31 +661,15 @@ def grating_coupler_elliptical( # MZI ################ -# TODO: (needs gdsfactory fix) currently function arguments need to be -# supplied as ComponentSpec strings, because when supplied as function they get -# serialized weirdly in the netlist - -mzi = base_cell( - "mzi", - partial( - gf.components.mzi, - delta_length=10.0, - length_y=2.0, - length_x=0.1, - port_e1_splitter="o2", - port_e0_splitter="o3", - port_e1_combiner="o3", - port_e0_combiner="o4", - bend="bend_euler", - straight="straight", - splitter="mmi1x2", - combiner="mmi2x2", - cross_section="xs_rc", - ), -) - -mzi_rc = partial( - mzi, +_mzi = partial( + gf.components.mzi, + delta_length=10.0, + length_y=2.0, + length_x=0.1, + port_e1_splitter="o2", + port_e0_splitter="o3", + port_e1_combiner="o3", + port_e0_combiner="o4", bend="bend_euler", straight="straight", splitter="mmi1x2", @@ -822,11 +678,32 @@ def grating_coupler_elliptical( ) +@gf.cell +def mzi_rc( + delta_length: float = 10.0, + length_y: float = 2.0, + length_x: float = 0.1, +) -> gf.Component: + return _mzi( + bend="bend_euler", + straight="straight", + splitter="mmi1x2", + combiner="mmi2x2", + cross_section="xs_rc", + delta_length=delta_length, + length_y=length_y, + length_x=length_x, + ) + + ################ # Packaging ################ +@gf.cell +def pad(size=(100.0, 100.0)) -> gf.Component: + return gf.c.pad(size=size, layer="PAD") + -pad = partial(gf.c.pad, layer="PAD", size=(100.0, 100.0)) rectangle = partial(gf.components.rectangle, layer=LAYER.FLOORPLAN) grating_coupler_array = partial( gf.components.grating_coupler_array, diff --git a/cspdk/sin300/cells.py b/cspdk/sin300/cells.py index 6002820..26fddce 100644 --- a/cspdk/sin300/cells.py +++ b/cspdk/sin300/cells.py @@ -5,7 +5,6 @@ from gdsfactory.port import Port from gdsfactory.typings import Component, CrossSectionSpec -from cspdk.base_cell import base_cell from cspdk.sin300.tech import LAYER ################ @@ -281,57 +280,61 @@ def taper( # MMIs ################ -mmi1x2 = base_cell( - "mmi1x2", - partial( - gf.components.mmi1x2, - cross_section="xs_nc", - width_mmi=12.0, - width_taper=5.5, - length_taper=50.0, - ), -) -mmi1x2_no = partial( - mmi1x2, - cross_section="xs_no", - length_mmi=42.0, - gap_mmi=0.4, -) - -mmi1x2_nc = partial( - mmi1x2, +_mmi1x2 = partial( + gf.components.mmi1x2, cross_section="xs_nc", - length_mmi=64.7, - gap_mmi=0.4, + width_mmi=12.0, + width_taper=5.5, + length_taper=50.0, ) -mmi2x2 = base_cell( - "mmi2x2", - partial( - gf.c.mmi2x2, + +@gf.cell +def mmi1x2_no() -> gf.Component: + return _mmi1x2( + cross_section="xs_no", + length_mmi=42.0, + gap_mmi=0.4, + ) + + +@gf.cell +def mmi1x2_nc() -> gf.Component: + return _mmi1x2( cross_section="xs_nc", - width_mmi=12.0, - width_taper=5.5, - length_taper=50.0, - ), -) + length_mmi=64.7, + gap_mmi=0.4, + ) -mmi2x2_no = partial( - mmi2x2, - cross_section="xs_no", - length_taper=50.0, - length_mmi=126.0, - gap_mmi=0.4, -) -mmi2x2_nc = partial( - mmi2x2, +_mmi2x2 = partial( + gf.c.mmi2x2, cross_section="xs_nc", - length_mmi=232.0, - gap_mmi=0.4, + width_mmi=12.0, + width_taper=5.5, + length_taper=50.0, ) +@gf.cell +def mmi2x2_no() -> gf.Component: + return _mmi2x2( + cross_section="xs_no", + length_taper=50.0, + length_mmi=126.0, + gap_mmi=0.4, + ) + + +@gf.cell +def mmi2x2_nc() -> gf.Component: + return _mmi2x2( + cross_section="xs_nc", + length_mmi=232.0, + gap_mmi=0.4, + ) + + ############################## # Evanescent couplers ############################## @@ -404,75 +407,68 @@ def coupler( ############################## # grating couplers Rectangular ############################## - -grating_coupler_rectangular = base_cell( - "grating_coupler_rectangular", - partial( - gf.components.grating_coupler_rectangular, - n_periods=30, - fill_factor=0.5, - length_taper=200.0, - fiber_angle=20.0, - layer_grating=LAYER.NITRIDE_ETCH, - layer_slab=LAYER.NITRIDE, - slab_offset=0.0, - period=0.75, - width_grating=11.0, - polarization="te", - wavelength=1.55, - slab_xmin=-1.0, - cross_section="xs_nc", - ), +_grating_coupler_rectangular = partial( + gf.components.grating_coupler_rectangular, + n_periods=30, + fill_factor=0.5, + length_taper=200.0, + fiber_angle=20.0, + layer_grating=LAYER.NITRIDE_ETCH, + layer_slab=LAYER.NITRIDE, + slab_offset=0.0, + period=0.75, + width_grating=11.0, + polarization="te", + wavelength=1.55, + slab_xmin=-1.0, + cross_section="xs_nc", ) -grating_coupler_rectangular_nc = partial( - grating_coupler_rectangular, - period=0.66, - cross_section="xs_nc", -) +@gf.cell +def grating_coupler_rectangular_nc(): + return _grating_coupler_rectangular(period=0.66, cross_section="xs_nc") + + +@gf.cell +def grating_coupler_rectangular_no(): + return _grating_coupler_rectangular(period=0.964, cross_section="xs_no") -grating_coupler_rectangular_no = partial( - grating_coupler_rectangular, - period=0.964, - cross_section="xs_no", -) ############################## # grating couplers elliptical ############################## -grating_coupler_elliptical = base_cell( - "grating_coupler_elliptical", - partial( - gf.components.grating_coupler_elliptical_trenches, - polarization="te", - taper_length=16.6, - taper_angle=30.0, - wavelength=1.55, - fiber_angle=20.0, - grating_line_width=0.343, - neff=1.6, - ncladding=1.443, - layer_trench=LAYER.GRA, - p_start=26, - n_periods=30, - end_straight_length=0.2, - cross_section="xs_nc", - ), -) - -grating_coupler_elliptical_nc = partial( - grating_coupler_elliptical, +_grating_coupler_elliptical = partial( + gf.components.grating_coupler_elliptical_trenches, + polarization="te", + taper_length=16.6, + taper_angle=30.0, + wavelength=1.55, + fiber_angle=20.0, + grating_line_width=0.343, + neff=1.6, + ncladding=1.443, + layer_trench=LAYER.GRA, + p_start=26, + n_periods=30, + end_straight_length=0.2, cross_section="xs_nc", - grating_line_width=0.66 / 2, ) -grating_coupler_elliptical_no = partial( - grating_coupler_elliptical, - grating_line_width=0.964 / 2, - cross_section="xs_no", -) + +@gf.cell +def grating_coupler_elliptical_nc(): + return _grating_coupler_elliptical( + cross_section="xs_nc", grating_line_width=0.66 / 2 + ) + + +@gf.cell +def grating_coupler_elliptical_no(): + return _grating_coupler_elliptical( + grating_line_width=0.964 / 2, cross_section="xs_no" + ) ################ @@ -483,57 +479,72 @@ def coupler( # supplied as ComponentSpec strings, because when supplied as function they get # serialized weirdly in the netlist -mzi = base_cell( - "mzi", - partial( - gf.components.mzi, - delta_length=10.0, - length_y=2.0, - length_x=0.1, - port_e1_splitter="o2", - port_e0_splitter="o3", - port_e1_combiner="o3", - port_e0_combiner="o4", - bend="bend_nc", - straight="straight_nc", - splitter="mmi1x2_nc", - combiner="mmi2x2_nc", - cross_section="xs_nc", - ), -) - -mzi_nc = partial( - mzi, - straight="straight_nc", +_mzi = partial( + gf.components.mzi, + delta_length=10.0, + length_y=2.0, + length_x=0.1, + port_e1_splitter="o2", + port_e0_splitter="o3", + port_e1_combiner="o3", + port_e0_combiner="o4", bend="bend_nc", + straight="straight_nc", splitter="mmi1x2_nc", combiner="mmi2x2_nc", cross_section="xs_nc", ) -mzi_no = partial( - mzi, - straight="straight_no", - bend="bend_no", - splitter="mmi1x2_no", - combiner="mmi2x2_no", - cross_section="xs_no", -) + +@gf.cell +def mzi_nc( + delta_length: float = 10.0, + length_y: float = 2.0, + length_x: float = 0.1, +) -> gf.Component: + return _mzi( + bend="bend_nc", + straight="straight", + splitter="mmi1x2_nc", + combiner="mmi2x2_nc", + cross_section="xs_nc", + delta_length=delta_length, + length_y=length_y, + length_x=length_x, + ) + + +@gf.cell +def mzi_no( + delta_length: float = 10.0, + length_y: float = 2.0, + length_x: float = 0.1, +) -> gf.Component: + return _mzi( + bend="bend_no", + straight="straight", + splitter="mmi1x2_no", + combiner="mmi2x2_no", + cross_section="xs_no", + delta_length=delta_length, + length_y=length_y, + length_x=length_x, + ) ################ # Packaging ################ +@gf.cell +def pad(size=(100.0, 100.0)) -> gf.Component: + return gf.c.pad(size=size, layer="PAD") -pad = base_cell("pad", partial(gf.c.pad, layer="PAD", size=(100.0, 100.0))) -rectangle = base_cell( - "rectangle", partial(gf.components.rectangle, layer=LAYER.FLOORPLAN) -) -grating_coupler_array = base_cell( - "grating_coupler_array", - partial( - gf.components.grating_coupler_array, +rectangle = partial(gf.components.rectangle, layer=LAYER.FLOORPLAN) + + +def grating_coupler_array() -> gf.Component: + return gf.components.grating_coupler_array( pitch=127, n=6, port_name="o1", @@ -541,8 +552,7 @@ def coupler( with_loopback=False, grating_coupler="grating_coupler_rectangular_nc", cross_section="xs_nc", - ), -) + ) _die = partial( @@ -568,7 +578,7 @@ def die_no(): return _die(grating_coupler="grating_coupler_rectangular_no", cross_section="xs_no") -array = base_cell("array", partial(gf.components.array)) +array = partial(gf.components.array) if __name__ == "__main__":