diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ea52e5e..8f5e6d0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,141 +1,39 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: "0122e76bfe37d895fa9085712e65dbfef2e349b1" + rev: d2bd9cd497c81622c3f5774b336ab451691f1c36 hooks: - - id: check-added-large-files - - id: check-case-conflict - - id: check-merge-conflict - - id: check-symlinks - id: check-yaml - - id: debug-statements + exclude: ^(conda\.recipe/meta\.yaml|conda_build/templates/.*\.yaml|docs/click/meta\.yaml|conda/meta\.yaml|conda/construct.yaml|.*\.pic\.yml|conda/constructor/Miniforge3/construct.yaml) - id: end-of-file-fixer - - id: mixed-line-ending - - id: name-tests-test - args: ["--pytest-test-first"] - id: trailing-whitespace - # - repo: https://github.com/hakancelik96/unimport - # rev: 0.14.1 - # hooks: - # - id: unimport - # args: [--remove, --include-star-import] - # - repo: https://github.com/pycqa/isort - # rev: "3a72e069635a865a92b8a0273aa829f630cbcd6f" - # hooks: - # - id: isort - # files: "demo_project/.*" - # args: ["--profile", "black", "--filter-files"] - - repo: https://github.com/psf/black - rev: "eb32729ab562c010d9f644a3bbb2305196b2deb7" + rev: 1b028cc9d99c2c2e82f9b727742539173a92a373 hooks: - id: black + # exclude: '^gdsfactory/samples/notebooks/|^docs/notebooks/' - # - repo: https://github.com/pycqa/flake8 - # rev: "647996c743f9e77368ce46cc74abe98549dd4c3a" - # hooks: - # - id: flake8 - - # - repo: https://github.com/kynan/nbstripout - # rev: e4c5b4dcbab4afa0b88b7a9243db42b1a8d95dde - # hooks: - # - id: nbstripout - # files: ".ipynb" - - - repo: https://github.com/asottile/pyupgrade - rev: v3.3.2 + - repo: https://github.com/codespell-project/codespell + rev: 38bc4a97f6e22827e86526148efa38f1044a97f8 hooks: - - id: pyupgrade - args: [--py37-plus, --keep-runtime-typing] + - id: codespell + additional_dependencies: + - tomli - # - repo: https://github.com/codespell-project/codespell - # rev: 68ea3cff5eba266e0814794cce6cd19537f58137 - # hooks: - # - id: codespell - # args: ["-L TE,TE/TM,te,ba,FPR,fpr_spacing,ro,donot"] - - - repo: https://github.com/shellcheck-py/shellcheck-py - rev: ee7a347451760f817260ca3cafae4e3bec06bc84 + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: "6c0ceaccffa1ebb1db1ea1a6d7289b50d29bfce2" hooks: - - id: shellcheck - - # - repo: https://github.com/pre-commit/pygrep-hooks - # rev: 7b4409161486c6956bb3206ce96db5d56731b1b9 # Use the ref you want to point at - # hooks: - # - id: python-use-type-annotations + - id: ruff + args: [ --fix, --exit-non-zero-on-fix ] - - repo: https://github.com/PyCQA/bandit - rev: 45619e0c8325fad08f0cbd74034e5161a16b1b4f + - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.10.0 hooks: - - id: bandit - args: [--exit-zero] - # ignore all tests, not just tests data - exclude: ^tests/ - # - repo: https://github.com/pre-commit/mirrors-mypy - # rev: "961f38dddd22ebfc8338e1244352afdc71ee6771" - # hooks: - # - id: mypy - # exclude: ^(docs/|example-plugin/|tests/fixtures) - # additional_dependencies: - # - "pydantic" - # - repo: https://github.com/terrencepreilly/darglint - # rev: master - # hooks: - # - id: darglint - # - repo: https://github.com/pycqa/pydocstyle - # rev: "a6fe4222012e990042c86cdaaa904a8d059752ee" - # hooks: - # - id: pydocstyle - # additional_dependencies: ["pydocstyle[toml]"] - # - repo: https://github.com/asottile/reorder_python_imports - # rev: 2b2f0c74acdb3de316e23ceb7dd0d7945c354050 - # hooks: - # - id: reorder-python-imports - # - repo: https://github.com/PyCQA/pylint - # rev: v2.14.1 - # hooks: - # - id: pylint - # args: [--exit-zero] - # - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - # rev: 6565d773ca281682d7062d4c0be74538cc474cc9 - # hooks: - # - id: pretty-format-java - # args: [--autofix] - # - id: pretty-format-kotlin - # args: [--autofix] - # - id: pretty-format-yaml - # args: [--autofix, --indent, "2"] - # - repo: https://github.com/adrienverge/yamllint.git - # rev: v1.21.0 # or higher tag - # hooks: - # - id: yamllint - # args: [--format, parsable, --strict] - # - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt - # rev: 0.1.0 # or specific tag - # hooks: - # - id: yamlfmt - # - repo: https://github.com/pre-commit/pygrep-hooks - # rev: "f6fb13e9516d1a9720a30a4049c930235abd642e" - # hooks: - # - id: python-check-blanket-noqa - # - id: python-check-blanket-type-ignore - # - id: python-no-log-warn - # - id: python-no-eval - # - id: python-use-type-annotations - # - id: rst-backticks - # - id: rst-directive-colons - # - id: rst-inline-touching-normal - # - repo: https://github.com/nbQA-dev/nbQA - # rev: 952c895a21aced4601165c43f77188559a5e825c - # hooks: - # - id: nbqa-black - # additional_dependencies: [jupytext, black] # optional, only if you're using Jupytext - # - id: nbqa-pyupgrade - # args: ["--py37-plus"] - # - id: nbqa-flake8 - # - id: nbqa-isort - # args: ["--float-to-top"] - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: "9e466ccca34e1b6b1e3a160152db786b8bc4c788" + - id: pretty-format-toml + args: [--autofix] + + - repo: https://github.com/aristanetworks/j2lint.git + rev: v1.1.0 hooks: - - id: ruff + - id: j2lint + args: [--ignore, jinja-statements-delimiter, jinja-statements-indentation, --] diff --git a/Makefile b/Makefile index 0b0578a..4a20a63 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,9 @@ install: - pip install -e .[dev] - pre-commit install - -dev: pip install -e .[dev,docs] pip install git+https://github.com/gdsfactory/kfactory.git +dev: install + test: pytest -s @@ -33,7 +31,6 @@ update-pre: git-rm-merged: git branch -D `git branch --merged | grep -v \* | xargs` - release: git push git push origin --tags @@ -43,12 +40,6 @@ build: pip install build python -m build -jupytext: - jupytext docs/**/*.ipynb --to py - -notebooks: - jupytext docs/**/*.py --to ipynb - docs: jb build docs diff --git a/docs/write_cells.py b/docs/write_cells.py index 369772e..699a015 100644 --- a/docs/write_cells.py +++ b/docs/write_cells.py @@ -1,9 +1,10 @@ import inspect import pathlib + import numpy as np +from kfactory.kcell import Any, Callable, KCell, LayerEnum, clean_name + from kgeneric.tests.test_cells import cell_factories as cells -from kfactory.kcell import KCell, Any, clean_name, Callable -from kfactory.kcell import LayerEnum def dict2name(prefix: str = "", **kwargs) -> str: @@ -34,7 +35,7 @@ def clean_value_json( return value.name elif type(value) in [float, np.float64]: # float return np.round(value, 3) - elif isinstance(value, (tuple, list)): + elif isinstance(value, tuple | list): return value elif isinstance(value, dict): return dict2name(**value) @@ -78,7 +79,7 @@ def clean_value_json( [ f"{p}={repr(clean_value_json(sig.parameters[p].default))}" for p in sig.parameters - if isinstance(sig.parameters[p].default, (int, float, str, tuple)) + if isinstance(sig.parameters[p].default, int | float | str | tuple) and p not in skip_settings ] ) diff --git a/docs/write_cells_jupyter.py b/docs/write_cells_jupyter.py index c53e1f0..ef53c63 100644 --- a/docs/write_cells_jupyter.py +++ b/docs/write_cells_jupyter.py @@ -2,7 +2,9 @@ import inspect import pathlib + from kfactory.kcell import clean_value + from kgeneric import cells_dict as cells filepath = pathlib.Path(__file__).parent.absolute() / "cells.py" @@ -50,7 +52,7 @@ [ f"{p}={repr(clean_value(sig.parameters[p].default))}" for p in sig.parameters - if isinstance(sig.parameters[p].default, (int, float, str, tuple)) + if isinstance(sig.parameters[p].default, int | float | str | tuple) and p not in skip_settings ] ) diff --git a/kgeneric/__init__.py b/kgeneric/__init__.py index eaabc58..52f8857 100644 --- a/kgeneric/__init__.py +++ b/kgeneric/__init__.py @@ -3,12 +3,12 @@ __version__ = "0.0.2" from kfactory.pdk import Pdk, get_cells -from kgeneric.pdk import LAYER -from kgeneric import cells +from kgeneric import cells, gpdk, layers +from kgeneric.layers import LAYER +from kgeneric.tech import TECH - -cells_dict = get_cells([cells]) +cells_dict = get_cells([gpdk]) pdk = Pdk(name="generic", cell_factories=cells_dict, layers=LAYER) -__all__ = ("pdk", "cells") +__all__ = ("pdk", "gpdk", "cells", "layers", "TECH") diff --git a/kgeneric/cells/__init__.py b/kgeneric/cells/__init__.py index acbe66e..f478936 100644 --- a/kgeneric/cells/__init__.py +++ b/kgeneric/cells/__init__.py @@ -1,13 +1,15 @@ # flake8: noqa -from .bezier import bend_s -from .circular import bend_circular -from .coupler import coupler, straight_coupler -from .euler import bend_euler, bend_s_euler -from .grating_coupler_elliptical import grating_coupler_elliptical -from .mzi import mzi -from .taper import taper -from .straight import straight +from kgeneric.cells.bezier import bend_s +from kgeneric.cells.circular import bend_circular +from kgeneric.cells.coupler import coupler, straight_coupler +from kgeneric.cells.euler import bend_euler, bend_s_euler +from kgeneric.cells.grating_coupler_elliptical import grating_coupler_elliptical +from kgeneric.cells.mzi import mzi +from kgeneric.cells.taper import taper +from kgeneric.cells.straight import straight, straight_dbu +from kgeneric.cells.dbu.taper import taper as taper_dbu + __all__ = [ "bend_circular", @@ -18,6 +20,8 @@ "grating_coupler_elliptical", "mzi", "straight", + "straight_dbu", "straight_coupler", "taper", + "taper_dbu", ] diff --git a/kgeneric/cells/bezier.py b/kgeneric/cells/bezier.py index f9569e1..44333c4 100644 --- a/kgeneric/cells/bezier.py +++ b/kgeneric/cells/bezier.py @@ -4,11 +4,9 @@ import numpy as np import numpy.typing as nty -from scipy.special import binom # type: ignore[import] - from kfactory import KCell, LayerEnum, cell, kdb -from kfactory.utils.enclosure import LayerEnclosure -from kfactory.utils.enclosure import extrude_path +from kfactory.utils.enclosure import LayerEnclosure, extrude_path +from scipy.special import binom # type: ignore[import] __all__ = ["bend_s"] @@ -93,8 +91,8 @@ def bend_s( if __name__ == "__main__": - from kgeneric.pdk import LAYER from kgeneric import pdk + from kgeneric.pdk import LAYER um = 1 / pdk.kcl.dbu enclosure = LayerEnclosure( diff --git a/kgeneric/cells/circular.py b/kgeneric/cells/circular.py index 29ee744..db48515 100644 --- a/kgeneric/cells/circular.py +++ b/kgeneric/cells/circular.py @@ -4,11 +4,9 @@ """ import numpy as np - from kfactory import kdb from kfactory.kcell import KCell, LayerEnum, cell -from kfactory.utils.enclosure import LayerEnclosure -from kfactory.utils.enclosure import extrude_path +from kfactory.utils.enclosure import LayerEnclosure, extrude_path __all__ = ["bend_circular"] diff --git a/kgeneric/cells/coupler.py b/kgeneric/cells/coupler.py index 7d1aacf..eef367e 100644 --- a/kgeneric/cells/coupler.py +++ b/kgeneric/cells/coupler.py @@ -1,14 +1,10 @@ -from typing import Union - from kfactory import KCell, cell, kdb - from kfactory.kcell import LayerEnum - from kfactory.utils.enclosure import LayerEnclosure -from kgeneric.pdk import LAYER from kgeneric.cells.bezier import bend_s from kgeneric.cells.straight import straight +from kgeneric.layers import LAYER @cell @@ -18,10 +14,11 @@ def coupler( dy: float = 5.0, dx: float = 5.0, width: float = 0.5, - layer: Union[int, LayerEnum] = LAYER.WG, + layer: int | LayerEnum = LAYER.WG, enclosure: LayerEnclosure = LayerEnclosure(), ) -> KCell: r"""Symmetric coupler. + Args: gap: between straights in um. length: of coupling region in um. @@ -29,6 +26,7 @@ def coupler( dx: length of bend in x direction in um. layer: layer number or name. enclosure: straight enclosure. + .. code:: dx dx |------| |------| @@ -95,7 +93,7 @@ def straight_coupler( gap: float = 0.2, length: float = 10.0, width: float = 0.5, - layer: Union[int, LayerEnum] = LAYER.WG, + layer: int | LayerEnum = LAYER.WG, enclosure: LayerEnclosure = LayerEnclosure(), ) -> KCell: """Straight coupler. diff --git a/kgeneric/cells/dbu/__init__.py b/kgeneric/cells/dbu/__init__.py index e205921..0ab7e27 100644 --- a/kgeneric/cells/dbu/__init__.py +++ b/kgeneric/cells/dbu/__init__.py @@ -1,4 +1,4 @@ -from .taper import taper from .straight import straight +from .taper import taper __all__ = ["straight", "taper"] diff --git a/kgeneric/cells/dbu/straight.py b/kgeneric/cells/dbu/straight.py index 05f31a2..7faab12 100644 --- a/kgeneric/cells/dbu/straight.py +++ b/kgeneric/cells/dbu/straight.py @@ -16,6 +16,7 @@ """ from kfactory import KCell, LayerEnum, cell, kdb +from kfactory.kcell import Info from kfactory.utils import LayerEnclosure __all__ = ["straight"] @@ -60,11 +61,14 @@ def straight( if enclosure is not None: enclosure.apply_minkowski_y(c, layer) - c.info = { - "width_um": width * c.kcl.dbu, - "length_um": length * c.kcl.dbu, - "layer": layer, - } + c.info = Info( + **{ + "width_um": width * c.kcl.dbu, + "length_um": length * c.kcl.dbu, + "width_dbu": width, + "length_dbu": length, + } + ) c.autorename_ports() return c diff --git a/kgeneric/cells/euler.py b/kgeneric/cells/euler.py index c0e517d..e380cea 100644 --- a/kgeneric/cells/euler.py +++ b/kgeneric/cells/euler.py @@ -6,13 +6,11 @@ """ import numpy as np -from scipy.optimize import brentq # type: ignore[import] -from scipy.special import fresnel # type: ignore[import] - from kfactory import kdb from kfactory.kcell import KCell, LayerEnum, cell -from kfactory.utils.enclosure import LayerEnclosure -from kfactory.utils.enclosure import extrude_path +from kfactory.utils.enclosure import LayerEnclosure, extrude_path +from scipy.optimize import brentq # type: ignore[import] +from scipy.special import fresnel # type: ignore[import] __all__ = [ "euler_bend_points", @@ -192,34 +190,19 @@ def bend_euler( end_angle=angle, ) - if angle == 90: - c.create_port( - name="W0", - layer=layer, - width=int(width / c.kcl.dbu), - trans=kdb.Trans(2, False, backbone[0].to_itype(dbu).to_v()), - ) - c.create_port( - name="N0", - layer=layer, - width=int(width / c.kcl.dbu), - trans=kdb.Trans(1, False, backbone[-1].to_itype(dbu).to_v()), - ) - elif angle == 180: - c.create_port( - name="W0", - layer=layer, - width=int(width / c.kcl.dbu), - trans=kdb.Trans(2, False, backbone[0].to_itype(dbu).to_v()), - ) - c.create_port( - name="W1", - layer=layer, - width=int(width / c.kcl.dbu), - trans=kdb.Trans(2, False, backbone[-1].to_itype(dbu).to_v()), - ) - - c.info["sim"] = "FDTD" + c.create_port( + layer=layer, + width=int(width / c.kcl.dbu), + trans=kdb.Trans(2, False, backbone[0].to_itype(dbu).to_v()), + ) + + c.create_port( + dcplx_trans=kdb.DCplxTrans(1, angle, False, backbone[-1].to_v()), + dwidth=width, + layer=layer, + ) + + c.autorename_ports() return c diff --git a/kgeneric/cells/grating_coupler_elliptical.py b/kgeneric/cells/grating_coupler_elliptical.py index dde551a..daaba8c 100644 --- a/kgeneric/cells/grating_coupler_elliptical.py +++ b/kgeneric/cells/grating_coupler_elliptical.py @@ -1,10 +1,10 @@ -from typing import Literal, Optional from functools import partial +from typing import Literal +import kfactory as kf import numpy as np -import kfactory as kf -from kgeneric.pdk import LAYER +from kgeneric.layers import LAYER nm = 1e-3 @@ -20,14 +20,14 @@ def grating_coupler_elliptical( grating_line_width: float = 0.343, wg_width: float = 500 * nm, neff: float = 2.638, # tooth effective index - layer_taper: Optional[LAYER] = LAYER.WG, + layer_taper: LAYER | None = LAYER.WG, layer_trench: LAYER = LAYER.UNDERCUT, p_start: int = 26, n_periods: int = 30, taper_offset: int = 0, taper_extent_n_periods: float | Literal["first"] | Literal["last"] = "last", - period: Optional[int] = None, - x_fiber_launch: Optional[int] = None, + period: int | None = None, + x_fiber_launch: int | None = None, clad_index: float = 1.443, # cladding index ) -> kf.KCell: """Returns elliptical grating coupler. @@ -162,31 +162,33 @@ def grating_tooth( angle_max = taper_angle / 2 backbone_points = ellipse_arc(ap, bp, xp, angle_min, angle_max, angle_step) - if spiked: - spike_length = width // 3 - path = kf.kdb.DPath(backbone_points, width).polygon() - edges = kf.kdb.Edges([path.to_itype(kf.kcl.dbu)]) - bb_edges = kf.kdb.Edges( - [ - kf.kdb.DEdge(backbone_points[0], backbone_points[1]).to_itype( - kf.kcl.dbu - ), - kf.kdb.DEdge(backbone_points[-1], backbone_points[-2]).to_itype( - kf.kcl.dbu - ), - ] - ) - border_edges = edges.interacting(bb_edges) - reg = kf.kdb.Region([path.to_itype(kf.kcl.dbu)]) - for edge in border_edges.each(): - shifted = edge.shifted(spike_length) - shifted_center = (shifted.p1 + shifted.p2.to_v()) / 2 - reg.insert(kf.kdb.Polygon([edge.p1, shifted_center, edge.p2])) - reg.merge() + return ( + _extracted_from_grating_tooth_15(width, backbone_points) + if spiked + else kf.kdb.Region(kf.kdb.Path(backbone_points, width)) + ) - else: - reg = kf.kdb.Region(kf.kdb.Path(backbone_points, width)) - return reg + +# TODO Rename this here and in `grating_tooth` +def _extracted_from_grating_tooth_15(width, backbone_points): + spike_length = width // 3 + path = kf.kdb.DPath(backbone_points, width).polygon() + edges = kf.kdb.Edges([path.to_itype(kf.kcl.dbu)]) + bb_edges = kf.kdb.Edges( + [ + kf.kdb.DEdge(backbone_points[0], backbone_points[1]).to_itype(kf.kcl.dbu), + kf.kdb.DEdge(backbone_points[-1], backbone_points[-2]).to_itype(kf.kcl.dbu), + ] + ) + border_edges = edges.interacting(bb_edges) + result = kf.kdb.Region([path.to_itype(kf.kcl.dbu)]) + for edge in border_edges.each(): + shifted = edge.shifted(spike_length) + shifted_center = (shifted.p1 + shifted.p2.to_v()) / 2 + result.insert(kf.kdb.Polygon([edge.p1, shifted_center, edge.p2])) + result.merge() + + return result def grating_taper_points( diff --git a/kgeneric/cells/mzi.py b/kgeneric/cells/mzi.py index 34895d2..bc848d4 100644 --- a/kgeneric/cells/mzi.py +++ b/kgeneric/cells/mzi.py @@ -1,5 +1,6 @@ +from collections.abc import Callable from functools import partial -from typing import Any, Callable, Optional +from typing import Any import kfactory as kf from kfactory import cell @@ -8,8 +9,8 @@ from kfactory.typings import CellSpec from kfactory.utils.enclosure import LayerEnclosure -from kgeneric.cells.dbu.straight import straight as straight_dbu from kgeneric.cells.coupler import coupler +from kgeneric.cells.dbu.straight import straight as straight_dbu from kgeneric.cells.euler import bend_euler from kgeneric.cells.straight import straight as straight_function @@ -18,14 +19,14 @@ def mzi( delta_length: float = 10.0, length_y: float = 2.0, - length_x: Optional[float] = 0.1, - bend_component: Callable[..., kf.KCell] = bend_euler, + length_x: float | None = 0.1, + bend: Callable[..., kf.KCell] = bend_euler, straight: CellSpec = straight_function, - straight_y: Optional[CellSpec] = None, - straight_x_top: Optional[CellSpec] = None, - straight_x_bot: Optional[CellSpec] = None, + straight_y: CellSpec | None = None, + straight_x_top: CellSpec | None = None, + straight_x_bot: CellSpec | None = None, splitter: CellSpec = coupler, - combiner: Optional[CellSpec] = None, + combiner: CellSpec | None = None, with_splitter: bool = True, port_e1_splitter: str = "o3", port_e0_splitter: str = "o4", @@ -33,10 +34,11 @@ def mzi( width: float = 1.0, layer: int | LayerEnum = 0, radius: float = 5.0, - enclosure: Optional[LayerEnclosure] = None, + enclosure: LayerEnclosure | None = None, **kwargs: Any, ) -> kf.KCell: """Mzi. + Args: delta_length: bottom arm vertical extra length. length_y: vertical length for both and top arms. @@ -97,7 +99,7 @@ def mzi( "radius": radius, "enclosure": enclosure, } - bend = kf.kcl.pdk.get_cell(bend_component, **bend_settings) + bend = kf.kcl.pdk.get_cell(bend, **bend_settings) c = kf.KCell() straight_connect = partial(straight_dbu, layer=layer, enclosure=enclosure) combiner_settings = { @@ -219,8 +221,8 @@ def mzi( if __name__ == "__main__": - from kgeneric.pdk import LAYER from kgeneric import pdk + from kgeneric.layers import LAYER um = 1 / pdk.kcl.dbu enclosure = LayerEnclosure( diff --git a/kgeneric/cells/straight.py b/kgeneric/cells/straight.py index c8b4ab8..8c24ff8 100644 --- a/kgeneric/cells/straight.py +++ b/kgeneric/cells/straight.py @@ -18,6 +18,7 @@ from kfactory import KCell, LayerEnum, kcl from kfactory.utils import LayerEnclosure + from kgeneric.cells.dbu.straight import straight as straight_dbu __all__ = ["straight", "straight_dbu"] @@ -55,7 +56,7 @@ def straight( if __name__ == "__main__": - from kgeneric.pdk import LAYER + from kgeneric.layers import LAYER c = straight(width=1, length=10, layer=LAYER.WG) c.show() diff --git a/kgeneric/cells/taper.py b/kgeneric/cells/taper.py index e280e47..c35a7bd 100644 --- a/kgeneric/cells/taper.py +++ b/kgeneric/cells/taper.py @@ -22,7 +22,7 @@ def taper( ) -> KCell: r"""Linear Taper [um]. - Visualization:: + .. code:: __ _/ │ Slab/Exclude diff --git a/kgeneric/gpdk.py b/kgeneric/gpdk.py new file mode 100644 index 0000000..d439744 --- /dev/null +++ b/kgeneric/gpdk.py @@ -0,0 +1,66 @@ +""" Example on how to build a generic PDK.""" +from functools import partial + +import kfactory as kf + +from kgeneric import cells +from kgeneric.layers import LAYER +from kgeneric.tech import TECH + +enclosure_sc = kf.utils.LayerEnclosure(name="WGSTD", sections=[(LAYER.WGCLAD, 0, 2000)]) + +bend_s_sc = partial( + cells.bend_s, + width=TECH.width_sc, + height=10, + length=20, + layer=LAYER.WG, + enclosure=enclosure_sc, +) +straight_sc = partial( + cells.straight, + length=10, + width=TECH.width_sc, + layer=LAYER.WG, + enclosure=enclosure_sc, +) +straight_dbu_sc = partial( + cells.straight_dbu, + length=int(10e3), + width=int(TECH.width_sc * 1e3), + layer=LAYER.WG, + enclosure=enclosure_sc, +) + +bend_euler_sc = partial( + cells.bend_euler, + width=TECH.width_sc, + layer=LAYER.WG, + radius=TECH.radius_sc, + enclosure=enclosure_sc, +) +bend_circular_sc = partial( + cells.bend_circular, + width=TECH.width_sc, + layer=LAYER.WG, + radius=TECH.radius_sc, + enclosure=enclosure_sc, +) + +taper_sc = partial( + cells.taper, + width1=TECH.width_sc, + width2=TECH.width_sc * 2, + length=10, + layer=LAYER.WG, + enclosure=enclosure_sc, +) + +grating_coupler_sc = partial(cells.grating_coupler_elliptical, wg_width=TECH.width_sc) + +# mzi_sc = partial(cells.mzi, bend=bend_s_sc, straight=straight_sc) # TODO: fix + + +if __name__ == "__main__": + c = straight_sc() + c.show() diff --git a/kgeneric/pdk.py b/kgeneric/layers.py similarity index 94% rename from kgeneric/pdk.py rename to kgeneric/layers.py index 7e0b52b..aa6363b 100644 --- a/kgeneric/pdk.py +++ b/kgeneric/layers.py @@ -1,11 +1,10 @@ """Technology settings.""" from __future__ import annotations -from typing import Any, Dict, Optional, Tuple, Union - -from pydantic import BaseModel, Field +from typing import Any from kfactory.kcell import LayerEnum +from pydantic import BaseModel, Field nm = 1e-3 @@ -122,14 +121,14 @@ class LayerLevel(BaseModel): bias: in um for the etch. """ - layer: Union[Tuple[int, int], LAYER] + layer: tuple[int, int] | LAYER thickness: float thickness_tolerance: float | None = None zmin: float material: str | None = None - sidewall_angle: float = 0 + sidewall_angle: float = 0.0 z_to_bias: list[list[float]] | None = None - info: Dict[str, Any] = {} + info: dict[str, Any] = {} class LayerStack(BaseModel): @@ -139,7 +138,7 @@ class LayerStack(BaseModel): layers: dict of layer_levels. """ - layers: Dict[str, LayerLevel] = Field(default_factory=dict) + layers: dict[str, LayerLevel] = Field(default_factory=dict) def __init__(self, **data: Any): """Add LayerLevels automatically for subclassed LayerStacks.""" @@ -152,7 +151,7 @@ def __init__(self, **data: Any): if isinstance(val.layer, LAYER): self.layers[field].layer = (val.layer[0], val.layer[1]) - def get_layer_to_thickness(self) -> Dict[Tuple[int, int] | LAYER, float]: + def get_layer_to_thickness(self) -> dict[tuple[int, int] | LAYER, float]: """Returns layer tuple to thickness (um).""" return { level.layer: level.thickness @@ -160,13 +159,13 @@ def get_layer_to_thickness(self) -> Dict[Tuple[int, int] | LAYER, float]: if level.thickness } - def get_layer_to_zmin(self) -> Dict[Tuple[int, int] | LAYER, float]: + def get_layer_to_zmin(self) -> dict[tuple[int, int] | LAYER, float]: """Returns layer tuple to z min position (um).""" return { level.layer: level.zmin for level in self.layers.values() if level.thickness } - def get_layer_to_material(self) -> Dict[Tuple[int, int] | LAYER, str]: + def get_layer_to_material(self) -> dict[tuple[int, int] | LAYER, str]: """Returns layer tuple to material name.""" return { level.layer: level.material @@ -174,7 +173,7 @@ def get_layer_to_material(self) -> Dict[Tuple[int, int] | LAYER, str]: if level.thickness and level.material } - def get_layer_to_sidewall_angle(self) -> Dict[Tuple[int, int] | LAYER, float]: + def get_layer_to_sidewall_angle(self) -> dict[tuple[int, int] | LAYER, float]: """Returns layer tuple to material name.""" return { level.layer: level.sidewall_angle @@ -182,11 +181,11 @@ def get_layer_to_sidewall_angle(self) -> Dict[Tuple[int, int] | LAYER, float]: if level.thickness } - def get_layer_to_info(self) -> Dict[Tuple[int, int] | LAYER, Dict[str, Any]]: + def get_layer_to_info(self) -> dict[tuple[int, int] | LAYER, dict[str, Any]]: """Returns layer tuple to info dict.""" return {level.layer: level.info for level in self.layers.values()} - def to_dict(self) -> Dict[str, Dict[str, Any]]: + def to_dict(self) -> dict[str, dict[str, Any]]: return {level_name: dict(level) for level_name, level in self.layers.items()} def __getitem__(self, key: str) -> LayerLevel: @@ -204,7 +203,7 @@ class LayerStackParameters: thickness_wg: float = 220 * nm thickness_slab_deep_etch: float = 90 * nm thickness_slab_shallow_etch: float = 150 * nm - sidewall_angle_wg: float = 10 + sidewall_angle_wg: float = 10.0 thickness_clad: float = 3.0 thickness_nitride: float = 350 * nm thickness_ge: float = 500 * nm @@ -362,8 +361,8 @@ def get_layer_stack( zmin=-box_thickness, material="air", z_to_bias=[ - [0., 0.3, 0.6, 0.8, 0.9, 1.], - [-0., -0.5, -1., -1.5, -2., -2.5], + [0.0, 0.3, 0.6, 0.8, 0.9, 1.0], + [-0.0, -0.5, -1.0, -1.5, -2.0, -2.5], ], mesh_order=1, ), @@ -373,7 +372,7 @@ def get_layer_stack( zmin=thickness_slab_deep_etch, material="Aluminum", mesh_order=1, - sidewall_angle=-10, + sidewall_angle=-10.0, width_to_z=0, ), metal1=LayerLevel( diff --git a/kgeneric/routing.py b/kgeneric/routing.py new file mode 100644 index 0000000..a81ebdd --- /dev/null +++ b/kgeneric/routing.py @@ -0,0 +1,24 @@ +from functools import partial + +import kfactory as kf + +from kgeneric import gpdk + +route_sc = partial( + kf.routing.optical.route, + straight_factory=gpdk.straight_dbu_sc, + bend90_cell=gpdk.bend_euler_sc(), +) + + +if __name__ == "__main__": + c = kf.KCell() + + sl = c << gpdk.straight_sc() + sr = c << gpdk.straight_sc() + sr.d.move((50, 50)) + + route_sc( + c, p1=sl.ports["o2"], p2=sr.ports["o1"], straight_factory=gpdk.straight_dbu_sc + ) + c.show() diff --git a/kgeneric/samples/bend_chain.py b/kgeneric/samples/bend_chain.py new file mode 100644 index 0000000..92d384e --- /dev/null +++ b/kgeneric/samples/bend_chain.py @@ -0,0 +1,13 @@ +import kfactory as kf + +from kgeneric import gpdk as pdk + +if __name__ == "__main__": + c = kf.KCell("bend_chain") + b1 = c << pdk.bend_euler_sc(angle=37) + b2 = c << pdk.bend_euler_sc(angle=37) + b2.connect("o1", b1.ports["o2"]) + # b1.flatten() + # b2.flatten() + c.flatten() + c.show() diff --git a/kgeneric/samples/straight_chain.py b/kgeneric/samples/straight_chain.py new file mode 100644 index 0000000..3b6e561 --- /dev/null +++ b/kgeneric/samples/straight_chain.py @@ -0,0 +1,14 @@ +import kfactory as kf + +from kgeneric import gpdk as pdk + +if __name__ == "__main__": + nm = 1e-3 + c = kf.KCell("bend_chain") + s1 = c << pdk.straight_sc(length=1 + 1.5 * nm) + s2 = c << pdk.straight_sc(length=1) + s2.connect("o1", s1.ports["o2"]) + # b1.flatten() + # b2.flatten() + # c.flatten() + c.show() diff --git a/kgeneric/tech.py b/kgeneric/tech.py new file mode 100644 index 0000000..827a1be --- /dev/null +++ b/kgeneric/tech.py @@ -0,0 +1,11 @@ +nm = 1e-3 + + +class Tech: + """Technology parameters.""" + + width_sc: float = 500 * nm + radius_sc: float = 10 + + +TECH = Tech() diff --git a/pyproject.toml b/pyproject.toml index 602711e..1776c5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,58 +1,49 @@ # https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html + [build-system] -requires = ["flit_core >=3.2,<4"] build-backend = "flit_core.buildapi" +requires = ["flit_core >=3.2,<4"] [project] -name="kgeneric" -description="KLayout generic PDK" +authors = [ + {name = "Skandan Chandrasekar", email = "s39chand@uwaterloo.ca"} +] classifiers = [ - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Operating System :: OS Independent", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Operating System :: OS Independent" ] -version="0.0.2" -authors = [ - {name = "Skandan Chandrasekar", email = "s39chand@uwaterloo.ca"}, +dependencies = [ + "kfactory==0.8.4", + "scipy" ] +description = "KLayout generic PDK" keywords = ["python"] license = {file = "LICENSE"} -dependencies = [ - "kfactory==0.7.5", - "scipy", -] +name = "kgeneric" readme = "README.md" requires-python = ">=3.10" +version = "0.0.2" [project.optional-dependencies] -tests = ["pytest", "pytest-cov"] dev = [ - "pre-commit", - "pytest", - "pytest-cov", - "pytest_regressions", - ] + "pre-commit", + "pytest", + "pytest-cov", + "pytest_regressions" +] docs = [ - "jupytext", - "autodoc_pydantic", - "matplotlib", - "jupytext", - "jupyter-book==0.14.0", - "sphinx-autodoc-typehints", - "sphinx-click", - ] - - -[tool.setuptools.packages] -find = {} - -# [project.scripts] -# kgeneric = "kgeneric.cli:cli" + "jupytext", + "autodoc_pydantic", + "matplotlib", + "jupytext", + "jupyter-book==0.14.0", + "sphinx-autodoc-typehints", + "sphinx-click" +] +tests = ["pytest", "pytest-cov"] [tool.black] -line-length = 88 -target-version = ['py310'] -include = '\.pyi?$' exclude = ''' # Specify the files/dirs that should be ignored by the black formatter /( \.eggs @@ -68,86 +59,94 @@ exclude = ''' # Specify the files/dirs that should be ignored by the black form | dist )/ ''' +include = '\.pyi?$' +line-length = 88 +target-version = ['py310'] -[tool.pytest.ini_options] -testpaths = ["kgeneric/", "tests"] -# addopts = --tb=no -addopts = '--tb=short' -python_files = ["kgeneric/*.py", "notebooks/*.ipynb", "tests/*.py"] -norecursedirs = ["extra/*.py"] - -[tool.flake8] -max-line-length = 88 -max-complexity = 57 -select = ["B","C","E","F","W","T4","B9"] -ignore = [ "E501", "E503", "E722", "W503", "W503", "E203", "B950", "B305", "B018", "B902", "B020", "B905"] -extend-ignore = "RST303" - -exclude = [ - ".git", - "__pycache__", - "lib", - "docs/source/conf.py", - "build", - "dist", - ".ipynb_checkpoints", - ".tox", - "extra", - "deprecated", - ".mypy_cache", - "venv", - "devsim" - ] +[tool.codespell] +ignore-words-list = "te, te/tm, te, ba, fpr, fpr_spacing, ro, nd, donot, schem" [tool.commitizen] name = "cz_conventional_commits" version = "0.1.0" version_files = [ - "pyproject.toml:version", + "pyproject.toml:version" ] -[tool.mypy] -python_version = "3.10" -strict = true +[tool.flake8] exclude = [ - "kgeneric/cells/mzi.py", - "kgeneric/pdk.py", + ".git", + "__pycache__", + "lib", + "docs/source/conf.py", + "build", + "dist", + ".ipynb_checkpoints", + ".tox", + "extra", + "deprecated", + ".mypy_cache", + "venv", + "devsim" ] -plugins = "pydantic.mypy" - -[tool.pylsp-mypy] -enabled = true -live_mode = true -strict = true +extend-ignore = "RST303" +ignore = ["E501", "E503", "E722", "W503", "W503", "E203", "B950", "B305", "B018", "B902", "B020", "B905"] +max-complexity = 57 +max-line-length = 88 +select = ["B", "C", "E", "F", "W", "T4", "B9"] [tool.isort] -multi_line_output = 3 -line_length = 88 include_trailing_comma = true -# skip = "kgeneric/__init__.py" +line_length = 88 +multi_line_output = 3 -[tool.setuptools.package-data] -mypkg = ["*.csv", "*.yaml"] +[tool.mypy] +exclude = [ + "kgeneric/cells/mzi.py", + "kgeneric/pdk.py" +] +plugins = "pydantic.mypy" +python_version = "3.10" +strict = true [tool.pydocstyle] +add-ignore = ["D100", "D101", "D102", "D103", "D104", "D203", "D405", "D417"] +convention = "google" inherit = false match = "(?!test).*\\.py" -add-ignore = ["D100","D101","D102","D103","D104","D203","D405","D417"] -convention = "google" + +[tool.pylsp-mypy] +enabled = true +live_mode = true +strict = true + +[tool.pytest.ini_options] +# addopts = --tb=no +addopts = '--tb=short' +norecursedirs = ["extra/*.py"] +python_files = ["kgeneric/*.py", "notebooks/*.ipynb", "tests/*.py"] +testpaths = ["kgeneric/", "tests"] [tool.ruff] -select = [ - "E", # pycodestyle errors - "W", # pycodestyle warnings - "F", # pyflakes - # "I", # isort - "C", # flake8-comprehensions - "B", # flake8-bugbear -] ignore = [ - "E501", # line too long, handled by black - "B008", # do not perform function calls in argument defaults - "C901", # too complex - "B905", # `zip()` without an explicit `strict=` parameter - "C408", # C408 Unnecessary `dict` call (rewrite as a literal) + "E501", # line too long, handled by black + "B008", # do not perform function calls in argument defaults + "C901", # too complex + "B905", # `zip()` without an explicit `strict=` parameter + "C408" # C408 Unnecessary `dict` call (rewrite as a literal) ] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "C", # flake8-comprehensions + "B", # flake8-bugbear + "UP" +] + +[tool.setuptools.package-data] +mypkg = ["*.csv", "*.yaml"] + +[tool.setuptools.packages] +find = {} diff --git a/kgeneric/tests/__init__.py b/tests/__init__.py similarity index 100% rename from kgeneric/tests/__init__.py rename to tests/__init__.py diff --git a/kgeneric/tests/gds/gds_ref/GC_TE.gds b/tests/gds/gds_ref/GC_TE.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/GC_TE.gds rename to tests/gds/gds_ref/GC_TE.gds diff --git a/kgeneric/tests/gds/gds_ref/GC_TM.gds b/tests/gds/gds_ref/GC_TM.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/GC_TM.gds rename to tests/gds/gds_ref/GC_TM.gds diff --git a/tests/gds/gds_ref/bend_circular_W0p5_R10_LWG_EWGSTD_A90_AS1.gds b/tests/gds/gds_ref/bend_circular_W0p5_R10_LWG_EWGSTD_A90_AS1.gds new file mode 100644 index 0000000..fe6c0c1 Binary files /dev/null and b/tests/gds/gds_ref/bend_circular_W0p5_R10_LWG_EWGSTD_A90_AS1.gds differ diff --git a/kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A180_AS1.gds b/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A180_AS1.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A180_AS1.gds rename to tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A180_AS1.gds diff --git a/kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A90_AS1.gds b/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A90_AS1.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A90_AS1.gds rename to tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_A90_AS1.gds diff --git a/kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T180_TS1.gds b/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T180_TS1.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T180_TS1.gds rename to tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T180_TS1.gds diff --git a/kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T90_TS1.gds b/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T90_TS1.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T90_TS1.gds rename to tests/gds/gds_ref/bend_circular_W1_R10_LWG_EWGSTD_T90_TS1.gds diff --git a/tests/gds/gds_ref/bend_euler_W0p5_R10_LWG_EWGSTD_A90_R150.gds b/tests/gds/gds_ref/bend_euler_W0p5_R10_LWG_EWGSTD_A90_R150.gds new file mode 100644 index 0000000..2784f24 Binary files /dev/null and b/tests/gds/gds_ref/bend_euler_W0p5_R10_LWG_EWGSTD_A90_R150.gds differ diff --git a/kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A180_R150.gds b/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A180_R150.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A180_R150.gds rename to tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A180_R150.gds diff --git a/kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A90_R150.gds b/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A90_R150.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A90_R150.gds rename to tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_A90_R150.gds diff --git a/kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T180_R150.gds b/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T180_R150.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T180_R150.gds rename to tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T180_R150.gds diff --git a/kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T90_R150.gds b/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T90_R150.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T90_R150.gds rename to tests/gds/gds_ref/bend_euler_W1_R10_LWG_EWGSTD_T90_R150.gds diff --git a/tests/gds/gds_ref/bend_s_W0p5_H10_L20_LWG_NP99_TS0_TS1_EWGSTD.gds b/tests/gds/gds_ref/bend_s_W0p5_H10_L20_LWG_NP99_TS0_TS1_EWGSTD.gds new file mode 100644 index 0000000..8dfac03 Binary files /dev/null and b/tests/gds/gds_ref/bend_s_W0p5_H10_L20_LWG_NP99_TS0_TS1_EWGSTD.gds differ diff --git a/kgeneric/tests/gds/gds_ref/bend_s_euler_O0_W0p5_R5_LWG_EWGSTD_R150.gds b/tests/gds/gds_ref/bend_s_euler_O0_W0p5_R5_LWG_EWGSTD_R150.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/bend_s_euler_O0_W0p5_R5_LWG_EWGSTD_R150.gds rename to tests/gds/gds_ref/bend_s_euler_O0_W0p5_R5_LWG_EWGSTD_R150.gds diff --git a/kgeneric/tests/gds/gds_ref/coupler_G0p2_L10_D5_D5_W0p5_LWG_E8a9ff7cf.gds b/tests/gds/gds_ref/coupler_G0p2_L10_D5_D5_W0p5_LWG_E8a9ff7cf.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/coupler_G0p2_L10_D5_D5_W0p5_LWG_E8a9ff7cf.gds rename to tests/gds/gds_ref/coupler_G0p2_L10_D5_D5_W0p5_LWG_E8a9ff7cf.gds diff --git a/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16600_TA40_TEA10_LC1p554_FA15_GLW343_WW500_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone.gds b/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16600_TA40_TEA10_LC1p554_FA15_GLW343_WW500_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone.gds new file mode 100644 index 0000000..93b2131 Binary files /dev/null and b/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16600_TA40_TEA10_LC1p554_FA15_GLW343_WW500_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone.gds differ diff --git a/kgeneric/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16600_TA40_TEA10_LC1p554_FA15_GLW343_WW500_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds b/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16600_TA40_TEA10_LC1p554_FA15_GLW343_WW500_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16600_TA40_TEA10_LC1p554_FA15_GLW343_WW500_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds rename to tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16600_TA40_TEA10_LC1p554_FA15_GLW343_WW500_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds diff --git a/kgeneric/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16p6_TA40_TEA10_LC1p554_FA15_GLW0p343_WW0p5_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds b/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16p6_TA40_TEA10_LC1p554_FA15_GLW0p343_WW0p5_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16p6_TA40_TEA10_LC1p554_FA15_GLW0p343_WW0p5_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds rename to tests/gds/gds_ref/grating_coupler_elliptical_Pte_TL16p6_TA40_TEA10_LC1p554_FA15_GLW0p343_WW0p5_N2p638_LTWG_LTUNDERCUT_PS26_NP30_TO0_TENPlast_PNone_XFLNone_CI1p443.gds diff --git a/kgeneric/tests/gds/gds_ref/mzi_DL10_LY2_LX0p1_BCbend_euler_Sstraight_SYNone_SXTNone_SXBNone_Scoupler_CNone_WSTrue_PESo3_PESo4_PECo1_W1_L0_R5_ENone.gds b/tests/gds/gds_ref/mzi_DL10_LY2_LX0p1_BCbend_euler_Sstraight_SYNone_SXTNone_SXBNone_Scoupler_CNone_WSTrue_PESo3_PESo4_PECo1_W1_L0_R5_ENone.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/mzi_DL10_LY2_LX0p1_BCbend_euler_Sstraight_SYNone_SXTNone_SXBNone_Scoupler_CNone_WSTrue_PESo3_PESo4_PECo1_W1_L0_R5_ENone.gds rename to tests/gds/gds_ref/mzi_DL10_LY2_LX0p1_BCbend_euler_Sstraight_SYNone_SXTNone_SXBNone_Scoupler_CNone_WSTrue_PESo3_PESo4_PECo1_W1_L0_R5_ENone.gds diff --git a/tests/gds/gds_ref/straight_W500_L10000_LWG_EWGSTD.gds b/tests/gds/gds_ref/straight_W500_L10000_LWG_EWGSTD.gds new file mode 100644 index 0000000..7157d8b Binary files /dev/null and b/tests/gds/gds_ref/straight_W500_L10000_LWG_EWGSTD.gds differ diff --git a/kgeneric/tests/gds/gds_ref/straight_W500_L1000_LWG_EWGSTD.gds b/tests/gds/gds_ref/straight_W500_L1000_LWG_EWGSTD.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/straight_W500_L1000_LWG_EWGSTD.gds rename to tests/gds/gds_ref/straight_W500_L1000_LWG_EWGSTD.gds diff --git a/kgeneric/tests/gds/gds_ref/straight_coupler_G0p2_L10_W0p5_LWG_E8a9ff7cf.gds b/tests/gds/gds_ref/straight_coupler_G0p2_L10_W0p5_LWG_E8a9ff7cf.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/straight_coupler_G0p2_L10_W0p5_LWG_E8a9ff7cf.gds rename to tests/gds/gds_ref/straight_coupler_G0p2_L10_W0p5_LWG_E8a9ff7cf.gds diff --git a/kgeneric/tests/gds/gds_ref/taper.gds b/tests/gds/gds_ref/taper.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/taper.gds rename to tests/gds/gds_ref/taper.gds diff --git a/kgeneric/tests/gds/gds_ref/taper_W500_W1000_L10000_LWG_EWGSTD.gds b/tests/gds/gds_ref/taper_W500_W1000_L10000_LWG_EWGSTD.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/taper_W500_W1000_L10000_LWG_EWGSTD.gds rename to tests/gds/gds_ref/taper_W500_W1000_L10000_LWG_EWGSTD.gds diff --git a/kgeneric/tests/gds/gds_ref/waveguide_W500_L1000_LWG_EWGSTD.gds b/tests/gds/gds_ref/waveguide_W500_L1000_LWG_EWGSTD.gds similarity index 100% rename from kgeneric/tests/gds/gds_ref/waveguide_W500_L1000_LWG_EWGSTD.gds rename to tests/gds/gds_ref/waveguide_W500_L1000_LWG_EWGSTD.gds diff --git a/kgeneric/tests/test_cells.py b/tests/test_cells.py similarity index 54% rename from kgeneric/tests/test_cells.py rename to tests/test_cells.py index 8c9efd7..79f8d12 100644 --- a/kgeneric/tests/test_cells.py +++ b/tests/test_cells.py @@ -1,13 +1,11 @@ -from functools import partial import pathlib -import pytest -from kfactory import kdb import kfactory as kf +import pytest +from kfactory import kdb from kfactory.conf import logger -from kgeneric import cells -from kgeneric.pdk import LAYER +from kgeneric import cells_dict class GeometryDifference(ValueError): @@ -16,91 +14,7 @@ class GeometryDifference(ValueError): pass -wg_enc = kf.utils.LayerEnclosure(name="WGSTD", sections=[(LAYER.WGCLAD, 0, 2000)]) - -straight = partial( - cells.straight, width=0.5, length=1, layer=LAYER.WG, enclosure=wg_enc -) - -bend90 = partial( - cells.circular.bend_circular, - width=1, - radius=10, - layer=LAYER.WG, - enclosure=wg_enc, - angle=90, -) - - -bend180 = partial( - cells.circular.bend_circular, - width=1, - radius=10, - layer=LAYER.WG, - enclosure=wg_enc, - angle=180, -) - - -bend90_euler = partial( - cells.euler.bend_euler, - width=1, - radius=10, - layer=LAYER.WG, - enclosure=wg_enc, - angle=90, -) - - -bend180_euler = partial( - cells.euler.bend_euler, - width=1, - radius=10, - layer=LAYER.WG, - enclosure=wg_enc, - angle=180, -) - -coupler = cells.coupler -straight_coupler = cells.straight_coupler - -grating_coupler_elliptical = cells.grating_coupler_elliptical - -taper = partial( - cells.taper, - width1=0.5, - width2=1, - length=10, - layer=LAYER.WG, - enclosure=wg_enc, -) - -bend_s_euler = partial( - cells.bend_s_euler, - offset=0, - width=0.5, - radius=5, - layer=LAYER.WG, - enclosure=wg_enc, -) - -mzi = cells.mzi -straight_coupler = cells.straight_coupler - - -cell_factories = dict( - bend_circular=bend90, - bend_euler=bend90_euler, - bend_s_euler=bend_s_euler, - coupler=coupler, - grating_coupler_elliptical=grating_coupler_elliptical, - straight_coupler=straight_coupler, - mzi=mzi, - taper=taper, - straight=straight, -) - -cell_names = set(cell_factories.keys()) +cell_names = set(cells_dict.keys()) @pytest.fixture(params=cell_names, scope="function") @@ -112,7 +26,7 @@ def cell_name(request): def test_cells(cell_name: str) -> None: """Ensure cells have the same geometry as their golden references.""" gds_ref = pathlib.Path(__file__).parent / "gds" / "gds_ref" - cell = cell_factories[cell_name]() + cell = cells_dict[cell_name]() ref_file = gds_ref / f"{cell.name}.gds" run_cell = cell if not ref_file.exists():