Source code for gdsfactory.typings

"""In programming, a factory is a function that returns an object.

Functions are easy to understand because they have clear inputs and outputs.
Most gdsfactory functions take some inputs and return a Component object.
Some of these inputs parameters are also functions.

- Component: Object with.
    - name.
    - references: to other components (x, y, rotation).
    - polygons in different layers.
    - ports dict.


Specs:

- ComponentSpec: Component, function, string or dict
    (component=mzi, settings=dict(delta_length=20)).
- LayerSpec: (3, 0), 3 (assumes 0 as datatype) or string.

"""

from __future__ import annotations

import dataclasses
import pathlib
from collections.abc import Callable, Generator, Sequence
from functools import partial
from typing import Any, Literal, ParamSpec, Protocol, TypeAlias, TypeVar

import kfactory as kf
import klayout.db as kdb
import numpy as np
import numpy.typing as npt
from kfactory.layer import LayerEnum

STEP_DIRECTIVES = {
    "x",
    "y",
    "dx",
    "dy",
}

STEP_DIRECTIVES_ALL_ANGLE = {
    "x",
    "y",
    "dx",
    "dy",
    "ds",
    "exit_angle",
    "cross_section",
    "connector",
    "separation",
}


[docs] @dataclasses.dataclass class Step: """Manhattan Step. Parameters: x: absolute. y: absolute. dx: x-displacement. dy: y-displacement. """ x: float | None = None y: float | None = None dx: Delta | None = None dy: Delta | None = None
Anchor: TypeAlias = Literal[ "ce", "cw", "nc", "ne", "nw", "sc", "se", "sw", "center", "cc", ] Axis: TypeAlias = Literal["x", "y"] NSEW: TypeAlias = Literal["N", "S", "E", "W"] WidthTypes: TypeAlias = Literal["sine", "linear", "parabolic"] Float2: TypeAlias = tuple[float, float] Float3: TypeAlias = tuple[float, float, float] Floats: TypeAlias = Sequence[float] Strs: TypeAlias = Sequence[str] Int2: TypeAlias = tuple[int, int] Int3: TypeAlias = tuple[int, int, int] Ints: TypeAlias = tuple[int, ...] | list[int] BoundingBox: TypeAlias = tuple[float, float, float, float] BoundingBoxes: TypeAlias = Sequence[BoundingBox] Size: TypeAlias = tuple[float, float] Spacing: TypeAlias = tuple[float, float] Position: TypeAlias = tuple[float, float] Radius: TypeAlias = float Delta: TypeAlias = float AngleInDegrees: TypeAlias = float Layer: TypeAlias = tuple[int, int] Layers: TypeAlias = Sequence[Layer] LayerSpec: TypeAlias = Layer | str | int | LayerEnum LayerSpecs: TypeAlias = Sequence[LayerSpec] Number: TypeAlias = float | int Coordinate: TypeAlias = tuple[float, float] Coordinates: TypeAlias = Sequence[Coordinate] WayPoints: TypeAlias = Sequence[Coordinate | kdb.DPoint] MaterialSpec: TypeAlias = ( str | float | tuple[float, float] | Callable[..., Any] | npt.NDArray[np.float64] ) WidthFunction: TypeAlias = Callable[..., npt.NDArray[np.floating[Any]]] OffsetFunction: TypeAlias = Callable[[float], float] PathType: TypeAlias = str | pathlib.Path PathTypes: TypeAlias = Sequence[PathType] Metadata: TypeAlias = dict[str, int | float | str] Port: TypeAlias = kf.DPort TPort = TypeVar("TPort", bound=Port) IOPorts: TypeAlias = tuple[str, str] PortFactory: TypeAlias = Callable[..., Port] PortsFactory: TypeAlias = Callable[..., Sequence[Port]] PortSymmetries: TypeAlias = dict[str, Sequence[str]] PortDict: TypeAlias = dict[str, Port] Ports: TypeAlias = kf.DPorts | Sequence[Port] | kf.DInstancePorts SelectPorts: TypeAlias = Callable[..., Sequence[Port]] PortType: TypeAlias = str PortName: TypeAlias = str PortTypes: TypeAlias = Sequence[PortType] PortNames: TypeAlias = Sequence[PortName] PortsDict: TypeAlias = dict[str, list[Port]] PortsDictGeneric: TypeAlias = dict[str, list[TPort]] ConductorConductorName: TypeAlias = tuple[str, str] ConductorViaConductorName: TypeAlias = tuple[str, str, str] | ConductorConductorName ConnectivitySpec: TypeAlias = ConductorConductorName | ConductorViaConductorName Sparameters: TypeAlias = dict[str, npt.NDArray[np.float64]] Route: TypeAlias = ( kf.routing.generic.ManhattanRoute | kf.routing.aa.optical.OpticalAllAngleRoute ) RoutingStrategy: TypeAlias = Callable[..., Sequence[Route]] RoutingStrategies: TypeAlias = dict[str, RoutingStrategy] from gdsfactory.cross_section import CrossSectionFactory, CrossSectionSpec # noqa: E402 MultiCrossSectionAngleSpec: TypeAlias = Sequence[ tuple[CrossSectionSpec, tuple[int, ...]] ] from gdsfactory import component # noqa: E402 AnyComponent: TypeAlias = component.Component | component.ComponentAllAngle AnyComponentT = TypeVar("AnyComponentT", bound=AnyComponent) AnyComponentFactory: TypeAlias = Callable[..., AnyComponent] AnyComponentPostProcess: TypeAlias = ( Callable[[component.Component], None] | Callable[[component.ComponentAllAngle], None] ) ComponentParams = ParamSpec("ComponentParams") ComponentFactory: TypeAlias = Callable[..., component.Component] ComponentAllAngleFactory: TypeAlias = Callable[..., component.ComponentAllAngle] ComponentBaseFactory: TypeAlias = Callable[..., component.ComponentBase] ComponentFactoryDict: TypeAlias = dict[str, ComponentFactory] ComponentFactories: TypeAlias = Sequence[ComponentFactory] ComponentSpec: TypeAlias = str | ComponentFactory | dict[str, Any] | kf.DKCell ComponentAllAngleSpec: TypeAlias = ( str | ComponentAllAngleFactory | dict[str, Any] | component.ComponentAllAngle ) ComponentSpecOrComponent: TypeAlias = ComponentSpec | component.Component ComponentSpecs: TypeAlias = Sequence[ComponentSpec] ComponentSpecsOrComponents: TypeAlias = Sequence[ComponentSpecOrComponent] class _PostProcess(Protocol): def __call__(self, component: component.Component, **kwargs: Any) -> Any: ... PostProcess: TypeAlias = ( _PostProcess | Callable[[component.Component], None] | partial[component.Component] ) PostProcesses: TypeAlias = Sequence[PostProcess] Instance: TypeAlias = component.ComponentReference InstanceOrVInstance: TypeAlias = component.ComponentReference | kf.VInstance ComponentOrPath: TypeAlias = PathType | component.Component ComponentOrReference: TypeAlias = component.Component | component.ComponentReference NameToFunctionDict: TypeAlias = dict[str, ComponentFactory] ComponentSpecOrList: TypeAlias = ComponentSpec | list[ComponentSpec] CellSpec: TypeAlias = ( str | ComponentFactory | dict[str, Any] # PCell function, function name or dict ) CellAllAngleSpec: TypeAlias = str | ComponentAllAngleFactory | dict[str, Any] ComponentSpecDict: TypeAlias = dict[str, ComponentSpec] LayerTransitions: TypeAlias = dict[LayerSpec | tuple[Layer, Layer], ComponentSpec] class TypedArray(np.ndarray[Any, np.dtype[Any]]): """based on https://github.com/samuelcolvin/pydantic/issues/380.""" @classmethod def __get_validators__( cls, ) -> Generator[Callable[[Any, Any], npt.NDArray[np.float64]], Any, None]: yield cls.validate_type # pragma: no cover @classmethod def validate_type(cls, val: Any, _info: Any) -> npt.NDArray[np.float64]: return np.array(val, dtype=cls.inner_type) # type: ignore[attr-defined] class ArrayMeta(type): def __getitem__(cls, t: np.dtype[Any]) -> type[npt.NDArray[Any]]: return type("Array", (TypedArray,), {"inner_type": t}) # pragma: no cover class Array(np.ndarray[Any, np.dtype[Any]], metaclass=ArrayMeta): ... __all__ = ( "AngleInDegrees", "ComponentSpec", "Coordinate", "Coordinates", "CrossSectionFactory", "CrossSectionSpec", "Delta", "Float2", "Float3", "Floats", "Instance", "Int2", "Int3", "Ints", "Layer", "LayerSpec", "LayerSpecs", "LayerTransitions", "Layers", "Number", "PathType", "PathTypes", "Port", "PortDict", "PortName", "PortNames", "PortType", "PortTypes", "Ports", "PortsDict", "PortsDictGeneric", "Position", "PostProcesses", "Radius", "RoutingStrategies", "SelectPorts", "Size", "Spacing", "Strs", "TPort", "WayPoints", "WidthTypes", )