gdsfactory¶
You can import gdsfactory.as gf.
functions: - import_gds(): returns a Component from a GDS
classes:
- Component
- Port
- TECH
modules:
- c: components
- routing
gdsfactory¶
You can import gdsfactory.as gf.
functions: - import_gds(): returns a Component from a GDS
classes:
- Component
- Port
- TECH
modules:
- c: components
- routing
gdsfactory.add_labels¶
Add Label to each component port.
get_input_label_text_dash¶
def get_input_label_text_dash(port: Port,
gc: ComponentReference | Component,
gc_index: int | None = None,
component_name: str | None = None,
prefix: str = "",
suffix: str = "") -> str
Returns text with GratingName-ComponentName-PortName
.
get_input_label_text_dash_loopback¶
def get_input_label_text_dash_loopback(port: Port,
gc: ComponentReference | Component,
gc_index: int | None = None,
component_name: str | None = None,
prefix: str = "") -> str
Returns text with GratingName-ComponentName-Loopback
.
get_input_label_text¶
def get_input_label_text(port: Port,
gc: ComponentReference | Component,
gc_index: int | None = None,
component_name: str | None = None,
component_prefix: str = "",
prefix: str = "opt",
suffix: str = "") -> str
Returns text string for an optical port based on grating coupler.
{label_prefix}{polarization}{wavelength_nm}_({prefix}{component_name})
Arguments:
port
- to label.gc
- grating coupler component or reference.gc_index
- grating_coupler index, which grating_coupler we are labelling.component_name
- optional name.component_prefix
- component prefix.prefix
- prefix to add to the label.
get_input_label¶
def get_input_label(
port: Port,
gc: ComponentReference,
gc_index: int | None = None,
gc_port_name: str = "o1",
layer_label: LayerSpec = "LABEL",
component_name: str | None = None,
get_input_label_text_function=get_input_label_text) -> Label
Returns a label with component info for a given grating coupler.
Test equipment to extract grating coupler coordinates and match it to the component.
Arguments:
port
- port to label.gc
- grating coupler reference.gc_index
- grating coupler index.gc_port_name
- name of grating coupler port.layer_label
- layer of the label.component_name
- for the label.get_input_label_text_function
- function to get input label.
get_input_label_electrical¶
def get_input_label_electrical(port: Port,
gc_index: int = 0,
component_name: str | None = None,
layer_label: LayerSpec = "LABEL",
gc: ComponentReference | None = None) -> Label
Returns a label to test component info for a given electrical port.
This is the label used by T&M to extract grating coupler coordinates and match it to the component.
Arguments:
port
- to label.gc_index
- index of the label.component_name
- Optional component_name.layer_label
- for label.gc
- ignored.
add_labels¶
def add_labels(component: Component,
get_label_function: Callable = get_input_label_electrical,
layer_label: LayerSpec = "LABEL",
gc: Component | None = None,
**kwargs) -> Component
Returns component with labels on ports.
Arguments:
component
- to add labels to.get_label_function
- function to get label.layer_label
- layer_label.gc
- Optional grating coupler.keyword Args:
layer
- port GDS layer.prefix
- with in port name.suffix
- select ports with port name suffix.orientation
- in degrees.width
- for ports to add label.layers_excluded
- List of layers to exclude.port_type
- optical, electrical, ...clockwise
- if True, sort ports clockwise, False: counter-clockwise.
Returns:
original component with labels.
add_siepic_labels¶
def add_siepic_labels(component: Component,
model: str = "auto",
library: str = "auto",
label_layer: LayerSpec = "DEVREC",
spice_params: dict | list | str | None = None,
label_spacing: float = 0.2) -> Component
Adds labels and returns the same component.
Arguments:
component
- component.model
- Lumerical Interconnect model. ‘auto’ attempts to extract this from the cross_section.library
- Lumerical Interconnect library. ‘auto’ attempts to extract this from the cross_section.label_layer
- layer for writing SiEPIC labels.spice_params
- spice parameters (in microns). Either pass in a dict with parameter, value pairs, or pass a list of values to extract from component info.label_spacing
- separation distance between labels in um.
add_labels_to_ports¶
def add_labels_to_ports(component: Component,
label_layer: LayerSpec = "LABEL",
port_type: str | None = None,
**kwargs) -> Component
Add labels to component ports.
Arguments:
component
- to add labels.label_layer
- layer spec for the label.port_type
- to select ports.keyword Args:
layer
- select ports with GDS layer.prefix
- select ports with prefix in port name.suffix
- select ports with port name suffix.orientation
- select ports with orientation in degrees.width
- select ports with port width.layers_excluded
- List of layers to exclude.port_type
- select ports with port_type (optical, electrical, vertical_te).clockwise
- if True, sort ports clockwise, False: counter-clockwise.
add_labels_to_ports_x_y¶
def add_labels_to_ports_x_y(component: Component,
label_layer: LayerSpec = "LABEL",
port_type: str | None = None,
**kwargs) -> Component
Add labels to component ports. Prepends -x-y coordinates
Arguments:
component
- to add labels.label_layer
- layer spec for the label.port_type
- to select ports.keyword Args:
layer
- select ports with GDS layer.prefix
- select ports with prefix in port name.suffix
- select ports with port name suffix.orientation
- select ports with orientation in degrees.width
- select ports with port width.layers_excluded
- List of layers to exclude.port_type
- select ports with port_type (optical, electrical, vertical_te).clockwise
- if True, sort ports clockwise, False: counter-clockwise.
get_labels¶
def get_labels(component: ComponentOrReference,
get_label_function: Callable = get_input_label_electrical,
layer_label: LayerSpec = "LABEL",
gc: Component | None = None,
component_name: str | None = None,
**kwargs) -> list[Label]
Returns component labels on ports.
Arguments:
component
- to add labels to.get_label_function
- function to get label.layer_label
- layer_label.gc
- Optional grating coupler.component_name
- optional component name.keyword Args:
layer
- port GDS layer.prefix
- look for prefix in port name.suffix
- select ports with port name suffix.orientation
- in degrees.width
- for ports to add label.layers_excluded
- List of layers to exclude.port_type
- optical, electrical, ...clockwise
- if True, sort ports clockwise, False: counter-clockwise.
Returns:
list of component labels.
gdsfactory.path¶
You can define a path with a list of points combined with a cross-section.
A path can be extruded using any CrossSection returning a Component The CrossSection defines the layer numbers, widths and offsets
Adapted from PHIDL https://
Path Objects¶
class Path(_GeometryHelper)
Path object for smooth Paths. You can extrude a Path with a CrossSection to create a Component.
Arguments:
path
- array-like[N][2], Path, or list of Paths. Points or Paths to append() initially.
__init__¶
def __init__(path=None) -> None
Creates an empty path.
__repr__¶
def __repr__() -> str
Returns path points.
__len__¶
def __len__() -> int
Returns path points.
__iadd__¶
def __iadd__(path_or_points) -> Path
Adds points to current path.
__add__¶
def __add__(path) -> Path
Returns new path concatenating current and new path.
bbox¶
@property
def bbox()
Returns the bounding box of the Path.
append¶
def append(path)
Attach Path to the end of this Path.
The input path automatically rotates and translates such that it continues smoothly from the previous segment.
Arguments:
path : Path, array-like[N][2], or list of Paths The input path that will be appended.
offset¶
def offset(offset: float | Callable[..., float] = 0)
Offsets Path so that it follows the Path centerline plus an offset.
The offset can either be a fixed value, or a function of the form my_offset(t) where t goes from 0->1
Arguments:
offset
- int or float, callable. Magnitude of the offset
move¶
def move(origin=(0, 0), destination=None, axis=None)
Moves the Path from the origin point to the destination.
Both origin and destination can be 1x2 array-like or a Port.
Arguments:
origin : array-like[2], Port Origin point of the move. destination : array-like[2], Port Destination point of the move. axis : {‘x’, ‘y’} Direction of move.
rotate¶
def rotate(angle: float = 45, center: Float2 | None = (0, 0))
Rotates all Polygons in the Component around the specified center point.
If no center point specified will rotate around (0,0).
Arguments:
angle
- Angle to rotate the Component in degrees.center
- array-like[2] or None. component of the Component.
mirror¶
def mirror(p1: Float2 = (0, 1), p2: Float2 = (0, 0))
Mirrors the Path across the line formed between the two specified points.
points
may be input as either single points [1,2]
or array-like[N][2], and will return in kind.
Arguments:
p1
- First point of the line.p2
- Second point of the line.
length¶
def length() -> float
Return cumulative length.
curvature¶
def curvature()
Calculates Path curvature.
The curvature is numerically computed so areas where the curvature jumps instantaneously (such as between an arc and a straight segment) will be slightly interpolated, and sudden changes in point density along the curve can cause discontinuities.
Returns:
s : array-like[N] The arc-length of the Path K : array-like[N] The curvature of the Path
hash_geometry¶
def hash_geometry(precision: float = 1e-4) -> str
Computes an SHA1 hash of the points in the Path and the start_angle and end_angle.
Arguments:
precision
- Rounding precision for the the objects in the Component. For instance, a precision of 1e-2 will round a point at (0.124, 1.748) to (0.12, 1.75)
Returns:
str Hash result in the form of an SHA1 hex digest string.
.. code::
hash( hash(First layer information: [layer1, datatype1]), hash(Polygon 1 on layer 1 points: [(x1,y1),(x2,y2),(x3,y3)] ), hash(Polygon 2 on layer 1 points: [(x1,y1),(x2,y2),(x3,y3),(x4,y4)] ), hash(Polygon 3 on layer 1 points: [(x1,y1),(x2,y2),(x3,y3)] ), hash(Second layer information: [layer2, datatype2]), hash(Polygon 1 on layer 2 points: [(x1,y1),(x2,y2),(x3,y3),(x4,y4)] ), hash(Polygon 2 on layer 2 points: [(x1,y1),(x2,y2),(x3,y3)] ), )
__get_validators__¶
@classmethod
def __get_validators__(cls)
For pydantic.
plot¶
def plot() -> None
Plot path in matplotlib.
.. plot:: :include-source:
import gdsfactory as gf
p = gf.path.euler(radius=10)
p.plot()
extrude¶
def extrude(cross_section: CrossSectionSpec | None = None,
layer: LayerSpec | None = None,
width: float | None = None,
widths: Float2 | None = None,
simplify: float | None = None,
shear_angle_start: float | None = None,
shear_angle_end: float | None = None) -> Component
Returns Component by extruding a Path with a CrossSection.
A path can be extruded using any CrossSection returning a Component The CrossSection defines the layer numbers, widths and offsets.
Arguments:
p
- a path is a list of points (arc, straight, euler).cross_section
- to extrude.layer
- optional layer.width
- optional width in um.widths
- tuple of starting and end width for a linear taper.simplify
- Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting polygon by more than the value listed here will be removed.shear_angle_start
- an optional angle to shear the starting face by (in degrees).shear_angle_end
- an optional angle to shear the ending face by (in degrees)... plot:: :include-source:
import gdsfactory as gf
p = gf.path.euler(radius=10) c = p.extrude(layer=(1, 0), width=0.5) c.plot()
copy¶
def copy()
Returns a copy of the Path.
transition_exponential¶
def transition_exponential(y1, y2, exp=0.5)
Returns the function for an exponential transition.
Arguments:
y1
- start width in um.y2
- end width in um.exp
- exponent.
transition_adiabatic¶
def transition_adiabatic(w1: float,
w2: float,
neff_w,
wavelength: float = 1.55,
alpha: float = 1,
max_length: float = 200,
num_points_ODE: int = 2000)
Returns the points for an optimal adiabatic transition for well-guided modes.
Arguments:
w1
- start width in um.w2
- end width in um.neff_w
- a callable that returns the effective index as a function of width By default, use a compact model of neff(y) for fundamental 1550 nm TE mode of 220nm-thick core with 3.45 index, fully clad with 1.44 index. Many coefficients are needed to capture the behaviour.wavelength
- wavelength, in same units as widthsalpha
- parameter that scales the rate of width change- closer to 0 means longer and more adiabatic;
- 1 is the intuitive limit beyond which higher order modes are excited;
- [2] reports good performance up to 1.4 for fundamental TE in SOI (for multiple core thicknesses)
max_length
- maximum length in um.num_points_ODE
- number of samplings points for the ODE solve.
References:
[1] Burns, W. K., et al. “Optical waveguide parabolic coupling horns.” Appl. Phys. Lett., vol. 30, no. 1, 1 Jan. 1977, pp. 28-30, doi:10.1063/1.89199. [2] Fu, Yunfei, et al. “Efficient adiabatic silicon-on-insulator waveguide taper.” Photonics Res., vol. 2, no. 3, 1 June 2014, pp. A41-A44, doi:10.1364/PRJ.2.000A41.
transition¶
def transition(cross_section1: CrossSection,
cross_section2: CrossSection,
width_type: WidthTypes = "sine",
**kwargs) -> Transition
Returns a smoothly-transitioning between two CrossSections.
Only cross-sectional elements that have the name
(as in X.add(..., name = ‘wg’) )
parameter specified in both input CrosSections will be created.
Port names will be cloned from the input CrossSections in reverse.
Arguments:
cross_section1
- First CrossSection.cross_section2
- Second CrossSection.width_type
- sine or linear. Sets the type of width transition used if any widths are different between the two input CrossSections.
along_path¶
@cell
def along_path(p: Path, component: ComponentSpec, spacing: float,
padding: float) -> Component
Returns Component containing many copies of component
along p
.
Places as many copies of component
along each segment of p
as possible
under the given constraints. spacing
is always followed precisely, but
actual padding
may exceed the provided value to place components evenly.
Arguments:
p
- Path to place components along.component
- Component to repeat along the path. The unrotated version of this object should be oriented for placement on a horizontal line.spacing
- distance between component placements.padding
- minimum distance from the path start to the first component.
extrude¶
@cell
def extrude(p: Path,
cross_section: CrossSectionSpec | None = None,
layer: LayerSpec | None = None,
width: float | None = None,
widths: Float2 | None = None,
simplify: float | None = None,
shear_angle_start: float | None = None,
shear_angle_end: float | None = None) -> Component
Returns Component extruding a Path with a cross_section.
A path can be extruded using any CrossSection returning a Component The CrossSection defines the layer numbers, widths and offsets
Arguments:
p
- a path is a list of points (arc, straight, euler).cross_section
- to extrude.layer
- optional layer to extrude.width
- optional width to extrude.widths
- tuple of starting and end width.simplify
- Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed.shear_angle_start
- an optional angle to shear the starting face by (in degrees).shear_angle_end
- an optional angle to shear the ending face by (in degrees).
arc¶
def arc(radius: float = 10.0,
angle: float = 90,
npoints: int | None = None,
start_angle: float | None = -90) -> Path
Returns a radial arc.
Arguments:
radius
- minimum radius of curvature.angle
- total angle of the curve.npoints
- Number of points used per 360 degrees. Defaults to pdk.bend_points_distance.start_angle
- initial angle of the curve for drawing, default -90 degrees... plot:: :include-source:
import gdsfactory as gf
p = gf.path.arc(radius=10, angle=45) p.plot()
euler¶
def euler(radius: float = 10,
angle: float = 90,
p: float = 0.5,
use_eff: bool = False,
npoints: int | None = None) -> Path
Returns an euler bend that adiabatically transitions from straight to curved.
radius
is the minimum radius of curvature of the bend.
However, if use_eff
is set to True, radius
corresponds to the effective
radius of curvature (making the curve a drop-in replacement for an arc).
If p < 1.0, will create a “partial euler” curve as described in Vogelbacher et. al.
Vogelbacher et al. (2019)
Arguments:
radius
- minimum radius of curvature.angle
- total angle of the curve.p
- Proportion of the curve that is an Euler curve.use_eff
- If False:radius
is the minimum radius of curvature of the bend. If True: The curve will be scaled such that the endpoints match an arc. with parametersradius
andangle
.npoints
- Number of points used per 360 degrees... plot:: :include-source:
import gdsfactory as gf
p = gf.path.euler(radius=10, angle=45, p=1, use_eff=True, npoints=720) p.plot()
straight¶
def straight(length: float = 10.0, npoints: int = 2) -> Path
Returns a straight path.
For transitions you should increase have at least 100 points
Arguments:
length
- of straight.npoints
- number of points.
spiral_archimedean¶
def spiral_archimedean(min_bend_radius: float, separation: float,
number_of_loops: float, npoints: int) -> Path
Returns an Archimedean spiral.
Arguments:
radius
- Inner radius of the spiral.separation
- Separation between the loops in um.number_of_loops
- number of loops.npoints
- number of Points... plot:: :include-source:
import gdsfactory as gf
p = gf.path.spiral_archimedean(min_bend_radius=5, separation=2, number_of_loops=3, npoints=200) p.plot()
smooth¶
def smooth(points: Coordinates,
radius: float = 4.0,
bend: PathFactory = euler,
**kwargs) -> Path
Returns a smooth Path from a series of waypoints.
Arguments:
points
- array-like[N][2] List of waypoints for the path to follow.radius
- radius of curvature, passed tobend
.bend
- bend function that returns a path that round corners.npoints
- Number of points used per 360 degrees for the bend.kwargs
- Extra keyword arguments that will be passed tobend
... plot:: :include-source:
import gdsfactory as gf
p = gf.path.smooth(([0, 0], [0, 10], [10, 10])) p.plot()
gdsfactory.pdk¶
PDK stores layers, cross_sections, cell functions ...
evanescent_coupler_sample¶
def evanescent_coupler_sample() -> None
Evanescent coupler example.
Arguments:
coupler_length
- length of coupling (min: 0.0, max: 200.0, um).
extract_args_from_docstring¶
def extract_args_from_docstring(docstring: str) -> dict[str, Any] | None
This function extracts settings from a function’s docstring for uPDK format.
Arguments:
docstring
- The function from which to extract YAML in the docstring.
Returns:
settings
dict - The extracted YAML data as a dictionary.
GdsWriteSettings Objects¶
class GdsWriteSettings(BaseModel)
Settings to use when writing to GDS.
CellDecoratorSettings Objects¶
class CellDecoratorSettings(BaseModel)
Settings for cell_without_validator decorator function in gdsfactory.cell.
Pdk Objects¶
class Pdk(BaseModel)
Store layers, cross_sections, cell functions, simulation_settings ...
only one Pdk can be active at a given time.
Arguments:
name
- PDK name.cross_sections
- dict of cross_sections factories.cells
- dict of parametric cells that return Components.symbols
- dict of symbols names to functions. default_symbol_factory:base_pdk
- a pdk to copy from and extend.default_decorator
- decorate all cells, if not otherwise defined on the cell.layers
- maps name to gdslayer/datatype. For example dict(si=(1, 0), sin=(34, 0)).layer_stack
- maps name to layer numbers, thickness, zmin, sidewall_angle. if can also contain material properties (refractive index, nonlinear coefficient, sheet resistance ...).layer_views
- includes layer name to color, opacity and pattern.layer_transitions
- transitions between different cross_sections.sparameters_path
- to store Sparameters simulations.modes_path
- to store Sparameters simulations.interconnect_cml_path
- path to interconnect CML (optional).warn_off_grid_ports
- raises warning when extruding paths with offgrid ports.constants
- dict of constants for the PDK.materials_index
- material spec names to material spec, which can be:string
- material name.float
- refractive index. float, float: refractive index real and imaginary part.function
- function of wavelength.routing_strategies
- functions enabled to route.gds_write_settings
- to write GDSII files.oasis_settings
- to write OASIS files.cell_decorator_settings
- settings for cell_without_validator decorator function in gdsfactory.cell.bend_points_distance
- default points distance for bends in um.
grid_size¶
@property
def grid_size()
The minimum unit resolvable on the layout grid, relative to the unit.
validate_layers¶
def validate_layers(layers_required: list[Layer] | None = None)
Raises ValueError if layers_required are not in Pdk.
activate¶
def activate() -> None
Set current pdk to the active pdk (if not already active).
register_cells¶
def register_cells(**kwargs) -> None
Register cell factories.
register_cross_sections¶
def register_cross_sections(**kwargs) -> None
Register cross_sections factories.
register_cells_yaml¶
def register_cells_yaml(dirpath: PathType | None = None,
update: bool = False,
**kwargs) -> None
Load *.pic.yml YAML files and register them as cells.
Arguments:
dirpath
- directory to recursive search for YAML cells.update
- does not raise ValueError if cell already registered.
Arguments:
cell_name
- cell function. To update cells dict.
remove_cell¶
def remove_cell(name: str)
Removes cell from a PDK.
get_cell¶
def get_cell(cell: CellSpec, **kwargs) -> ComponentFactory
Returns ComponentFactory from a cell spec.
get_component¶
def get_component(component: ComponentSpec, **kwargs) -> Component
Returns component from a component spec.
get_symbol¶
def get_symbol(component: ComponentSpec, **kwargs) -> Component
Returns a component’s symbol from a component spec.
get_cross_section¶
def get_cross_section(cross_section: CrossSectionSpec,
**kwargs) -> CrossSection | Transition
Returns cross_section from a cross_section spec.
get_layer¶
def get_layer(layer: LayerSpec) -> Layer
Returns layer from a layer spec.
to_updk¶
def to_updk() -> str
Export to uPDK YAML definition.
get_constant¶
def get_constant(constant_name: Any) -> Any
If constant_name is a string returns a the value from the dict.
get_routing_strategies¶
def get_routing_strategies() -> dict[str, Callable]
Gets a dictionary of named routing functions available to the PDK, if defined, or gdsfactory defaults otherwise.
gdsfactory.serialization¶
Serialize component settings into YAML or strings.
DEFAULT_SERIALIZATION_MAX_DIGITS¶
By default, the maximum number of digits retained when serializing float-like arrays
clean_value_json¶
def clean_value_json(
value: Any) -> str | int | float | dict | list | bool | None
Return JSON serializable object.
clean_value_name¶
def clean_value_name(value: Any) -> str
Returns a string representation of an object.
gdsfactory.cell¶
Cell decorator for functions that return a Component.
clear_cache¶
def clear_cache() -> None
Clears Component CACHE.
Settings Objects¶
class Settings(BaseModel)
info¶
derived properties (length, resistance)
cell_without_validator¶
def cell_without_validator(func: _F) -> _F
Decorator for Component functions.
Similar to cell decorator, this one does not validate_arguments using type annotations
I recommend using cell instead
cell¶
def cell(func: _F) -> _F
Decorator for Component functions.
Wraps cell_without_validator Validates type annotations with pydantic.
Implements a cache so that if a component has already been build it will return the component from the cache directly. This avoids creating two exact Components that have the same name.
When decorate your functions with cell you get:
- cache: avoids creating duplicated Components.
- name: names Components uniquely name based on parameters.
- metadata: adds Component.metadata with default, changed and full Args.
Note the cell decorator does not take any arguments. Keyword Args are applied the resulting Component.
Arguments:
autoname
bool - True renames Component based on args and kwargs. True by default.name
str - Optional name.cache
bool - returns Component from the CACHE if it already exists. Avoids having duplicated cells with the same name. If False overrides CACHE creates a new Component.flatten
bool - False by default. True flattens component hierarchy.info
- updates Component.info dict.prefix
str - name_prefix, defaults to function name.max_name_length
int - truncates name beyond some characters with a hash.decorator
Callable - function to apply to Component.A decorator is a function that runs over a function, so when you do.
.. code::
import gdsfactory as gf
gf.cell def mzi_with_bend(): c = gf.Component() mzi = c << gf.components.mzi() bend = c << gf.components.bend_euler() return c
it’s equivalent to
.. code::
def mzi_with_bend(): c = gf.Component() mzi = c << gf.components.mzi() bend = c << gf.components.bend_euler(radius=radius) return c
mzi_with_bend_decorated = gf.cell(mzi_with_bend)
declarative_cell¶
def declarative_cell(cls: type[Any]) -> Callable[..., Component]
Decorator to turn a dataclass into a cell. Work in progress.
wg¶
@cell
def wg(length: int = 3, layer: tuple[int, int] = (1, 0)) -> Component
Dummy component for testing.
wg2¶
@cell
def wg2(wg1=wg)
Dummy component for testing.
demo¶
@cell
def demo(length: int = 3, wg_width: float = 0.5) -> Component
Demo Dummy cell.
gdsfactory.component¶
Component is a canvas for geometry.
Adapted from PHIDL https://
valid_plotters¶
qt and holoviews are deprecated
Component Objects¶
class Component(_GeometryHelper)
A Component is an empty canvas where you add polygons, references and ports (to connect to other components).
- stores settings that you use to build the component
- stores info that you want to use
- can return ports by type (optical, electrical ...)
- can return netlist for circuit simulation
- can write to GDS, OASIS
- can show in KLayout, matplotlib, 3D
- can return copy, mirror, flattened (no references)
Arguments:
name
- component_name. Use cell decorator for auto-naming.with_uuid
- adds unique identifier.Properties:
info
- dictionary that includes- derived properties
- external metadata (test_protocol, docs, ...)
- simulation_settings
- function_name
- name: for the component
settings:
full
- full settings passed to the function to create component.changed
- changed settings.default
- default component settings.child
- dict info from the children, if any.
__init__¶
def __init__(name: str = "Unnamed", with_uuid: bool = False) -> None
Initialize the Component object.
__iter__¶
def __iter__()
You can iterate over polygons, paths, labels and references.
get_polygon_bbox¶
def get_polygon_bbox(default: float = 0.0,
top: float | None = None,
bottom: float | None = None,
right: float | None = None,
left: float | None = None) -> shapely.Polygon
Returns shapely Polygon with bounding box.
Arguments:
default
- default padding in um.top
- north padding in um.bottom
- south padding in um.right
- east padding in um.left
- west padding in um.
get_polygons¶
def get_polygons(
by_spec: bool | tuple[int, int] = False,
depth: int | None = None,
include_paths: bool = True,
as_array: bool = True,
as_shapely: bool = False,
as_shapely_merged: bool = False
) -> list[Polygon] | dict[tuple[int, int], list[Polygon]]
Return a list of polygons in this cell.
Arguments:
by_spec
- bool or layer If True, the return value is a dictionary with the polygons of each individual pair (layer, datatype), which are used as keys. If set to a tuple of (layer, datatype), only polygons with that specification are returned.depth
- integer or None If not None, defines from how many reference levels to retrieve polygons. References below this level will result in a bounding box. Ifby_spec
is True the key will be the name of this cell.include_paths
- If True, polygonal representation of paths are also included in the result.as_array
- when as_array=false, return the Polygon objects instead. polygon objects have more information (especially when by_spec=False) and are faster to retrieve.as_shapely
- returns shapely polygons.as_shapely_merged
- returns a shapely polygonize.Returns
out
- list of array-like[N][2] or dictionary List containing the coordinates of the vertices of each polygon, or dictionary with with the list of polygons (ifby_spec
is True).
Notes:
Instances of FlexPath
and RobustPath
are also included in
the result by computing their polygonal boundary.
get_dependencies¶
def get_dependencies(recursive: bool = False) -> list[Component]
Return a list of Components referenced by this Component.
Arguments:
recursive
- If True returns dependencies recursively.
__getitem__¶
def __getitem__(key) -> Port
Access reference ports.
__lshift__¶
def __lshift__(element) -> ComponentReference
Convenience operator equivalent to add_ref().
unlock¶
def unlock() -> None
Only do this if you know what you are doing.
lock¶
def lock() -> None
Makes sure components can’t add new elements or move existing ones.
Components lock automatically when going into the CACHE to ensure one component does not change others
__setitem__¶
def __setitem__(key, element)
Allow adding polygons and cell references.
like D[‘arc3’] = pg.arc()
Arguments:
key
- Alias name.element
- Object that will be accessible by alias name.
__get_validators__¶
@classmethod
def __get_validators__(cls)
Get validators for the Component object.
validate¶
@classmethod
def validate(cls, v, _info)
Pydantic assumes component is valid if the following are true.
- name characters < pdk.cell_decorator_settings.max_name_length
- is not empty (has references or polygons)
add_label¶
def add_label(text: str = "hello",
position: tuple[float, float] = (0.0, 0.0),
magnification: float = 1.0,
rotation: float = 0,
anchor: str = "o",
layer: LayerSpec = "TEXT",
x_reflection: bool = False) -> Label
Adds Label to the Component.
Arguments:
text
- Label text.position
- x-, y-coordinates of the Label location.magnification
- Magnification factor for the Label text.rotation
- Angle rotation of the Label text.anchor
- {‘n’, ‘e’, ‘s’, ‘w’, ‘o’, ‘ne’, ‘nw’, ...} Position of the anchor relative to the text.layer
- Specific layer(s) to put Label on.x_reflection
- True reflects across the horizontal axis before rotation.
bbox¶
@property
def bbox()
Returns the bounding box of the ComponentReference.
ports_layer¶
@property
def ports_layer() -> dict[str, str]
Returns a mapping from layer0_layer1_E0: portName.
port_by_orientation_cw¶
def port_by_orientation_cw(key: str, **kwargs)
Returns port by indexing them clockwise.
port_by_orientation_ccw¶
def port_by_orientation_ccw(key: str, **kwargs)
Returns port by indexing them clockwise.
get_ports_xsize¶
def get_ports_xsize(**kwargs) -> float
Returns xdistance from east to west ports.
Arguments:
layer
- port GDS layer.prefix
- with in port name.orientation
- in degrees.width
- port width.layers_excluded
- List of layers to exclude.port_type
- optical, electrical, ...
get_ports_ysize¶
def get_ports_ysize(**kwargs) -> float
Returns ydistance from east to west ports.
Arguments:
layer
- port GDS layer.prefix
- with in port name.orientation
- in degrees.width
- port width (um).layers_excluded
- List of layers to exclude.port_type
- optical, electrical, ...
plot_netlist¶
def plot_netlist(with_labels: bool = True,
font_weight: str = "normal",
**kwargs)
Plots a netlist graph with networkx.
Arguments:
with_labels
- add label to each node.font_weight
- normal, bold.**kwargs
- keyword arguments for the get_netlist function
plot_netlist_flat¶
def plot_netlist_flat(with_labels: bool = True,
font_weight: str = "normal",
**kwargs)
Plots a netlist graph with networkx.
Arguments:
flat
- if true, will plot the flat netlistwith_labels
- add label to each node.font_weight
- normal, bold.**kwargs
- keyword arguments for the get_netlist function
write_netlist¶
def write_netlist(filepath: str) -> None
Write netlist in YAML.
write_netlist_dot¶
def write_netlist_dot(filepath: str | None = None) -> None
Write netlist graph in DOT format.
get_netlist¶
def get_netlist(**kwargs) -> dict[str, Any]
From Component returns instances, connections and placements dict.
Arguments:
component
- to extract netlist.full_settings
- True returns all, false changed settings.tolerance
- tolerance in nm to consider two ports connected.exclude_port_types
- optional list of port types to exclude from netlisting.get_instance_name
- function to get instance name.allow_multiple
- False to raise an error if more than two ports share the same connection. if True, will return key: [value] pairs with [value] a list of all connected instances.
Returns:
Netlist dict (instances, connections, placements, ports)
instances
- Dict of instance name and settings.connections
- Dict of Instance1Name,portName: Instance2Name,portName.placements
- Dict of instance names and placements (x, y, rotation).ports
- Dict portName: ComponentName,port.name
- name of component.
get_netlist_recursive¶
def get_netlist_recursive(**kwargs) -> dict[str, DictConfig]
Returns recursive netlist for a component and subcomponents.
Arguments:
component
- to extract netlist.component_suffix
- suffix to append to each component name. useful if to save and reload a back-annotated netlist.get_netlist_func
- function to extract individual netlists.full_settings
- True returns all, false changed settings.tolerance
- tolerance in nm to consider two ports connected.exclude_port_types
- optional list of port types to exclude from netlisting.get_instance_name
- function to get instance name.allow_multiple
- False to raise an error if more than two ports share the same connection. if True, will return key: [value] pairs with [value] a list of all connected instances.
Returns:
Dictionary of netlists, keyed by the name of each component.
get_netlist_flat¶
def get_netlist_flat(**kwargs) -> dict[str, DictConfig]
Returns a netlist where all subinstances are exposed and independently named.
Arguments:
component
- to extract netlist.component_suffix
- suffix to append to each component name. useful if to save and reload a back-annotated netlist.get_netlist_func
- function to extract individual netlists.full_settings
- True returns all, false changed settings.tolerance
- tolerance in nm to consider two ports connected.exclude_port_types
- optional list of port types to exclude from netlisting.get_instance_name
- function to get instance name.allow_multiple
- False to raise an error if more than two ports share the same connection. if True, will return key: [value] pairs with [value] a list of all connected instances.
Returns:
Dictionary of netlists, keyed by the name of each component.
assert_ports_on_grid¶
def assert_ports_on_grid(nm: int = 1) -> None
Asserts that all ports are on grid.
get_ports¶
def get_ports(depth=None)
Returns copies of all the ports of the Component, rotated and translated so that they’re in their top-level position.
The Ports returned are copies of the originals, but each copy has the same
uid
as the original so that they can be traced back to the original if needed.
Arguments:
depth : int or None If not None, defines from how many reference levels to retrieve Ports from.
Returns:
port_list : list of Port List of all Ports in the Component.
get_ports_dict¶
def get_ports_dict(**kwargs) -> dict[str, Port]
Returns a dict of ports.
Arguments:
layer
- port GDS layer.prefix
- select ports with prefix in port name.suffix
- select ports with port name suffix.orientation
- select ports with orientation in degrees.width
- select ports with port width.layers_excluded
- List of layers to exclude.port_type
- select ports with port_type (optical, electrical, vertical_te).clockwise
- if True, sort ports clockwise, False: counter-clockwise.
get_ports_list¶
def get_ports_list(**kwargs) -> list[Port]
Returns list of ports.
Arguments:
layer
- select ports with GDS layer.prefix
- select ports with prefix in port name.suffix
- select ports with port name suffix.orientation
- select ports with orientation in degrees.orientation
- select ports with orientation in degrees.width
- select ports with port width.layers_excluded
- List of layers to exclude.port_type
- select ports with port_type (optical, electrical, vertical_te).clockwise
- if True, sort ports clockwise, False: counter-clockwise.
ref¶
def ref(position: Coordinate = (0, 0),
port_id: str | None = None,
rotation: float = 0,
h_mirror: bool = False,
v_mirror: bool = False) -> ComponentReference
Returns Component reference.
Arguments:
position
- x, y position.port_id
- name of the port.rotation
- in degrees.h_mirror
- horizontal mirror using y axis (x, 1) (1, 0). This is the most common mirror.v_mirror
- vertical mirror using x axis (1, y) (0, y).
ref_center¶
def ref_center(position=(0, 0))
Returns a reference of the component centered at (x=0, y=0).
__repr__¶
def __repr__() -> str
Return a string representation of the object.
pprint¶
def pprint() -> None
Prints component info.
pprint_ports¶
def pprint_ports() -> None
Prints ports in a rich table.
metadata_child¶
@property
def metadata_child() -> dict
Returns metadata from child if any, Otherwise returns component own.
metadata Great to access the children metadata at the bottom of the hierarchy.
add_port¶
def add_port(name: str | object | None = None,
center: tuple[float, float] | None = None,
width: float | None = None,
orientation: float | None = None,
port: Port | None = None,
layer: LayerSpec | None = None,
port_type: str | None = None,
cross_section: CrossSectionSpec | None = None,
shear_angle: float | None = None) -> Port
Add port to component.
You can copy an existing port like add_port(port = existing_port) or create a new port add_port(myname, mycenter, mywidth, myorientation). You can also copy an existing port with a new name add_port(port = existing_port, name = new_name)
Arguments:
name
- port name.center
- x, y.width
- in um.orientation
- in deg.port
- optional port.layer
- port layer.port_type
- optical, electrical, vertical_dc, vertical_te, vertical_tm. Defaults to optical.cross_section
- port cross_section.shear_angle
- an optional angle to shear port face in degrees.
add_ports¶
def add_ports(ports: Iterable[Port] | dict[str, Port],
prefix: str = "",
suffix: str = "",
**kwargs) -> None
Add a list or dict of ports.
you can include a prefix to add to the new port names to avoid name conflicts.
Arguments:
ports
- list or dict of ports.prefix
- to prepend to each port name.suffix
- to append to each port name.
remove_layers¶
def remove_layers(layers: list[LayerSpec],
include_labels: bool = True,
invert_selection: bool = False,
recursive: bool = True) -> Component
Remove a list of layers and returns the same Component.
Arguments:
layers
- list of layers to remove.include_labels
- remove labels on those layers.invert_selection
- removes all layers except layers specified.recursive
- operate on the cells included in this cell.
extract¶
def extract(layers: list[tuple[int, int] | str]) -> Component
Extract polygons from a Component and returns a new Component.
add_polygon¶
def add_polygon(
points,
layer: str | int | tuple[int, int] | np.nan = np.nan) -> Polygon
Adds a Polygon to the Component.
Arguments:
points
- Coordinates of the vertices of the Polygon.layer
- layer spec to add polygon on.
add_ref_container¶
def add_ref_container(component: Component) -> ComponentReference
Add reference, ports and copy_child_info.
copy_child_info¶
def copy_child_info(component: Component) -> None
Copy and settings info from child component into parent.
Parent components can access child cells settings.
size_info¶
@property
def size_info() -> SizeInfo
Size info of the component.
is_unlocked¶
def is_unlocked() -> None
Raises error if Component is locked.
add¶
def add(element) -> None
Add a new element or list of elements to this Component.
Arguments:
element
- Polygon, ComponentReference or iterable The element or iterable of elements to be inserted in this cell.
Raises:
MutabilityError
- if component is locked.
add_array¶
def add_array(component: Component,
columns: int = 2,
rows: int = 2,
spacing: tuple[float, float] = (100, 100),
alias: str | None = None) -> ComponentReference
Creates a ComponentReference reference to a Component.
Arguments:
component
- The referenced component.columns
- Number of columns in the array.rows
- Number of rows in the array.spacing
- array-like[2] of int or float. Distance between adjacent columns and adjacent rows.alias
- str or None. Alias of the referenced Component.Returns
a
- ComponentReference containing references to the Component.
distribute¶
def distribute(elements="all",
direction="x",
spacing=100,
separation=True,
edge="center")
Distributes the specified elements in the Component.
Arguments:
elements : array-like of objects or ‘all’ Elements to distribute. direction : {‘x’, ‘y’} Direction of distribution; either a line in the x-direction or y-direction. spacing : int or float Distance between elements. separation : bool If True, guarantees elements are separated with a fixed spacing between; if False, elements are spaced evenly along a grid. edge : {‘x’, ‘xmin’, ‘xmax’, ‘y’, ‘ymin’, ‘ymax’} Which edge to perform the distribution along (unused if separation == True)
align¶
def align(elements="all", alignment="ymax")
Align elements in the Component.
Arguments:
elements : array-like of objects, or ‘all’ Elements in the Component to align. alignment : {‘x’, ‘y’, ‘xmin’, ‘xmax’, ‘ymin’, ‘ymax’} Which edge to align along (e.g. ‘ymax’ will move the elements such that all of their topmost points are aligned).
flatten¶
def flatten(single_layer: LayerSpec | None = None)
Returns a flattened copy of the component.
Flattens the hierarchy of the Component such that there are no longer any references to other Components. All polygons and labels from underlying references are copied and placed in the top-level Component. If single_layer is specified, all polygons are moved to that layer.
Arguments:
single_layer
- move all polygons are moved to the specified (optional).
flatten_reference¶
def flatten_reference(ref: ComponentReference) -> None
From existing cell replaces reference with a flatten reference which has the transformations already applied.
Transformed reference keeps the original name.
Arguments:
ref
- the reference to flatten into a new cell.
flatten_invalid_refs¶
def flatten_invalid_refs(grid_size: float | None = None,
updated_components=None,
traversed_components=None) -> Component
Returns new component with flattened references.
add_ref¶
def add_ref(component: Component,
alias: str | None = None,
**kwargs) -> ComponentReference
Add ComponentReference to the current Component.
Arguments:
component
- Component.alias
- named_references.
Arguments:
columns
- Number of columns in the array.rows
- Number of rows in the array.spacing
- Distances between adjacent columns and adjacent rows.origin
- array-like[2] of int or float Position where the cell is inserted. rotation : int or float Angle of rotation of the reference (indegrees
). magnification : int or float Magnification factor for the reference. x_reflection : bool If True, the reference is reflected parallel to the x direction before being rotated. name : str (optional) A name for the reference (if provided).
layers¶
@property
def layers() -> set[tuple[int, int]]
Returns a set of the Layers in the Component.
get_layers¶
def get_layers() -> set[tuple[int, int]]
Return a set of (layer, datatype).
.. code ::
import gdsfactory as gf
gf.components.straight().get_layers() == {(1, 0), (111, 0)}
get_layer_names¶
def get_layer_names() -> list[tuple[int, int]]
Return layer names used in the design.
.. code ::
import gdsfactory as gf
gf.components.straight().get_names() == ['WG']
_repr_html_¶
def _repr_html_()
Show geometry in KLayout and in matplotlib for Jupyter Notebooks.
add_pins_triangle¶
def add_pins_triangle(port_marker_layer: Layer = (1, 10),
layer_label: Layer = (1, 10),
make_copy: bool = True) -> Component
Returns component with triangular pins.
plot_widget¶
def plot_widget(show_ports: bool = True,
port_marker_layer: Layer = (1, 10)) -> None
Returns ipython widget for klayout visualization.
Arguments:
show_ports
- shows component with port markers and labels.port_marker_layer
- for the ports.
plot_klayout¶
def plot_klayout(show_ports: bool = True,
port_marker_layer: Layer = (1, 10),
show_labels: bool = False)
Returns klayout image.
If it fails to import klayout defaults to matplotlib.
Arguments:
show_ports
- shows component with port markers and labels.port_marker_layer
- for the ports.show_labels
- shows labels.
plot_kweb¶
def plot_kweb()
Shows current gds in kweb.
plot_matplotlib¶
def plot_matplotlib(**kwargs) -> None
Plot component using matplotlib.
Arguments:
show_ports
- Sets whether ports are drawn.show_subports
- Sets whether subports (ports that belong to references) are drawn.label_aliases
- Sets whether aliases are labeled with a text name.new_window
- If True, each call to quickplot() will generate a separate window.blocking
- If True, calling quickplot() will pause execution of (“block”) the remainder of the python code until the quickplot() window is closed. If False, the window will be opened and code will continue to run.zoom_factor
- Sets the scaling factor when zooming the quickplot window with the mousewheel/trackpad.interactive_zoom
- Enables using mousewheel/trackpad to zoom.fontsize
- for labels.layers_excluded
- list of layers to exclude.layer_views
- layer_views colors loaded from Klayout.min_aspect
- minimum aspect ratio.
plot¶
def plot(plotter: str | None = None, **kwargs)
Returns component plot using klayout, matplotlib, holoviews or qt.
We recommend using klayout.
Arguments:
plotter
- plot backend (‘matplotlib’, ‘widget’, ‘klayout’, ‘kweb’).
show¶
def show(show_ports: bool = False,
show_subports: bool = False,
port_marker_layer: Layer = (1, 10),
**kwargs) -> None
Show component in KLayout.
returns a copy of the Component, so the original component remains intact. with pins markers on each port show_ports = True, and optionally also the ports from the references (show_subports=True)
Arguments:
show_ports
- shows component with port markers and labels.show_subports
- add ports markers and labels to references.port_marker_layer
- for the ports.
Arguments:
gdspath
- GDS file path to write to.gdsdir
- directory for the GDS file. Defaults to /tmp/.unit
- unit size for objects in library. 1um by default.precision
- for object dimensions in the library (m). 1nm by default.timestamp
- Defaults to 2019-10-25. If None uses current time.
write_gds¶
def write_gds(gdspath: PathType | None = None,
gdsdir: PathType | None = None,
**kwargs) -> Path
Write component to GDS and returns gdspath.
Arguments:
gdspath
- GDS file path to write to.gdsdir
- directory for the GDS file. Defaults to /tmp/randomFile/gdsfactory.
Arguments:
unit
- unit size for objects in library. 1um by default.precision
- for dimensions in the library (m). 1nm by default.logging
- disable GDS path logging, for example for showing it in KLayout.on_duplicate_cell
- specify how to resolve duplicate-named cells. Choose one of the following:"warn"
default - overwrite all duplicate cells with one of the duplicates (arbitrarily)."error"
- throw a ValueError when attempting to write a gds with duplicate cells."overwrite"
- overwrite all duplicate cells with one of the duplicates, without warning.on_uncached_component
- Literal[“warn”, “error”] = “warn”flatten_invalid_refs
- flattens component references which have invalid transformations.max_points
- Maximal number of vertices per polygon. Polygons with more vertices that this are automatically fractured.with_metadata
- writes metadata in YAML format.with_netlist
- writes a netlist in JSON format.netlist_function
- function to generate the netlist.
write_oas¶
def write_oas(gdspath: PathType | None = None,
gdsdir: PathType | None = None,
**kwargs) -> Path
Write component to GDS and returns gdspath.
Arguments:
gdspath
- GDS file path to write to.gdsdir
- directory for the GDS file. Defaults to /tmp/randomFile/gdsfactory.
Arguments:
unit
- unit size for objects in library. 1um by default.precision
- for dimensions in the library (m). 1nm by default.logging
- disable GDS path logging, for example for showing it in KLayout.on_duplicate_cell
- specify how to resolve duplicate-named cells. Choose one of the following:"warn"
default - overwrite all duplicate cells with one of the duplicates (arbitrarily)."error"
- throw a ValueError when attempting to write a gds with duplicate cells."overwrite"
- overwrite all duplicate cells with one of the duplicates, without warning.None
- do not try to resolve (at your own risk!)on_uncached_component
- Literal[“warn”, “error”] = “warn”flatten_invalid_refs
- flattens component references which have invalid transformations.compression_level
- Level of compression for cells (between 0 and 9). Setting to 0 will disable cell compression, 1 gives the best speed and 9, the best compression.detect_rectangles
- Store rectangles in compressed format.detect_trapezoids
- Store trapezoids in compressed format.circle_tolerance
- Tolerance for detecting circles. If less or equal to 0, no detection is performed. Circles are stored in compressed format. validation (“crc32”, “checksum32”, None) – type of validation to include in the saved file.standard_properties
- Store standard OASIS properties in the file.
write_gds_with_metadata¶
def write_gds_with_metadata(*args, **kwargs) -> Path
Write component in GDS and metadata (component settings) in YAML.
to_dict¶
def to_dict(ignore_components_prefix: list[str] | None = None,
ignore_functions_prefix: list[str] | None = None,
with_cells: bool = False,
with_ports: bool = True) -> dict[str, Any]
Returns Dict representation of a component.
Arguments:
ignore_components_prefix
- for components to ignore when exporting.ignore_functions_prefix
- for functions to ignore when exporting.with_cells
- write cells recursively.with_ports
- write port information dict.
to_yaml¶
def to_yaml(**kwargs) -> str
Write Dict representation of a component in YAML format.
Arguments:
ignore_components_prefix
- for components to ignore when exporting.ignore_functions_prefix
- for functions to ignore when exporting.with_cells
- write cells recursively.with_ports
- write port information.
auto_rename_ports¶
def auto_rename_ports(**kwargs) -> None
Rename ports by orientation NSEW (north, south, east, west).
Arguments:
function
- to rename ports.select_ports_optical
- to select optical ports.select_ports_electrical
- to select electrical ports.prefix_optical
- prefix.prefix_electrical
- prefix... code::
3 4 |__| 2 -| |- 5 | | 1 -|______|- 6 | | 8 7
auto_rename_ports_orientation¶
def auto_rename_ports_orientation(**kwargs) -> None
Rename ports by orientation NSEW (north, south, east, west).
Arguments:
function
- to rename ports.select_ports_optical
- to select ports. select_ports_electrical: prefix_optical: prefix_electrical:.. code::
N0 N1 || W1 -| |- E1 | | W0 -|____|- E0 | | S0 S1
move¶
def move(origin: Float2 = (0, 0),
destination: Float2 | None = None,
axis: Axis | None = None) -> Component
Returns new Component with a moved reference to the original.
component.
Arguments:
origin
- of component.destination
- x, y.axis
- x or y.
mirror¶
def mirror(p1: Float2 = (0, 1), p2: Float2 = (0, 0), **kwargs) -> Component
Returns new Component with a mirrored reference.
Arguments:
p1
- first point to define mirror axis.p2
- second point to define mirror axis.
rotate¶
def rotate(angle: float = 90, **kwargs) -> Component
Returns new component with a rotated reference to the original.
Arguments:
angle
- in degrees.
add_padding¶
def add_padding(**kwargs) -> Component
Returns same component with padding.
Arguments:
component
- for padding.layers
- list of layers. suffix for name.default
- default padding (50um).top
- north padding.bottom
- south padding.right
- east padding.left
- west padding.
absorb¶
def absorb(reference) -> Component
Absorbs polygons from ComponentReference into Component.
Destroys the reference in the process but keeping the polygon geometry.
Arguments:
reference
- ComponentReference to be absorbed into the Component.
remove¶
def remove(items)
Removes items from a Component, which can include Ports, PolygonSets CellReferences, ComponentReferences and Labels.
Arguments:
items
- list of Items to be removed from the Component.
hash_geometry¶
def hash_geometry(precision: float = 1e-4) -> str
Returns an SHA1 hash of the geometry in the Component.
For each layer, each polygon is individually hashed and then the polygon hashes are sorted, to ensure the hash stays constant regardless of the ordering the polygons. Similarly, the layers are sorted by (layer, datatype).
Arguments:
precision
- Rounding precision for the the objects in the Component. For instance, a precision of 1e-2 will round a point at (0.124, 1.748) to (0.12, 1.75).
get_labels¶
def get_labels(apply_repetitions=True,
depth: int | None = None,
layer=None) -> list[Label]
Return labels.
Arguments:
apply_repetitions:.
depth
- None returns all labels and 0 top level.layer
- layerspec.
remove_labels¶
def remove_labels() -> None
Remove labels.
get_info¶
def get_info()
Gathers the .info dictionaries from every sub-Component and returns them in a list.
Arguments:
depth
- int or None If not None, defines from how many reference levels to retrieve Ports from.
Returns:
list of dictionaries List of the “.info” property dictionaries from all sub-Components
remap_layers¶
def remap_layers(layermap,
include_labels: bool = True,
include_paths: bool = True) -> Component
Returns a copy of the component with remapped layers.
Arguments:
layermap
- Dictionary of values in format {layer_from : layer_to}.include_labels
- Selects whether to move Labels along with polygons.include_paths
- Selects whether to move Paths along with polygons.
to_3d¶
def to_3d(layer_views: LayerViews | None = None,
layer_stack: LayerStack | None = None,
exclude_layers: tuple[Layer, ...] | None = None)
Return Component 3D trimesh Scene.
Arguments:
component
- to extrude in 3D.layer_views
- layer colors from Klayout Layer Properties file. Defaults to active PDK.layer_views.layer_stack
- contains thickness and zmin for each layer. Defaults to active PDK.layer_stack.exclude_layers
- layers to exclude.
to_np¶
def to_np(nm_per_pixel: int = 20,
layers: Layers = ((1, 0), ),
values: tuple[float, ...] | None = None,
pad_width: int = 1) -> np.ndarray
Returns a pixelated numpy array from Component polygons.
Arguments:
component
- Component.nm_per_pixel
- you can go from 20 (coarse) to 4 (fine).layers
- to convert. Order matters (latter overwrite former).values
- associated to each layer (defaults to 1).pad_width
- padding pixels around the image.
write_stl¶
def write_stl(filepath: str,
layer_stack: LayerStack | None = None,
exclude_layers: tuple[Layer, ...] | None = None,
use_layer_name: bool = False,
hull_invalid_polygons: bool = True,
scale: float | None = None) -> None
Write a Component to STL for 3D printing.
Arguments:
filepath
- to write STL to.layer_stack
- contains thickness and zmin for each layer.exclude_layers
- layers to exclude.use_layer_name
- If True, uses LayerLevel names in output filenames rather than gds_layer and gds_datatype.hull_invalid_polygons
- If True, replaces invalid polygons (determined by shapely.Polygon.is_valid) with its convex hull.scale
- Optional factor by which to scale meshes before writing.
write_gerber¶
def write_gerber(dirpath, layermap_to_gerber_layer, options) -> None
Arguments:
dirpath
- directory to write gerber files to.layermap_to_gerber_layer
- dictionary of layermap to gerber layer.options
- dictionary of options for gerber export.header
- List[str] | None = Nonemode
- Literal[“mm”, “in”] = “mm”resolution
- float = 1e-6int_size
- int = 4
to_gmsh¶
def to_gmsh(type: str,
layer_stack: LayerStack,
z: float | None = None,
xsection_bounds=None,
wafer_padding: float = 0.0,
wafer_layer: Layer = (99999, 0),
*args,
**kwargs)
Returns a gmsh mesh of the component for finite element simulation.
Arguments:
type
- one of “xy”, “uz”, or “3D”. Determines the type of mesh to return.layer_stack
- LayerStack object containing layer information.z
- used to define z-slice for xy meshing.xsection_bounds
- used to define in-plane line for uz meshing.wafer_padding
- padding beyond bbox to add to WAFER layers.wafer_layer
- layer to use for WAFER padding.
Arguments:
Arguments for the target meshing function in gplugins.gmsh
offset¶
def offset(distance: float = 0.1,
use_union: bool = True,
precision: float = 1e-4,
join: str = "miter",
tolerance: int = 2,
layer: LayerSpec = "WG") -> Component
Returns new Component with polygons eroded or dilated by an offset.
Arguments:
distance
- Distance to offset polygons. Positive values expand, negative shrink.use_union
- If True, use union of all polygons to offset. If False, offsetprecision
- Desired precision for rounding vertex coordinates.join
- {‘miter’, ‘bevel’, ‘round’} Type of join used to create polygon offsettolerance
- For miter joints, this number must be at least 2 represents the maximal distance in multiples of offset between new vertices and their original position before beveling to avoid spikes at acute joints. For round joints, it indicates the curvature resolution in number of points per full circle.layer
- Specific layer to put polygon geometry on.
copy¶
def copy(D: Component,
references=None,
ports=None,
polygons=None,
paths=None,
name=None,
labels=None) -> Component
Returns a Component copy.
Arguments:
D
- component to copy.
recurse_structures¶
def recurse_structures(
component: Component,
ignore_components_prefix: list[str] | None = None,
ignore_functions_prefix: list[str] | None = None) -> dict[str, Any]
Recurse component and components references recursively.
Arguments:
component
- component to recurse.ignore_components_prefix
- list of prefix to ignore.ignore_functions_prefix
- list of prefix to ignore.
flatten_invalid_refs_recursive¶
def flatten_invalid_refs_recursive(component: Component,
grid_size: float | None = None,
updated_components=None,
traversed_components=None) -> Component
Recursively flattens component references which have invalid transformations (i.e. non-90 deg rotations or sub-grid translations) returns a copy if any subcells have been modified.
WARNING: this function will produce same-name copies of cells. It is strictly meant to be used on write of the GDS file and should not be mixed with other cells, or you will likely experience issues with duplicate cells
Arguments:
component
- the component to fix (in place).grid_size
- the GDS grid size, in um, defaults to active PDK.get_grid_size() any translations with higher resolution than this are considered invalid.updated_components
- dict of components transformed. Should always be None, except for recursive.traversed_components
- the set of component names which have been traversed. Should always be None, except for recursive invocations.
gdsfactory.route_info¶
route_info¶
def route_info(cs_type: str,
length: float,
length_eff: float | None = None,
taper: bool = False,
**kwargs) -> dict[str, float | str]
Returns route info dict for pathlength analysis.
Arguments:
cs_type
- cross section type.length
- length.length_eff
- effective length (i.e. an equivalent straight length of a bend).taper
- True if this component is a taper.kwargs
- other attributes to track.
Returns:
A dictionary of routing attributes.
route_info_from_cs¶
def route_info_from_cs(cs: CrossSectionSpec,
length: float,
length_eff: float | None = None,
**kwargs) -> dict[str, float | str]
Returns route info dict for pathlength analysis.
Arguments:
cs
- cross section object or spec.length
- length.length_eff
- effective length (i.e. an equivalent straight length of a bend).kwargs
- other attributes to track.
Returns:
A dictionary of routing attributes.
gdsfactory.pack¶
pack a list of components into as few components as possible.
Adapted from PHIDL https://
pack¶
@validate_call
def pack(component_list: list[ComponentSpec],
spacing: float = 10.0,
aspect_ratio: Float2 = (1.0, 1.0),
max_size: tuple[float | None, float | None] = (None, None),
sort_by_area: bool = True,
density: float = 1.1,
precision: float = 1e-2,
text: ComponentSpec | None = None,
text_prefix: str = "",
text_mirror: bool = False,
text_rotation: int = 0,
text_offsets: tuple[Float2, ...] = ((0, 0), ),
text_anchors: tuple[Anchor, ...] = ("cc", ),
name_prefix: str | None = None,
rotation: int = 0,
h_mirror: bool = False,
v_mirror: bool = False,
add_ports_prefix: bool = True,
add_ports_suffix: bool = False) -> list[Component]
Pack a list of components into as few Components as possible.
Arguments:
component_list
- list or tuple.spacing
- Minimum distance between adjacent shapes.aspect_ratio
- (width, height) ratio of the rectangular bin.max_size
- Limits the size into which the shapes will be packed.sort_by_area
- Pre-sorts the shapes by area.density
- Values closer to 1 pack tighter but require more computation.precision
- Desired precision for rounding vertex coordinates.text
- Optional function to add text labels.text_prefix
- for labels. For example. ‘A’ will produce ‘A1’, ‘A2’, ...text_mirror
- if True mirrors text.text_rotation
- Optional text rotation.text_offsets
- relative to component size info anchor. Defaults to center.text_anchors
- relative to component (ce cw nc ne nw sc se sw center cc).name_prefix
- for each packed component (avoids the Unnamed cells warning). Note that the suffix contains a uuid so the name will not be deterministic.rotation
- optional component rotation in degrees.h_mirror
- horizontal mirror in y axis (x, 1) (1, 0). This is the most common.v_mirror
- vertical mirror using x axis (1, y) (0, y).add_ports_prefix
- adds port names with prefix.add_ports_suffix
- adds port names with suffix... plot:: :include-source:
import gdsfactory as gf from functools import partial
components = [gf.components.triangle(x=i) for i in range(1, 10)] c = gf.pack( components, spacing=20.0, max_size=(100, 100), text=partial(gf.components.text, justify=“center”), text_prefix=“R”, name_prefix=“demo”, text_anchors=[“nc”], text_offsets=[(-10, 0)], v_mirror=True, ) c[0].plot()
test_pack¶
def test_pack() -> None
Test packing function.
test_pack_with_settings¶
def test_pack_with_settings() -> None
Test packing function with custom settings.
gdsfactory.geometry.boolean_polygons¶
boolean_polygons¶
def boolean_polygons(operand1: ComponentReference | Component | gdstk.Polygon,
operand2: ComponentReference | Component | gdstk.Polygon,
operation: str,
output_layer: LayerSpec = (0, 0),
precision: float = 1e-3) -> list[gdstk.Polygon]
Perform a boolean operation and return the list of resulting Polygons. See gdstk docs for details.
Arguments:
operand1
- polygon set A.operand2
- polygon set B.operation
- the name of the operation to perform, i.e. “or”, “and”, “not”, or “xor”.output_layer
- the layer to assign the resulting polygons.precision
- the precision used for the operation, in microns.Returns
- a list of gdstk Polygons on the specified output layer.
gdsfactory.geometry.maskprep¶
get_polygons_over_under¶
def get_polygons_over_under(component: ComponentOrReference,
layers: LayerSpecs,
distances: Floats,
use_union: bool = True,
precision: float = 1e-4,
join: str = "miter",
tolerance: int = 2) -> list[gdstk.Polygon]
Returns list polygons dilated and eroded by an offset. Cleans min width gap and acute angle DRC errors equal to distances.
Arguments:
component
- Component containing polygons to offset.layers
- list of layers to remove min gap errors.distances
- Distance to offset polygons. By expanding and shrinking it merges polygons. If you want to fix min gaps of 0.5 use 0.5.precision
- Desired precision for rounding vertex coordinates.join
- {‘miter’, ‘bevel’, ‘round’} Type of join used to create polygon offsettolerance
- For miter joints, this number must be at least 2 represents the maximal distance in multiples of offset between new vertices and their original position before beveling to avoid spikes at acute joints. For round joints, it indicates the curvature resolution in number of points per full circle.layer
- Specific layer to put polygon geometry on.
Returns:
Component containing a polygon(s) with the specified offset applied.
over_under¶
@gf.cell
def over_under(component: ComponentSpec,
layers: LayerSpecs,
remove_original: bool = False,
**kwargs) -> Component
Returns cleaned component.
Arguments:
component:
layers
- list of layers.remove_original
- remove original layers.
gdsfactory.geometry.fillet¶
fillet¶
def fillet(operand: ComponentReference | Component | gdstk.Polygon
| list[gdstk.Polygon],
radius: float | list[float],
tolerance: float = 0.01) -> list[gdstk.Polygon]
Perform a fillet operation and return the list of resulting Polygons.
Arguments:
operand
- polygon, list of Polygons, Component, or ComponentReference.radius
- Fillet radius. You can also define a value for each vertex.tolerance
- for calculating the polygonal approximation of the filleted corners... plot:: :include-source:
import gdstk import gdsfactory as gf
points = [(0, 0), (1.2, 0), (1.2, 0.3), (1, 0.3), (1.5, 1), (0, 1.5)] p0 = gdstk.Polygon(points, datatype=1) p1 = gdstk.Polygon(points, datatype=1) p1 = gf.geometry.fillet(p1, radius=1.0)
c = gf.Component(“demo”) c.add_polygon(p0, layer=(1, 0)) c.add_polygon(p1, layer=(2, 0)) c.plot_matplotlib() c.show()
gdsfactory.geometry¶
Geometric operations: Booleans, DRC checks.
gdsfactory.geometry.layer_priority¶
layer_priority¶
@gf.cell
def layer_priority(component: ComponentSpec,
layer_high_order: LayerSpec,
layer_low_order: LayerSpec,
remove_high_order: bool = False,
**kwargs) -> gf.Component
Returns new component after removing one layer from another.
Arguments:
component
- spec.layer_high_order
- layer used to etch.layer_low_order
- layer etched into.remove_high_order
- whether to also remove the high order layer polygons. Useful if the higher order layer is purely logical.kwargs
- keyword arguments for boolean difference operation.
gdsfactory.geometry.fill_klayout¶
Dummy fill to keep density constant using klayout.
fill¶
def fill(gdspath,
layer_to_fill: LayerSpec,
layer_to_fill_margin: float = 0,
layers_to_avoid: tuple[LayerSpec, float] | None = None,
cell_name: str | None = None,
fill_cell_name: str = "fill_cell",
create_new_fill_cell: bool = False,
include_original: bool = False,
fill_layers: LayerSpecs | None = None,
fill_size: tuple[float, float] = (10, 10),
fill_spacing: tuple[float, float] = (20, 20),
fill_name: str | None = None,
gdspath_out: PathType | None = None) -> None
Write gds file with fill.
Arguments:
gdspath
- GDS input.layer_to_fill
- Layer that defines the region to fill.layer_to_fill_margin
- in um.layers_to_avoid
- Layer to avoid to margin (((1, 0), 3.5), (LAYER.SLAB, 2)).cell_name
- Optional cell to fill. Defaults to top cell.fill_cell_name
- Optional cell name to use as fill.create_new_fill_cell
- creates new fill cell, otherwise uses fill_cell_name from gdspath.include_original
- True include original gdspath. False returns only fill.fill_layers
- if create_new_fill_cell=True, defines new fill layers.fill_size
- if create_new_fill_cell=True, defines new fill size.fill_spacing
- fill pitch in x and y.fill_name
- name of the cell containing all fill cells. Defaults to Cell_fill.gdspath_out
- Optional GDS output. Defaults to input.
gdsfactory.geometry.maskprep_flat¶
gdsfactory.geometry.functions¶
area¶
def area(pts: ndarray) -> float64
Returns the area.
manhattan_direction¶
def manhattan_direction(p0, p1, tol=1e-5)
Returns manhattan direction between 2 points.
curvature¶
def curvature(points: ndarray, t: ndarray) -> ndarray
Args are the points and the tangents at each point.
points : numpy.array shape (n, 2) t: numpy.array of size n
Returns:
The curvature at each point.
Computes the curvature at every point excluding the first and last point.
For a planar curve parametrized as P(t) = (x(t), y(t)), the curvature is given by (x’ y’’ - x’’ y’ ) / (x’ **2 + y’ 2)(3/2)
path_length¶
def path_length(points: ndarray) -> float64
Returns: The path length.
Arguments:
points
- With shape (N, 2) representing N points with coordinates x, y.
snap_angle¶
def snap_angle(a: float64) -> int
Returns angle snapped along manhattan angle (0, 90, 180, 270).
a: angle in deg Return angle snapped along manhattan angle
angles_rad¶
def angles_rad(pts: ndarray) -> ndarray
Returns the angles (radians) of the connection between each point and the next.
angles_deg¶
def angles_deg(pts: ndarray) -> ndarray
Returns the angles (degrees) of the connection between each point and the next.
extrude_path¶
def extrude_path(points: ndarray,
width: float,
with_manhattan_facing_angles: bool = True,
spike_length: float64 | int | float = 0,
start_angle: int | None = None,
end_angle: int | None = None,
grid: float | None = None) -> ndarray
Deprecated. Use gdsfactory.path.Path.extrude() instead.
Extrude a path of width
along a curve defined by points
.
Arguments:
points
- numpy 2D array of shape (N, 2).width
- of the path to extrude.with_manhattan_facing_angles
- snaps to manhattan angles.spike_length
- in um.start_angle
- in degrees.end_angle
- in degrees.grid
- in um.
Returns:
numpy 2D array of shape (2*N, 2).
polygon_grow¶
def polygon_grow(polygon: ndarray, offset: float) -> ndarray
Returns a grown closed shaped polygon by an offset.
gdsfactory.geometry.trim¶
Trim component.
Adapted from PHIDL https://
trim¶
@gf.cell
def trim(component: Component,
domain: list[tuple[float, float]],
precision: float = 1e-4,
return_ports: bool | None = False) -> Component
Trim a component by another geometry, preserving the component’s layers and ports.
Useful to get a smaller component from a larger one for simulation.
Arguments:
component
- Component(/Reference).domain
- list of array-like[N][2] representing the boundary of the component to keep.precision
- float Desired precision for rounding vertex coordinates.return_ports
- whether to return the included ports or not. Ports are always renamed to avoid inheritance conflicts.Returns
- New component with layers (and possibly ports) of the component restricted to the domain... plot:: :include-source:
import gdsfactory as gf c = gf.components.straight_pin(length=10, taper=None) trimmed_c = gf.geometry.trim(component=c, domain=[[0, -5], [0, 5], [5, 5], [5, -5]]) trimmed_c.plot_matplotlib()
gdsfactory.geometry.boolean_klayout¶
boolean_klayout¶
@gf.cell
def boolean_klayout(gdspath1: ComponentOrPath,
gdspath2: ComponentOrPath,
layer1: tuple[int, int] = (1, 0),
layer2: tuple[int, int] = (1, 0),
layer3: tuple[int, int] = (2, 0),
operation: str = "xor") -> Component
Returns a boolean operation between two components Uses KLayout python API.
Arguments:
gdspath1
- path to GDS or Component.gdspath2
- path to GDS or Component.layer1
- tuple for gdspath1.layer2
- tuple for gdspath2.layer3
- for the result of the operation.
gdsfactory.geometry.boolean¶
Based on phidl.geometry.
boolean¶
@gf.cell
def boolean(A: ComponentOrReference | tuple[ComponentOrReference, ...],
B: ComponentOrReference | tuple[ComponentOrReference, ...],
operation: str,
precision: float = 1e-4,
layer: LayerSpec = (1, 0)) -> Component
Performs boolean operations between 2 Component/Reference/list objects.
operation
should be one of {‘not’, ‘and’, ‘or’, ‘xor’, ‘A-B’, ‘B-A’, ‘A+B’}.
Note that ‘A+B’ is equivalent to ‘or’, ‘A-B’ is equivalent to ‘not’, and
‘B-A’ is equivalent to ‘not’ with the operands switched
You can also use gdsfactory.drc.boolean_klayout
Arguments:
A
- Component(/Reference) or list of Component(/References).B
- Component(/Reference) or list of Component(/References).operation
- {‘not’, ‘and’, ‘or’, ‘xor’, ‘A-B’, ‘B-A’, ‘A+B’}.precision
- float Desired precision for rounding vertex coordinates.layer
- Specific layer to put polygon geometry on.Returns
- Component with polygon(s) of the boolean operations between the 2 input Components performed.Notes¶
- ‘A+B’ is equivalent to ‘or’.
- ‘A-B’ is equivalent to ‘not’.
- ‘B-A’ is equivalent to ‘not’ with the operands switched.
.. plot:: :include-source:
import gdsfactory as gf
c1 = gf.components.circle(radius=10).ref() c2 = gf.components.circle(radius=9).ref() c2.movex(5)
c = gf.geometry.boolean(c1, c2, operation=“xor”) c.plot_matplotlib()
gdsfactory.geometry.fill_tiled¶
gdsfactory.geometry.offset¶
Based on phidl.geometry.
offset¶
@gf.cell
def offset(elements: Component,
distance: float = 0.1,
use_union: bool = True,
precision: float = 1e-4,
join: str = "miter",
tolerance: int = 2,
layer: LayerSpec = "WG") -> Component
Returns new Component with polygons eroded or dilated by an offset.
Arguments:
elements
- Component(/Reference), list of Component(/Reference), or Polygon Polygons to offset or Component containing polygons to offset.distance
- Distance to offset polygons. Positive values expand, negative shrink.use_union
- If True, use union of all polygons to offset. If False, offsetprecision
- Desired precision for rounding vertex coordinates.join
- {‘miter’, ‘bevel’, ‘round’} Type of join used to create polygon offsettolerance
- For miter joints, this number must be at least 2 represents the maximal distance in multiples of offset between new vertices and their original position before beveling to avoid spikes at acute joints. For round joints, it indicates the curvature resolution in number of points per full circle.layer
- Specific layer to put polygon geometry on.
Returns:
Component containing a polygon(s) with the specified offset applied.
.. plot:: :include-source:
import gdsfactory as gf c = gf.Component() layer_slab = (2, 0) c1 = gf.components.coupler_ring( cladding_layers=[layer_slab], cladding_offsets=[0.5] ) d = 0.8 c2 = gf.geometry.offset(c1, distance=+d, layer=layer_slab) c3 = gf.geometry.offset(c2, distance=-d, layer=layer_slab)
c << c1.extract(layers=(“WG”,)) c << c3 c.plot_matplotlib()
gdsfactory.geometry.union¶
union¶
@gf.cell
def union(component: Component,
by_layer: bool = False,
precision: float = 1e-4,
join_first: bool = True,
layer: Layer = (1, 0)) -> Component
Returns new Component with inverted union of Component polygons.
based on phidl.geometry.union
Arguments:
component
- Component(/Reference), list of Component(/Reference), or Polygon A containing the polygons to perform union and inversion on.by_Layer
- performs the union operation layer-wise so each layer can be individually combined.precision
- Desired precision for rounding vertex coordinates.join_first
- before offsetting to avoid unnecessary joins in adjacent polygons.layer
- Specific layer to put polygon geometry on... plot:: :include-source:
import gdsfactory as gf c = gf.Component() c << gf.components.ellipse(radii=(6, 6)) c << gf.components.ellipse(radii=(10, 4)) c2 = gf.geometry.union(c, join_first=False)
gdsfactory.geometry.outline¶
outline¶
@gf.cell
def outline(elements,
distance=1,
precision: float = 1e-3,
join: str = "miter",
tolerance: int = 2,
join_first: bool = True,
open_ports: bool | float = False,
layer=0) -> Component
Returns Component containing the outlined polygon(s).
Creates an outline around all the polygons passed in the elements
argument. elements
may be a Component, Polygon, or list of Components.
Arguments:
elements
- Component(/Reference), list of Component(/Reference), or Polygon Polygons to outline or Component containing polygons to outline.distance
- int or float Distance to offset polygons. Positive values expand, negative shrink.precision
- float Desired precision for rounding vertex coordinates.join
- {‘miter’, ‘bevel’, ‘round’} Type of join used to create the offset polygon.tolerance
- int or float For miter joints, this number must be at least 2 and it represents the maximal distance in multiples of offset between new vertices and their original position before beveling to avoid spikes at acute joints. For round joints, it indicates the curvature resolution in number of points per full circle.open_ports
- bool or float If not False, holes will be cut in the outline such that the Ports are not covered. If True, the holes will have the same width as the Ports. If a float, the holes will be be widened by that value (useful for fully clearing the outline around the Ports for positive-tone processeslayer
- int, array-like[2], or set Specific layer(s) to put polygon geometry on.).
gdsfactory.geometry.xor_diff¶
xor_diff¶
@gf.cell
def xor_diff(A, B, precision: float = 1e-4) -> Component
Given two Components A and B, performs the layer-by-layer XOR difference between A and B and returns polygons representing the differences between A and B.
gdsfactory wrapper for phidl.geometry.xor_diff
Arguments:
A
- Component(/Reference) or list of Component(/References).B
- Component(/Reference) or list of Component(/References).precision
- Desired precision for rounding vertex coordinates.Returns
Component
- containing a polygon(s) defined by the XOR difference result between A and B.
gdsfactory.geometry.invert¶
Based on phidl.geometry.
invert¶
@gf.cell
def invert(elements,
border: float = 10.0,
precision: float = 1e-4,
layer: LayerSpec = (1, 0)) -> Component
Creates an inverted version of the input shapes with an additional border around the edges.
Arguments:
elements : Component(/Reference), list of Component(/Reference), or Polygon A Component containing the polygons to invert.
border
- Size of the border around the inverted shape (border value is the distance from the edges of the boundary box defining the inverted shape to the border, and is applied to all 4 sides of the shape).precision
- Desired precision for rounding vertex coordinates.layer
- Specific layer(s) to put polygon geometry on.Returns
D
- A Component containing the inverted version of the input shape(s) and the corresponding border(s)... plot:: :include-source:
import gdsfactory as gf
e1 = gf.components.ellipse(radii=(6, 6)) c = gf.geometry.invert(e1) c.plot_matplotlib()
gdsfactory.geometry.manhattanize¶
manhattanize_polygon¶
def manhattanize_polygon(p: Polygon, target_step: float = 0.05) -> Polygon
Return a Manhattanized version of the input polygon (where non-x and non-y parallel segments are decomposed into a staircase of small x and y-parallel segments)
Implemented in pure Python, and hence only suited to small polygons.
Arguments:
p
- input polygon.target_step
- target staircase step size.
Returns:
manhattanized polygon
.. plot:: :include-source:
import gdsfactory as gf c = gf.Component()
poly = gdstk.rectangle((-2, -2), (2, 2)) poly.rotate(np.pi / 4) poly.scale(1, 0.5) init_poly = c.add_polygon(poly, layer=1) final_poly = gf.geometry.manhattanize_polygon(poly) c.add_polygon(final_poly, layer=2) c.plot_matplotlib()
gdsfactory.polygon¶
Polygon
Adapted from PHIDL https://
Polygon Objects¶
class Polygon(gdstk.Polygon, _GeometryHelper)
Polygonal geometric object.
Arguments:
points
- array-like[N][2] Coordinates of the vertices of the Polygon.gds_layer
- int GDSII layer of the Polygon.gds_datatype
- int GDSII datatype of the Polygon.
__repr__¶
def __repr__() -> str
Returns path points.
bbox¶
@property
def bbox()
Returns the bounding box of the Polygon.
rotate¶
def rotate(angle: float = 45, center: tuple[float, float] = (0, 0)) -> Polygon
Rotates a Polygon by the specified angle.
Arguments:
angle
- Angle to rotate the Polygon in degrees.center
- Midpoint of the Polygon.
move¶
def move(origin: tuple[float, float] = (0, 0),
destination: tuple[float, float] | None = None,
axis: str | None = None) -> Polygon
Moves elements of the Device from the origin point to the destination. Both origin and destination can be 1x2 array-like, Port, or a key corresponding to one of the Ports in this device.
Arguments:
origin
- Origin point of the move. destination : Destination point of the move.axis
- {‘x’, ‘y’} Direction of move.
mirror¶
def mirror(p1=(0, 1), p2=(0, 0)) -> Polygon
Mirrors a Polygon across the line formed between the two
specified points. points
may be input as either single points
[1,2] or array-like[N][2], and will return in kind.
Arguments:
p1
- First point of the line.p2
- Second point of the line.
simplify¶
def simplify(tolerance: float = 1e-3) -> Polygon
Removes points from the polygon but does not change the polygon
shape by more than tolerance
from the original. Uses the
Ramer-Douglas-Peucker algorithm.
Arguments:
tolerance
- float Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting polygon by more than the value listed here will be removed. Also known asepsilon
here https://en .wikipedia .org /wiki /Ramer–Douglas–Peucker _algorithm
snap¶
def snap(nm: int = 1) -> sp.Polygon
Returns new polygon snap points to grid
gdsfactory.font¶
Support for font rendering in GDS files.
Adapted from PHIDL https://
gdsfactory.get_factories¶
get_cells¶
def get_cells(modules, verbose: bool = False) -> dict[str, ComponentFactory]
Returns PCells (component functions) from a module or list of modules.
Arguments:
modules
- module or iterable of modules.verbose
- prints in case any errors occur.
gdsfactory.get_netlist_flat¶
get_netlist_flat¶
def get_netlist_flat(component: Component, **kwargs) -> dict[str, Any]
Parses a recursive netlist for a component as if it was a single netlist with its lowest-level instances.
Procedure:
- Recursively parse the recursive dict to generate a unique list of all instances even if they are reused Each entry is formatted as [(netlist, instance),...], and defines a unique flat_name = {top}{hierarchy_delimiter}{instance}{hierarchy_delimiter}{instance}{hierarchy_delimiter}...
- Populate the flat netlist dict with similar entries as regular gdsfactory netlists:
- instances: component, info, and settings from the original netlist, but keyed with flat_name
- placements: For instance corresponding to each flat_name, accumulate placements across the hierarchy
- ports and connections: each unique port of each flat_name instance is uniquely named as flat_name,port_name for each flat_name,port_name, starting at lowest hierarchy level:
- list connections at that level (finding the proper other flat_name,port_name if non-leaf level)
- if possible, maps the port to a port of that instance’s netlist, and repeat at a higher level
- if the top level is reached, assign that flat_name,port_name to a top-level component port instead the returned ports dict has top level component portname: flat_name,port_name mappings the returned connections dict is sorted and flattened into a minimal (flat_name,port_name)_1: [(flat_name,port_name)] key: value pairs If allow_multiple flag in get_netlist is True, the values will be lists (to support multiple connections)
- name: top_level_component name
Arguments:
component
- to extract flat netlist.
Arguments:
component_suffix
- suffix to append to each component name. useful if to save and reload a back-annotated netlist.get_netlist_func
- function to extract individual netlists.full_settings
- True returns all, false changed settings.tolerance
- tolerance in nm to consider two ports connected.exclude_port_types
- optional list of port types to exclude from netlisting.get_instance_name
- function to get instance name.
Returns:
instances
- Dict of instance name and settings.connections
- Dict of Instance1Name,portName: Instance2Name,portName.placements
- Dict of instance names and placements (x, y, rotation).port
- Dict portName: ComponentName,port.name
- name of component.warnings
- warning messages (disconnected pins).
gdsfactory.port¶
We use Ports to connect Components with other Components.
we follow start from the bottom left and name the ports counter-clock-wise
.. code::
3 4
|___|_
2 -| |- 5
| |
1 -|______|- 6
| |
8 7
You can also rename them with W,E,S,N prefix (west, east, south, north).
.. code::
N0 N1
|___|_
W1 -| |- E1
| |
W0 -|______|- E0
| |
S0 S1
Adapted from PHIDL https://
Port Objects¶
class Port()
Ports are useful to connect Components with each other.
Arguments:
name
- we name ports clock-wise starting from bottom left.center
- (x, y) port center coordinate.width
- of the port in um.orientation
- in degrees (0: east, 90: north, 180: west, 270: south).parent
- parent component (component to which this port belong to).layer
- layer tuple.port_type
- str (optical, electrical, vertical_te, vertical_tm).parent
- Component that port belongs to.cross_section
- cross_section spec.shear_angle
- an optional angle to shear port face in degrees.
__init__¶
def __init__(name: str,
orientation: float | None,
center: tuple[float, float],
width: float | None = None,
layer: tuple[int, int] | None = None,
port_type: str = "optical",
parent: Component | None = None,
cross_section: CrossSection | None = None,
shear_angle: float | None = None) -> None
Initializes Port object.
__repr__¶
def __repr__() -> str
Return a string representation of the object.
__get_validators__¶
@classmethod
def __get_validators__(cls)
Get validators.
validate¶
@classmethod
def validate(cls, v, _info)
For pydantic assumes Port is valid if has a name and a valid type.
move_polar_copy¶
def move_polar_copy(d: float, angle: float) -> Port
Returns a copy of the port with a distance (d) in um and angle (deg).
move_copy¶
def move_copy(x, y=None) -> Port
Returns a copy of the port moved by a vector or given x and y.
flip¶
def flip(**kwargs) -> Port
Flips port.
endpoints¶
@property
def endpoints() -> None
Returns the endpoints of the Port.
endpoints¶
@endpoints.setter
def endpoints(points: Float2) -> None
Sets the endpoints of a Port.
normal¶
@property
def normal() -> ndarray
Returns a vector normal to the Port.
x¶
@property
def x() -> float
Returns the x-coordinate of the Port center.
y¶
@property
def y() -> float
Returns the y-coordinate of the Port center.
rotate¶
def rotate(angle: float = 45, center: Float2 | None = None) -> Port
Rotates a Port around the specified center point, if no centerpoint specified will rotate around (0,0).
Arguments:
angle
- Angle to rotate the Port in degrees.center
- array-like[2] or None center of the Port.
copy¶
def copy(name: str | None = None) -> Port
Returns a copy of the port.
Arguments:
name
- optional new name.
get_extended_center¶
def get_extended_center(length: float = 1.0) -> ndarray
Returns an extended port center.
snap_to_grid¶
def snap_to_grid(nm: int = 1) -> None
Snap port center to nm grid.
assert_on_grid¶
def assert_on_grid(nm: int = 1) -> None
Ensures ports edges are on grid to avoid snap_to_grid errors.
assert_manhattan¶
def assert_manhattan(nm: int = 1) -> None
Ensures port has a valid manhattan orientation (0, 90, 180, 270).
port_array¶
def port_array(center: tuple[float, float] = (0.0, 0.0),
width: float = 0.5,
orientation: float = 0,
pitch: tuple[float, float] = (10.0, 0.0),
n: int = 2,
**kwargs) -> list[Port]
Returns a list of ports placed in an array.
Arguments:
center
- center point of the port.width
- port width.orientation
- angle in degrees.pitch
- period of the port array.n
- number of ports in the array.
read_port_markers¶
def read_port_markers(
component: object, layers: LayerSpecs = ("PORT", )) -> Component
Returns extracted polygons from component layers.
Arguments:
component
- Component to extract markers.layers
- GDS layer specs.
csv2port¶
def csv2port(csvpath) -> dict[str, Port]
Reads ports from a CSV file and returns a Dict.
sort_ports_clockwise¶
def sort_ports_clockwise(ports: dict[str, Port]) -> dict[str, Port]
Sort and return ports in the clockwise direction.
.. code::
3 4
|___|_
2 -| |- 5
| |
1 -|______|- 6
| |
8 7
sort_ports_counter_clockwise¶
def sort_ports_counter_clockwise(ports: dict[str, Port]) -> dict[str, Port]
Sort and return ports in the counter-clockwise direction.
.. code::
4 3
|___|_
5 -| |- 2
| |
6 -|______|- 1
| |
7 8
select_ports¶
def select_ports(ports: dict[str, Port],
layer: tuple[int, int] | None = None,
prefix: str | None = None,
suffix: str | None = None,
orientation: int | None = None,
width: float | None = None,
layers_excluded: tuple[tuple[int, int], ...] | None = None,
port_type: str | None = None,
names: list[str] | None = None,
clockwise: bool = True) -> dict[str, Port]
Returns a dict of ports from a dict of ports.
Arguments:
ports
- Dict[str, Port] a port dict {port name: port}.layer
- select ports with port GDS layer.prefix
- select ports with port name prefix.suffix
- select ports with port name suffix.orientation
- select ports with orientation in degrees.width
- select ports with port width.layers_excluded
- List of layers to exclude.port_type
- select ports with port type (optical, electrical, vertical_te).clockwise
- if True, sort ports clockwise, False: counter-clockwise.
Returns:
Dict containing the selected ports {port name: port}.
rename_ports_by_orientation¶
def rename_ports_by_orientation(component: Component,
layers_excluded: LayerSpec | None = None,
select_ports: Callable = select_ports,
function=_rename_ports_facing_side,
prefix: str = "o",
**kwargs) -> Component
Returns Component with port names based on port orientation (E, N, W, S).
Arguments:
component
- to rename ports.layers_excluded
- to exclude.select_ports
- function to select_ports.function
- to rename ports.prefix
- to add on each port name.kwargs
- select_ports settings... code::
N0 N1 || W1 -| |- E1 | | W0 -|____|- E0 | | S0 S1
auto_rename_ports¶
def auto_rename_ports(component: Component,
function=_rename_ports_clockwise,
select_ports_optical: Callable
| None = select_ports_optical,
select_ports_electrical: Callable
| None = select_ports_electrical,
select_ports_placement: Callable
| None = select_ports_placement,
prefix: str = "",
prefix_optical: str = "o",
prefix_electrical: str = "e",
prefix_placement: str = "p",
port_type: str | None = None,
**kwargs) -> Component
Adds prefix for optical and electrical.
Arguments:
component
- to auto_rename_ports.function
- to rename ports.select_ports_optical
- to select optical ports.select_ports_electrical
- to select electrical ports.select_ports_placement
- to select placement ports.prefix_optical
- prefix of optical ports.prefix_electrical
- prefix of electrical ports.prefix_placement
- prefix of electrical ports.port_type
- select ports with port type (optical, electrical, vertical_te).
Arguments:
prefix
- select ports with port name prefix.suffix
- select ports with port name suffix.orientation
- select ports with orientation in degrees.width
- select ports with port width.layers_excluded
- List of layers to exclude.clockwise
- if True, sort ports clockwise, False: counter-clockwise.
map_ports_layer_to_orientation¶
def map_ports_layer_to_orientation(
ports: dict[str, Port],
function=_rename_ports_facing_side) -> dict[str, str]
Returns component or reference port mapping.
.. code::
N0 N1
|___|_
W1 -| |- E1
| |
W0 -|______|- E0
| |
S0 S1
map_ports_to_orientation_cw¶
def map_ports_to_orientation_cw(ports: dict[str, Port],
function=_rename_ports_facing_side,
**kwargs) -> dict[str, str]
Returns component or reference port mapping clockwise.
Arguments:
ports
- dict of ports.function
- to rename ports.kwargs
- for the function to rename ports... code::
N0 N1 || W1 -| |- E1 | | W0 -|____|- E0 | | S0 S1
auto_rename_ports_layer_orientation¶
def auto_rename_ports_layer_orientation(component: Component,
function=_rename_ports_facing_side,
prefix: str = "") -> None
Renames port names with layer_orientation (1_0_W0).
port orientation (E, N, W, S) numbering is clockwise
.. code::
N0 N1
|___|_
W1 -| |- E1
| |
W0 -|______|- E0
| |
S0 S1
gdsfactory.difftest_git¶
gdsdiff_git¶
def gdsdiff_git(path: str = "",
curr_file: str = "",
old_file: str = "",
old_hex: str = "",
old_mode: str = "",
new_file: str = "",
new_hex: str = "",
new_mode: str = "") -> None
Show diffs for two files when running git diff.
Arguments:
path
- script to run path.curr_file
- current GDS file.old_file
- old GDS.old_hex
- ignore.old_mode
- ignore.new_file
- new GDS file.new_hex
- ignore.new_mode
- ignore.
gdsfactory.read.from_gdspaths¶
from_gdspaths¶
def from_gdspaths(cells: tuple[ComponentOrPath, ...]) -> Component
Combine all GDS files or gf.components into a gf.component.
Arguments:
cells
- List of gdspaths or Components.
from_gdsdir¶
def from_gdsdir(dirpath: PathType) -> Component
Merges GDS cells from a directory into a single Component.
gdsfactory.read.labels¶
read_labels_yaml¶
def read_labels_yaml(csvpath: PathType,
prefix: str | None = None) -> dict[str, DictConfig]
Read labels from csvfile in YAML format.
add_port_markers¶
def add_port_markers(gdspath,
csvpath,
marker_size: int = 20,
marker_layer: LayerSpec = (203, 0))
Add port markers from port info extracted from a gdspath and csvpath.
gdsfactory.read.import_gds¶
import_gds¶
@cell
def import_gds(gdspath: str | Path,
cellname: str | None = None,
gdsdir: str | Path | None = None,
read_metadata: bool = False,
keep_name_short: bool = False,
unique_names: bool = True,
**kwargs) -> Component
Returns a Component from a GDS file.
appends $ with a number to the name if the cell name is on CACHE
Arguments:
gdspath
- path of GDS file.cellname
- cell of the name to import. None imports top cell.gdsdir
- optional GDS directory.read_metadata
- loads metadata (ports, settings) if it exists in YAML format.keep_name_short
- appends a hash to a shortened component name.unique_names
- appends $ with a number to the name if the cell name is on CACHE. This avoids name collisions when importing multiple times the same cell name.kwargs
- extra to add to component.info (polarization, wavelength ...).
gdsfactory.read.from_phidl¶
from_gdstk¶
@cache
def from_gdstk(cell: gdstk.Cell, **kwargs) -> Component
Returns gdsfactory Component from a gdstk cell.
Arguments:
cell
- gdstk cell.
Arguments:
cellname
- cell of the name to import (None) imports top cell.snap_to_grid_nm
- snap to different nm grid (does not snap if False).gdsdir
- optional GDS directory.read_metadata
- loads metadata if it exists.hashed_name
- appends a hash to a shortened component name.kwargs
- extra to add to component.info (polarization, wavelength ...).
from_phidl¶
@cache
def from_phidl(component, port_layer: Layer = (1, 0), **kwargs) -> Component
Returns gdsfactory Component from a phidl Device or function.
Arguments:
component
- phidl component.port_layer
- to add to component ports.
Arguments:
cellname
- cell of the name to import (None) imports top cell.snap_to_grid_nm
- snap to different nm grid (does not snap if False).gdsdir
- optional GDS directory.read_metadata
- loads metadata if it exists.hashed_name
- appends a hash to a shortened component name.kwargs
- extra to add to component.info (polarization, wavelength ...).
gdsfactory.read¶
gdsfactory.read.from_dphox¶
from_dphox¶
@cell_without_validator
def from_dphox(device, foundry) -> Component
Returns Gdsfactory Component from a dphox Device.
Note that you need to install dphox pip install dphox
https://
Arguments:
device
- Dphox device.foundry
- Dphox foundry object.
gdsfactory.read.from_yaml_template¶
split_default_settings_from_yaml¶
def split_default_settings_from_yaml(
yaml_lines: Iterable[str]) -> tuple[str, str]
Separates out the ‘default_settings’ block from the rest of the file body. Note: ‘default settings’ MUST be at the TOP of the file.
Arguments:
yaml_lines
- the lines of text in the yaml file.
Returns:
a tuple of (main file contents), (setting block), both as multi-line strings.
cell_from_yaml_template¶
def cell_from_yaml_template(
filename: str | IO[Any] | pathlib.Path,
name: str,
routing_strategy: dict[str, Callable] | None = None) -> Callable
Gets a PIC factory function from a yaml definition, which can optionally be a jinja template.
Arguments:
filename
- the filepath of the pic yaml template.name
- the name of the component to create.routing_strategy
- a dictionary of routing functions.
Returns:
a factory function for the component.
yaml_cell¶
def yaml_cell(yaml_definition, name: str,
routing_strategy) -> Callable[..., Component]
The “cell” decorator equivalent for yaml files. Generates a proper cell function for yaml-defined circuits.
Arguments:
yaml_definition
- the filename to the pic yaml definition.name
- the name of the pic to create.routing_strategy
- a dictionary of routing strategies to use for pic generation.
Returns:
a dynamically-generated function for the yaml file.
gdsfactory.read.from_np¶
Read component from a numpy.ndarray.
compute_area_signed¶
def compute_area_signed(pr) -> float
Return the signed area enclosed by a ring using the linear time.
algorithm at http://
from_np¶
@cell_without_validator
def from_np(ndarray: np.ndarray,
nm_per_pixel: int = 20,
layer: tuple[int, int] = (1, 0),
threshold: float = 0.99,
invert: bool = True) -> Component
Returns Component from a np.ndarray.
Extracts contours skimage.measure.find_contours using threshold
.
Arguments:
ndarray
- 2D ndarray representing the device layout.nm_per_pixel
- scale_factor.layer
- layer tuple to output gds.threshold
- value along which to find contours in the array.invert
- invert the mask.
from_image¶
@cell_without_validator
def from_image(image_path: str, **kwargs) -> Component
Returns Component from a png image.
Arguments:
image_path
- png file path.
Arguments:
nm_per_pixel
- scale_factor.layer
- layer tuple to output gds.threshold
- value along which to find contours in the array.
gdsfactory.read.from_yaml¶
Returns Component from YAML syntax.
name: myComponent settings: length: 3
info: description: just a demo polarization: TE ...
instances: mzi: component: mzi_phase_shifter settings: delta_length: ${settings.length} length_x: 50
pads:
component: pad_array
settings:
n: 2
port_names:
- e4
placements: mzi: x: 0 pads: y: 200 x: mzi,cc ports: o1: mzi,o1 o2: mzi,o2
routes: electrical: links: mzi,etop_e1: pads,e4_0 mzi,etop_e2: pads,e4_1
settings:
layer: [31, 0]
width: 10
radius: 10
place¶
def place(placements_conf: dict[str, dict[str, int | float | str]],
connections_by_transformed_inst: dict[str, dict[str, str]],
instances: dict[str, ComponentReference],
encountered_insts: list[str],
instance_name: str | None = None,
all_remaining_insts: list[str] | None = None) -> None
Place instance_name based on placements_conf config.
Arguments:
placements_conf
- Dict of instance_name to placement (x, y, rotation ...).connections_by_transformed_inst
- Dict of connection attributes. keyed by the name of the instance which should be transformed.instances
- Dict of references.encountered_insts
- list of encountered_instances.instance_name
- instance_name to place.all_remaining_insts
- list of all the remaining instances to place instances pop from this instance as they are placed.
transform_connections_dict¶
def transform_connections_dict(
connections_conf: dict[str, str]) -> dict[str, dict]
Returns Dict with source_instance_name key and connection properties.
make_connection¶
def make_connection(instance_src_name: str, port_src_name: str,
instance_dst_name: str, port_dst_name: str,
instances: dict[str, ComponentReference]) -> None
Connect instance_src_name,port to instance_dst_name,port.
Arguments:
instance_src_name
- source instance name.port_src_name
- from instance_src_name.instance_dst_name
- destination instance name.port_dst_name
- from instance_dst_name.instances
- dict of instances.
cell_from_yaml¶
def cell_from_yaml(yaml_str: str | pathlib.Path | IO[Any] | dict[str, Any]
| DictConfig,
routing_strategy: dict[str, Callable] | None = None,
label_instance_function: Callable = add_instance_label,
name: str | None = None,
prefix: str | None = None,
**kwargs) -> Callable
Returns Component factory from YAML string or file.
YAML includes instances, placements, routes, ports and connections.
Arguments:
yaml
- YAML string or file.routing_strategy
- for each route.label_instance_function
- to label each instance.name
- Optional name.prefix
- name prefix.kwargs
- function settings for creating YAML PCells... code::
valid variables:
name
- Optional Component namesettings
- Optional variablespdk
- overridesinfo
- Optional component infodescription
- just a demopolarization
- TE ... instances: name:component
- (ComponentSpec) settings (Optional)length
- 10 ... placements:x
- float, str | None str can be instanceName,portNamey
- float, str | Nonerotation
- float | Nonemirror
- bool, float | None float is x mirror axisport
- str | None port anchorconnections
Optional - between instancesports
Optional - ports to exposeroutes
Optional - bundles of routes routeName:library
- optical links:instance1,port1
- instance2,port2.. code::
settings:
length_mmi
- 5instances: mmi_bot:
component
- mmi1x2 settings:width_mmi
- 4.5length_mmi
- 10 mmi_top:component
- mmi1x2 settings:width_mmi
- 4.5length_mmi
- ${settings.length_mmi}placements: mmi_top:
port
- o1x
- 0y
- 0 mmi_bot:port
- o1x
- mmi_top,o2y
- mmi_top,o2dx
- 30dy
- -30 routes: optical:library
- optical links:mmi_top,o3
- mmi_bot,o1
from_yaml¶
def from_yaml(yaml_str: str | pathlib.Path | IO[Any] | dict[str, Any]
| DictConfig,
routing_strategy: dict[str, Callable] | None = None,
label_instance_function: Callable = add_instance_label,
name: str | None = None,
prefix: str | None = None,
**kwargs) -> Component
Returns Component from YAML string or file.
YAML includes instances, placements, routes, ports and connections.
Arguments:
yaml
- YAML string or file.routing_strategy
- for each route.label_instance_function
- to label each instance.name
- Optional name.prefix
- name prefix.kwargs
- function settings for creating YAML PCells... code::
valid variables:
name
- Optional Component namesettings
- Optional variablespdk
- overridesinfo
- Optional component infodescription
- just a demopolarization
- TE ... instances: name:component
- (ComponentSpec) settings (Optional)length
- 10 ... placements:x
- float, str | None str can be instanceName,portNamey
- float, str | Nonerotation
- float | Nonemirror
- bool, float | None float is x mirror axisport
- str | None port anchorconnections
Optional - between instancesports
Optional - ports to exposeroutes
Optional - bundles of routes routeName:library
- optical links:instance1,port1
- instance2,port2.. code::
settings:
length_mmi
- 5instances: mmi_bot:
component
- mmi1x2 settings:width_mmi
- 4.5length_mmi
- 10 mmi_top:component
- mmi1x2 settings:width_mmi
- 4.5length_mmi
- ${settings.length_mmi}placements: mmi_top:
port
- o1x
- 0y
- 0 mmi_bot:port
- o1x
- mmi_top,o2y
- mmi_top,o2dx
- 30dy
- -30 routes: optical:library
- optical links:mmi_top,o3
- mmi_bot,o1
gdsfactory.read.from_updk¶
Read uPDK YAML definition and returns a gdsfactory script.
https://
from_updk¶
def from_updk(filepath: PathType,
filepath_out: PathType | None = None,
layer_bbox: tuple[int, int] = (68, 0),
layer_bbmetal: tuple[int, int] | None = None,
layer_label: tuple[int, int] | None = None,
layer_pin_label: tuple[int, int] | None = None,
layer_pin: tuple[int, int] | None = None,
optical_xsections: list[str] | None = None,
electrical_xsections: list[str] | None = None,
layers_text: list[LayerSpec] | None = None,
text_size: float = 2.0,
activate_pdk: bool = False,
read_xsections: bool = True,
prefix: str = "",
suffix: str = "") -> str
Read uPDK definition and returns a gdsfactory script.
Arguments:
filepath
- uPDK filepath definition.filepath_out
- optional filepath to save script. if None only returns script and does not save it.layer_bbox
- layer to draw bounding boxes.layer_bbmetal
- layer to draw bounding boxes for metal.optical_xsections
- Optional list of names of xsections that will add optical ports.electrical_xsections
- Optional list of names of xsections that will add electrical ports.layers_text
- Optional list of layers to add text labels.text_size
- text size for labels.activate_pdk
- if True, activate the pdk after writing the script.read_xsections
- if True, read xsections from uPDK.prefix
- optional prefix to add to the script.suffix
- optional suffix to add to the script.
gdsfactory.export.to_gerber¶
Based on Gerber file spec:
https://
See Also:
- https://
github .com /opiopan /pcb -tools -extension - https://
github .com /jamesbowman /cuflow /blob /master /gerber .py
to_gerber¶
def to_gerber(
component: Component,
dirpath: Path,
layermap_to_gerber_layer: dict[tuple[int, int], GerberLayer],
options: GerberOptions = Field(default_factory=dict)
) -> None
Writes each layer to a different Gerber file.
Arguments:
component
- to export.dirpath
- directory path.layermap_to_gerber_layer
- map of GDS layer to GerberLayer.options
- to save.header
- List[str] | None = Nonemode
- Literal[“mm”, “in”] = “mm”resolution
- float = 1e-6int_size
- int = 4
gdsfactory.export¶
gdsfactory.export.to_np¶
to_np¶
def to_np(component: Component,
nm_per_pixel: int = 20,
layers: Layers = ((1, 0), ),
values: Floats | None = None,
pad_width: int = 1) -> np.ndarray
Returns a pixelated numpy array from Component polygons.
Arguments:
component
- Component.nm_per_pixel
- you can go from 20 (coarse) to 4 (fine).layers
- to convert. Order matters (latter overwrite former).values
- associated to each layer (defaults to 1).pad_width
- padding pixels around the image.
gdsfactory.export.to_stl¶
to_stl¶
def to_stl(component: Component,
filepath: str,
layer_stack: LayerStack | None = None,
exclude_layers: tuple[Layer, ...] | None = None,
use_layer_name: bool = False,
hull_invalid_polygons: bool = True,
scale: float | None = None) -> None
Exports a Component into STL.
Arguments:
component
- to export.filepath
- filepath prefix to write STL to. Each file will have each exported layer as suffix.layer_stack
- contains thickness and zmin for each layer.exclude_layers
- layers to exclude.use_layer_name
- If True, uses LayerLevel names in output filenames rather than gds_layer and gds_datatype.hull_invalid_polygons
- If True, replaces invalid polygons (determined by shapely.Polygon.is_valid) with its convex hull.scale
- Optional factor by which to scale meshes before writing.
gdsfactory.export.to_3d¶
to_3d¶
def to_3d(component: Component,
layer_views: LayerViews | None = None,
layer_stack: LayerStack | None = None,
exclude_layers: tuple[Layer, ...] | None = None)
Return Component 3D trimesh Scene.
Arguments:
component
- to extrude in 3D.layer_views
- layer colors from Klayout Layer Properties file. Defaults to active PDK.layer_views.layer_stack
- contains thickness and zmin for each layer. Defaults to active PDK.layer_stack.exclude_layers
- layers to exclude.
gdsfactory.add_keepout¶
add_keepout¶
@cell
def add_keepout(component: Component,
target_layers: Layers,
keepout_layers: Layers,
margin: float = 2.0) -> Component
Adds keepout after looking up all polygons in a cell.
You can also use add_padding for rectangular keepout.
Arguments:
component
- to add keepout.target_layers
- list of layers to read.keepout_layers
- list of layers to add keepout.margin
- offset from target to keepout_layers.
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.
- Route: dataclass with 3 attributes.
- references: list of references (straights, bends and tapers).
- ports: dict(input=PortIn, output=PortOut).
- length: how long is this route?
Factories:
- ComponentFactory: function that returns a Component.
- RouteFactory: function that returns a Route.
Specs:
- ComponentSpec: Component, function, string or dict (component=mzi, settings=dict(delta_length=20)).
- LayerSpec: (3, 0), 3 (assumes 0 as datatype) or string.
Step Objects¶
@dataclasses.dataclass
class Step()
Manhattan Step.
Arguments:
x
- absolute.y
- absolute.dx
- x-displacement.dy
- y-displacement.
StepAllAngle Objects¶
@dataclasses.dataclass
class StepAllAngle()
separation¶
All angle Ste.
Arguments:
x
- absolute.y
- absolute.dx
- x-displacement.dy
- y-displacement.exit_angle
- in degrees.cross_section
- spec.connector
- define transition.separation
- in um.
Layer¶
Tuple of integer (layer, datatype)
LayerSpec¶
tuple of integers (layer, datatype), a integer (layer, 0) or a string (layer_name)
ComponentSpec¶
PCell function, function name, dict or Component
CellSpec¶
PCell function, function name or dict
CrossSectionSpec¶
cross_section function, function name or dict
NetlistModel Objects¶
class NetlistModel(BaseModel)
Netlist defined component.
Arguments:
instances
- dict of instances (name, settings, component).placements
- dict of placements.connections
- dict of connections.routes
- dict of routes.name
- component name.info
- information (polarization, wavelength ...).settings
- input variables.ports
- exposed component ports.
TypedArray Objects¶
class TypedArray(np.ndarray)
based on https://
gdsfactory.get_netlist¶
Extract netlist from component port connectivity.
Assumes two ports are connected when they have same width, x, y
.. code:: yaml
connections:
- coupler,N0:bendLeft,W0
- coupler,N1:bendRight,N0
- bednLeft,N0:straight,W0
- bendRight,N0:straight,E0
ports:
- coupler,E0
- coupler,W0
get_instance_name_from_alias¶
def get_instance_name_from_alias(component: Component,
reference: ComponentReference) -> str
Returns the instance name from the label.
If no label returns to instanceName_x_y.
Arguments:
component
- with labels.reference
- reference that needs naming.
get_instance_name_from_label¶
def get_instance_name_from_label(
component: Component,
reference: ComponentReference,
layer_label: LayerSpec = "LABEL_INSTANCE") -> str
Returns the instance name from the label.
If no label returns to instanceName_x_y.
Arguments:
component
- with labels.reference
- reference that needs naming.layer_label
- ignores layer_label[1].
get_netlist_yaml¶
def get_netlist_yaml(component: Component,
full_settings: bool = False,
tolerance: int = 5,
exclude_port_types: list | None = None,
**kwargs) -> str
Returns instances, connections and placements yaml string content.
get_netlist¶
def get_netlist(
component: Component,
full_settings: bool = False,
tolerance: int = 5,
exclude_port_types: list[str] | tuple[str] | None = ("placement", ),
get_instance_name: Callable[..., str] = get_instance_name_from_alias,
allow_multiple: bool = False) -> dict[str, Any]
From Component returns instances, connections and placements dict.
Does two sweeps over the connections:
- first tries to connect everything assuming perfect connections at each port.
- Then gathers ports which did not perfectly connect to anything and tries to find imperfect connections, by grouping ports on a coarse grid.
warnings collected during netlisting are reported back into the netlist. These include warnings about mismatched port widths, orientations, shear angles, excessive offsets, etc. You can also configure warning types which should throw an error when encountered by modifying DEFAULT_CRITICAL_CONNECTION_ERROR_TYPES. Validators, which will produce warnings for each port type, can be overridden with DEFAULT_CONNECTION_VALIDATORS A key difference in this algorithm is that we group each port type independently. This allows us to use different logic to determine i.e. if an electrical port is properly connected vs an optical port. In this function, the core logic is the same, but we employ extra validation for optical ports. snap_to_grid() allows a value of 0, which will return the original value, is more efficient when the value is 1, and will throw a more descriptive error when the value is <0 the default value of tolerance is 5nm because it should allow better performance with the two-grid-sweep approach.
Arguments:
component
- to extract netlist.full_settings
- True returns all, false changed settings.tolerance
- tolerance in nm to consider two ports connected.exclude_port_types
- optional list of port types to exclude from netlisting.get_instance_name
- function to get instance name.allow_multiple
- False to raise an error if more than two ports share the same connection. if True, will return key: [value] pairs with [value] a list of all connected instances.
Returns:
instances
- Dict of instance name and settings.connections
- Dict of Instance1Name,portName: Instance2Name,portName.placements
- Dict of instance names and placements (x, y, rotation).port
- Dict portName: ComponentName,port.name
- name of component.warnings
- warning messages (disconnected pins).
get_netlist_recursive¶
def get_netlist_recursive(component: Component,
component_suffix: str = "",
get_netlist_func: Callable = get_netlist,
get_instance_name: Callable[
..., str] = get_instance_name_from_alias,
**kwargs) -> dict[str, Any]
Returns recursive netlist for a component and subcomponents.
Arguments:
component
- to extract netlist.component_suffix
- suffix to append to each component name. useful if to save and reload a back-annotated netlist.get_netlist_func
- function to extract individual netlists.
Arguments:
full_settings
- True returns all, false changed settings.tolerance
- tolerance in nm to consider two ports connected.exclude_port_types
- optional list of port types to exclude from netlisting.get_instance_name
- function to get instance name.
Returns:
Dictionary of netlists, keyed by the name of each component.
gdsfactory.decorators¶
is_valid_transformation¶
def is_valid_transformation(ref: ComponentReference,
grid_size: float | None = None) -> bool
Returns True if the component has valid transformations.
Arguments:
component
- the component reference to check.grid_size
- the GDS grid size, in um, defaults to active PDK.get_grid_size() any translations with higher resolution than this are considered invalid.
has_valid_transformations¶
def has_valid_transformations(component: Component) -> bool
Returns True if the component has valid transformations.
flatten_invalid_refs¶
def flatten_invalid_refs(component: Component, grid_size: float | None = None)
Flattens component references which have invalid transformations.
(i.e. non-90 deg rotations or sub-grid translations).
This is an in-place operation, so you should use it as a decorator. flattens only individual references with invalid transformations.
Deprecated Use Component.write_gds(flatten_invalid_refs=True)
Arguments:
component
- the component to fix (in place).grid_size
- the GDS grid size, in um, defaults to active PDK.get_grid_size() any translations with higher resolution than this are considered invalid.
gdsfactory.component_layout¶
Helper functions for layout.
Adapted from PHIDL https://
get_polygons¶
def get_polygons(
instance,
by_spec: bool | tuple[int, int] = False,
depth: int | None = None,
include_paths: bool = True,
as_array: bool = True,
as_shapely: bool = False,
as_shapely_merged: bool = False
) -> list[Polygon] | dict[tuple[int, int], list[Polygon]]
Return a list of polygons in this cell.
Arguments:
by_spec
- bool or layer If True, the return value is a dictionary with the polygons of each individual pair (layer, datatype), which are used as keys. If set to a tuple of (layer, datatype), only polygons with that specification are returned.depth
- integer or None If not None, defines from how many reference levels to retrieve polygons. References below this level will result in a bounding box. Ifby_spec
is True the key will be the name of this cell.include_paths
- If True, polygonal representation of paths are also included in the result.as_array
- when as_array=false, return the Polygon objects instead. polygon objects have more information (especially when by_spec=False) and are faster to retrieve.as_shapely
- returns shapely polygons.Returns
out
- list of array-like[N][2] or dictionary List containing the coordinates of the vertices of each polygon, or dictionary with with the list of polygons (ifby_spec
is True).
Notes:
Instances of FlexPath
and RobustPath
are also included in
the result by computing their polygonal boundary.
_GeometryHelper Objects¶
class _GeometryHelper()
Helper class for a class with functions move() and the property bbox.
It uses that function+property to enable you to do things like check what the center of the bounding box is (self.center), and also to do things like move the bounding box such that its maximum x value is 5.2 (self.xmax = 5.2).
center¶
@property
def center()
Returns the center of the bounding box.
center¶
@center.setter
def center(destination) -> None
Sets the center of the bounding box.
Arguments:
destination : array-like[2] Coordinates of the new bounding box center.
x¶
@property
def x()
Returns the x-coordinate of the center of the bounding box.
x¶
@x.setter
def x(destination) -> None
Sets the x-coordinate of the center of the bounding box.
Arguments:
destination : int or float x-coordinate of the bbox center.
y¶
@property
def y()
Returns the y-coordinate of the center of the bounding box.
y¶
@y.setter
def y(destination) -> None
Sets the y-coordinate of the center of the bounding box.
Arguments:
destination : int or float y-coordinate of the bbox center.
xmax¶
@property
def xmax()
Returns the maximum x-value of the bounding box.
xmax¶
@xmax.setter
def xmax(destination) -> None
Sets the x-coordinate of the maximum edge of the bounding box.
Arguments:
destination : int or float x-coordinate of the maximum edge of the bbox.
ymax¶
@property
def ymax()
Returns the maximum y-value of the bounding box.
ymax¶
@ymax.setter
def ymax(destination) -> None
Sets the y-coordinate of the maximum edge of the bounding box.
Arguments:
destination : int or float y-coordinate of the maximum edge of the bbox.
xmin¶
@property
def xmin()
Returns the minimum x-value of the bounding box.
xmin¶
@xmin.setter
def xmin(destination) -> None
Sets the x-coordinate of the minimum edge of the bounding box.
Arguments:
destination : int or float x-coordinate of the minimum edge of the bbox.
ymin¶
@property
def ymin()
Returns the minimum y-value of the bounding box.
ymin¶
@ymin.setter
def ymin(destination) -> None
Sets the y-coordinate of the minimum edge of the bounding box.
Arguments:
destination : int or float y-coordinate of the minimum edge of the bbox.
size¶
@property
def size()
Returns the (x, y) size of the bounding box.
xsize¶
@property
def xsize()
Returns the horizontal size of the bounding box.
ysize¶
@property
def ysize()
Returns the vertical size of the bounding box.
movex¶
def movex(origin=0, destination=None)
Moves an object by a specified x-distance.
Arguments:
origin
- array-like[2], Port, or key Origin point of the move.destination
- array-like[2], Port, key, or None Destination point of the move.
movey¶
def movey(origin=0, destination=None)
Moves an object by a specified y-distance.
Arguments:
origin : array-like[2], Port, or key Origin point of the move. destination : array-like[2], Port, or key Destination point of the move.
__add__¶
def __add__(element) -> Group
Adds an element to a Group.
Arguments:
element
- Component, ComponentReference, Port, Polygon, Label, or Group to add.
Group Objects¶
class Group(_GeometryHelper)
Group objects together so you can manipulate them as a single object (move/rotate/mirror).
__init__¶
def __init__(*args) -> None
Initialize Group.
__repr__¶
def __repr__() -> str
Prints the number of elements in the Group.
__len__¶
def __len__() -> float
Returns the number of elements in the Group.
__iadd__¶
def __iadd__(element) -> Group
Adds an element to the Group.
Arguments:
element
- Component, ComponentReference, Port, Polygon, Label, or Group to add.
bbox¶
@property
def bbox()
Returns the bounding boxes of the Group.
add¶
def add(element) -> Group
Adds an element to the Group.
Arguments:
element
- Component, ComponentReference, Port, Polygon, Label, or Group to add.
rotate¶
def rotate(angle: float = 45, center=(0, 0)) -> Group
Rotates all elements in a Group around the specified centerpoint.
Arguments:
angle : int or float Angle to rotate the Group in degrees. center : array-like[2] or None center of the Group.
move¶
def move(origin=(0, 0), destination=None, axis=None) -> Group
Moves the Group from the origin point to the destination.
Both origin and destination can be 1x2 array-like, Port, or a key corresponding to one of the Ports in this Group.
Arguments:
origin : array-like[2], Port, or key Origin point of the move. destination : array-like[2], Port, or key Destination point of the move. axis : {‘x’, ‘y’} Direction of the move.
mirror¶
def mirror(p1=(0, 1), p2=(0, 0)) -> Group
Mirrors a Group across the line formed between the two specified points.
points
may be input as either single points
[1,2] or array-like[N][2], and will return in kind.
Arguments:
p1 : array-like[N][2] First point of the line. p2 : array-like[N][2] Second point of the line.
distribute¶
def distribute(direction="x",
spacing=100,
separation=True,
edge="center") -> Group
Distributes the elements in the Group.
Arguments:
direction : {‘x’, ‘y’} Direction of distribution; either a line in the x-direction or y-direction. spacing : int or float Distance between elements. separation : bool If True, guarantees elements are separated with a fixed spacing between; if False, elements are spaced evenly along a grid. edge : {‘x’, ‘xmin’, ‘xmax’, ‘y’, ‘ymin’, ‘ymax’} Which edge to perform the distribution along (unused if separation == True)
align¶
def align(alignment="ymax") -> Group
Aligns the elements in the Group.
Arguments:
alignment : {‘x’, ‘y’, ‘xmin’, ‘xmax’, ‘ymin’, ‘ymax’} Which edge to align along (e.g. ‘ymax’ will align move the elements such that all of their topmost points are aligned)
gdsfactory.add_padding¶
get_padding_points¶
def get_padding_points(component: Component,
default: float = 50.0,
top: float | None = None,
bottom: float | None = None,
right: float | None = None,
left: float | None = None) -> list[float]
Returns padding points for a component outline.
Arguments:
component
- to add padding.default
- default padding in um.top
- north padding in um.bottom
- south padding in um.right
- east padding in um.left
- west padding in um.
add_padding¶
def add_padding(component: ComponentSpec = "mmi2x2",
layers: tuple[LayerSpec, ...] = ("PADDING", ),
**kwargs) -> Component
Adds padding layers to component. Returns same component.
Arguments:
component
- to add padding.layers
- list of layers.keyword Args:
default
- default padding.top
- north padding in um.bottom
- south padding in um.right
- east padding in um.left
- west padding in um.
add_padding_container¶
@cell
def add_padding_container(component: ComponentSpec,
layers: tuple[LayerSpec, ...] = ("PADDING", ),
**kwargs) -> Component
Returns new component with padding added.
Arguments:
component
- to add padding.layers
- list of layers.
Arguments:
default
- default padding in um.top
- north padding in um.bottom
- south padding in um.right
- east padding in um.left
- west padding in um.
add_padding_to_size¶
def add_padding_to_size(component: ComponentSpec,
layers: tuple[LayerSpec, ...] = ("PADDING", ),
xsize: float | None = None,
ysize: float | None = None,
left: float = 0,
bottom: float = 0) -> Component
Returns component with padding layers on each side.
New size is multiple of grid size.
Arguments:
component
- to add padding.layers
- list of layers.xsize
- x size to fill up in um.ysize
- y size to fill up in um.left
- left padding in um to fill up in um.bottom
- bottom padding in um to fill up in um.
add_padding_to_size_container¶
@cell
def add_padding_to_size_container(component: ComponentSpec,
layers: tuple[LayerSpec,
...] = ("PADDING", ),
xsize: float | None = None,
ysize: float | None = None,
left: float = 0,
bottom: float = 0) -> Component
Returns new component with padding layers on each side. New size is.
multiple of grid size.
Arguments:
component
- to add padding.layers
- list of layers.xsize
- x size to fill up in um.ysize
- y size to fill up in um.left
- left padding in um to fill up in um.bottom
- bottom padding in um to fill up in um.
gdsfactory.pixelate¶
pixelate_path¶
def pixelate_path(pts: Coordinates,
pixel_size: float = 0.55,
snap_res: float = 0.05,
middle_offset: float = 0.5,
theta_start: float = 0,
theta_end: float = 90) -> Coordinates
From a path add one pixel per point on the path.
Arguments:
pts
- points.pixel_size
- in um.snap_res
- snap resolution.middle_offset
- in um.theta_start
- in degrees.theta_end
- in degrees.
pixelate¶
def pixelate(pts, N=100, margin=0.4, **kwargs)
Pixelate shape defined by points Return rectangles [Rect1, Rect2, ...] ready to go in the quad tree.
gdsfactory.show¶
show¶
def show(component: Component | str | pathlib.Path,
technology: str | None = None,
**kwargs) -> None
Write GDS and show Component in KLayout.
Arguments:
component
- Component or GDS path.technology
- Name of KLayout technology to load when displaying component.
Arguments:
gdspath
- GDS file path to write to.gdsdir
- directory for the GDS file. Defaults to /tmp/.unit
- unit size for objects in library. 1um by default.precision
- for object dimensions in the library (m). 1nm by default.timestamp
- Defaults to 2019-10-25. If None uses current time.
gdsfactory.cross_section¶
You can define a path as list of points.
To create a component you need to extrude the path with a cross-section.
Section Objects¶
class Section(BaseModel)
CrossSection to extrude a path with a waveguide.
Arguments:
width
- of the section (um) or parameterized function from 0 to 1. the width at t==0 is the width at the beginning of the Path. the width at t==1 is the width at the end.offset
- center offset (um) or function parameterized function from 0 to 1. the offset at t==0 is the offset at the beginning of the Path. the offset at t==1 is the offset at the end.insets
- distance (um) in x to inset section relative to end of the Path (i.e. (start inset, stop_inset)).layer
- layer spec. If None does not draw the main section.port_names
- Optional port names.port_types
- optical, electrical, ...name
- Optional Section name.hidden
- hide layer.simplify
- Optional Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed... code::
0 offset |<-------------->| | _____ | | | | |layer| | |_____| | <----> width
ComponentAlongPath Objects¶
class ComponentAlongPath(BaseModel)
A ComponentAlongPath object to place along an extruded path.
Arguments:
component
- Component to repeat along the path. The unrotated version of this object should be oriented for placement on a horizontal line.spacing
- distance between component placementspadding
- minimum distance from the path start to the first component.y_offset
- offset in y direction (um).
CrossSection Objects¶
class CrossSection(BaseModel)
Waveguide information to extrude a path.
cladding_layers follow path shape, while bbox_layers are rectangular.
Arguments:
layer
- main Section layer. Main section name = ‘_default’. If None does not draw the main section.width
- main Section width (um) or function parameterized from 0 to 1. the width at t==0 is the width at the beginning of the Path. the width at t==1 is the width at the end.offset
- main Section center offset (um) or function from 0 to 1. the offset at t==0 is the offset at the beginning of the Path. the offset at t==1 is the offset at the end.radius
- main Section bend radius (um).simplify
- main Section Optional Tolerance value for the simplification algorithm.width_wide
- wide waveguides width (um) for low loss routing.auto_widen
- taper to wide waveguides for low loss routing.auto_widen_minimum_length
- minimum straight length for auto_widen.taper_length
- taper_length for auto_widen.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- list of layers to extrude.cladding_offsets
- list of offset from main Section edge.cladding_simplify
- Optional Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed.sections
- list of Sections(width, offset, layer, ports).port_names
- for input and output (‘o1’, ‘o2’).port_types
- for input and output: electrical, optical, vertical_te ...gap
- edge to edge waveguide spacing for routing.min_length
- defaults to 1nm = 10e-3um for routing.start_straight_length
- straight length at the beginning of the route.end_straight_length
- end length at the beginning of the route.snap_to_grid
- Optional snap points to grid when extruding paths (um).decorator
- function when extruding component. For example add_pins.add_pins
- Optional function to add pins.add_bbox
- Optional function to add bounding box.info
- dict with extra settings or useful information.name
- cross_section name.mirror
- if True, reflects the offsets.vias
- list of ComponentAlongPaths(component, spacing, padding, offset).Properties:
aliases
- dict of cross_section aliases.
copy¶
def copy(**kwargs)
Returns a CrossSection copy.
add_bbox_layers¶
def add_bbox_layers(component,
top: float | None = None,
bottom: float | None = None,
right: float | None = None,
left: float | None = None)
Add bounding box layers to a component.
Arguments:
component
- to add layers.top
- top padding.bottom
- bottom padding.right
- right padding.left
- left padding.
get_xmin_xmax¶
def get_xmin_xmax()
Returns the min and max extent of the cross_section across all sections.
Transition Objects¶
class Transition(CrossSection)
Waveguide information to extrude a path between two CrossSection.
cladding_layers follow path shape, while bbox_layers are rectangular.
Arguments:
cross_section1
- input cross_section.cross_section2
- output cross_section.width_type
- sine or linear. Sets the type of width transition used if any widths are different between the two input CrossSections.sections
- list of Sections(width, offset, layer, ports).layer
- main Section layer. Main section name = ‘_default’.width
- main Section width (um) or function parameterized from 0 to 1. the width at t==0 is the width at the beginning of the Path. the width at t==1 is the width at the end.snap_to_grid
- Optional snap points to grid when extruding paths (um).radius
- main Section bend radius (um).width_wide
- wide waveguides width (um) for low loss routing.auto_widen
- taper to wide waveguides for low loss routing.auto_widen_minimum_length
- minimum straight length for auto_widen.taper_length
- taper_length for auto_widen.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- list of layers to extrude.cladding_offsets
- list of offset from main Section edge.cladding_simplify
- Optional Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed.sections
- list of Sections(width, offset, layer, ports).port_names
- for input and output (‘o1’, ‘o2’).port_types
- for input and output: electrical, optical, vertical_te ...gap
- edge to edge waveguide spacing for routing.min_length
- defaults to 1nm = 10e-3um for routing.start_straight_length
- straight length at the beginning of the route.end_straight_length
- end length at the beginning of the route.snap_to_grid
- Optional snap points to grid when extruding paths (um).decorator
- function when extruding component. For example add_pins.add_pins
- Optional function to add pins.add_bbox
- Optional function to add bounding box.info
- dict with extra settings or useful information.name
- cross_section name.mirror
- if True, reflects the offsets.
xsection¶
def xsection(func: _F) -> _F
Decorator for CrossSection functions
Validates type annotations with pydantic.
.. plot:: :include-source:
import gdsfactory as gf
@gf.cross_section.xsection
def xs_sc(width=0.5, **kwargs):
xs = gf.cross_section.cross_section(width=width, **kwargs)
return xs
p = gf.path.arc(radius=10, angle=45)
c = p.extrude(xs_sc)
c.plot()
cross_section¶
@xsection
def cross_section(width: Callable | float = 0.5,
offset: float | Callable = 0,
layer: LayerSpec | None = "WG",
width_wide: float | None = None,
auto_widen: bool = False,
auto_widen_minimum_length: float = 200.0,
taper_length: float = 10.0,
radius: float | None = 10.0,
sections: tuple[Section, ...] | None = None,
port_names: tuple[str, str] = ("o1", "o2"),
port_types: tuple[str, str] = ("optical", "optical"),
gap: float = 3.0,
min_length: float = 10e-3,
start_straight_length: float = 10e-3,
end_straight_length: float = 10e-3,
snap_to_grid: float | None = None,
bbox_layers: list[LayerSpec] | None = None,
bbox_offsets: list[float] | None = None,
cladding_layers: LayerSpecs | None = None,
cladding_offsets: Floats | None = None,
cladding_simplify: Floats | None = cladding_simplify_optical,
info: dict[str, Any] | None = None,
decorator: Callable | None = None,
add_pins: Callable | None = None,
add_bbox: Callable | None = None,
mirror: bool = False,
name: str | None = None) -> CrossSection
Return CrossSection.
Arguments:
width
- main Section width (um) or function parameterized from 0 to 1. the width at t==0 is the width at the beginning of the Path. the width at t==1 is the width at the end.offset
- main Section center offset (um) or function from 0 to 1. the offset at t==0 is the offset at the beginning of the Path. the offset at t==1 is the offset at the end.layer
- main section layer.width_wide
- wide waveguides width (um) for low loss routing.auto_widen
- taper to wide waveguides for low loss routing.auto_widen_minimum_length
- minimum straight length for auto_widen.taper_length
- taper_length for auto_widen.radius
- bend radius (um).sections
- list of Sections(width, offset, layer, ports).port_names
- for input and output (‘o1’, ‘o2’).port_types
- for input and output: electrical, optical, vertical_te ...gap
- edge to edge waveguide gap for routing.min_length
- defaults to 1nm = 10e-3um for routing.start_straight_length
- straight length at the beginning of the route.end_straight_length
- end length at the beginning of the route.snap_to_grid
- can snap points to grid when extruding the path.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- list of layers to extrude.cladding_offsets
- list of offset from main Section edge.cladding_simplify
- Optional Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed.info
- settings info.decorator
- function to run when converting path to component.add_pins
- optional function to add pins to component.add_bbox
- optional function to add bounding box to component.mirror
- if True, reflects the offsets.name
- cross_section name... plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.cross_section(width=0.5, offset=0, layer=‘WG’) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
slot¶
@xsection
def slot(width: float = 0.5,
layer: LayerSpec = "WG",
slot_width: float = 0.04,
**kwargs) -> CrossSection
Return CrossSection Slot (with an etched region in the center).
Arguments:
width
- main Section width (um) or function parameterized from 0 to 1. the width at t==0 is the width at the beginning of the Path. the width at t==1 is the width at the end.layer
- main section layer.slot_width
- in um.
Arguments:
offset
- main Section center offset (um) or function from 0 to 1. the offset at t==0 is the offset at the beginning of the Path. the offset at t==1 is the offset at the end.width_wide
- wide waveguides width (um) for low loss routing.auto_widen
- taper to wide waveguides for low loss routing.auto_widen_minimum_length
- minimum straight length for auto_widen.taper_length
- taper_length for auto_widen.radius
- bend radius (um).sections
- list of Sections(width, offset, layer, ports).port_names
- for input and output (‘o1’, ‘o2’).port_types
- for input and output: electrical, optical, vertical_te ...min_length
- defaults to 1nm = 10e-3um for routing.start_straight_length
- straight length at the beginning of the route.end_straight_length
- end length at the beginning of the route.snap_to_grid
- can snap points to grid when extruding the path.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- list of layers to extrude.cladding_offsets
- list of offset from main Section edge.cladding_simplify
- Optional Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed.info
- settings info.decorator
- function to run when converting path to component.add_pins
- optional function to add pins to component.add_bbox
- optional function to add bounding box to component... plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.slot(width=0.5, slot_width=0.05, layer=‘WG’) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
rib_with_trenches¶
@xsection
def rib_with_trenches(width: float = 0.5,
width_trench: float = 2.0,
width_slab: float = 7.0,
simplify_slab: float | None = None,
layer: LayerSpec | None = "WG",
layer_trench: LayerSpec = "DEEP_ETCH",
wg_marking_layer: LayerSpec | None = None,
**kwargs) -> CrossSection
Return CrossSection of rib waveguide defined by trenches.
Arguments:
width
- main Section width (um) or function parameterized from 0 to 1. the width at t==0 is the width at the beginning of the Path. the width at t==1 is the width at the end.width_trench
- in um.width_slab
- in um.layer
- ridge layer. None adds only ridge.layer_trench
- layer to etch trenches.wg_marking_layer
- layer to draw over the actual waveguide. This can be useful for booleans, routing, placement ...kwargs
- cross_section settings... code::
| | | | || ||
<-------> | width_trench | <----------------------------------------> width_slab
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.rib_with_trenches(width=0.5) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
l_with_trenches¶
@xsection
def l_with_trenches(width: float = 0.5,
width_trench: float = 2.0,
width_slab: float = 7.0,
layer: LayerSpec | None = "WG",
layer_trench: LayerSpec = "DEEP_ETCH",
mirror: bool = False,
wg_marking_layer: LayerSpec | None = None,
**kwargs) -> CrossSection
Return CrossSection of l waveguide defined by trenches.
Arguments:
width
- main Section width (um) or function parameterized from 0 to 1. the width at t==0 is the width at the beginning of the Path. the width at t==1 is the width at the end.width_slab
- in um.width_trench
- in um.layer
- ridge layer. None adds only ridge.layer_trench
- layer to etch trenches.mirror
- this cross section is not symmetric and you can switch orientation.kwargs
- cross_section settings... code:: x = 0 | |
| | | |________| |
<-------> | width_trench <--------> width | <------------------------> width_slab
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.l_with_trenches(width=0.5) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
pin¶
@xsection
def pin(width: float = 0.5,
layer: LayerSpec = "WG",
layer_slab: LayerSpec = "SLAB90",
layers_via_stack1: LayerSpecs = ("PPP", ),
layers_via_stack2: LayerSpecs = ("NPP", ),
bbox_offsets_via_stack1: tuple[float, ...] = (0, -0.2),
bbox_offsets_via_stack2: tuple[float, ...] = (0, -0.2),
via_stack_width: float = 9.0,
via_stack_gap: float = 0.55,
slab_gap: float = -0.2,
layer_via: LayerSpec | None = None,
via_width: float = 1,
via_offsets: tuple[float, ...] | None = None,
**kwargs) -> CrossSection
Rib PIN doped cross_section.
Arguments:
width
- ridge width.layer
- ridge layer.layer_slab
- slab layer.layers_via_stack1
- P++ layer.layers_via_stack2
- N++ layer.bbox_offsets_via_stack1
- for via left.bbox_offsets_via_stack2
- for via right.via_stack_width
- in um.via_stack_gap
- offset from via_stack to ridge edge.slab_gap
- extra slab gap (negative: via_stack goes beyond slab).layer_via
- for via.via_width
- in um.via_offsets
- in um.kwargs
- other cross_section settings... code::
layer |<----width--->| _______________ via_stack_gap slab_gap | |<----------->| <--> ___ | || | | | | | | | | P++ | undoped silicon | N++ | | |||_______________||| <-----------> via_stack_width <----------------------------------------------------------------------> slab_width
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.pin(width=0.5, via_stack_gap=1, via_stack_width=1) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
pn¶
@xsection
def pn(width: float = 0.5,
layer: LayerSpec = "WG",
layer_slab: LayerSpec = "SLAB90",
gap_low_doping: float = 0.0,
gap_medium_doping: float | None = 0.5,
gap_high_doping: float | None = 1.0,
offset_low_doping: float | None = 0.0,
width_doping: float = 8.0,
width_slab: float = 7.0,
layer_p: LayerSpec | None = "P",
layer_pp: LayerSpec | None = "PP",
layer_ppp: LayerSpec | None = "PPP",
layer_n: LayerSpec | None = "N",
layer_np: LayerSpec | None = "NP",
layer_npp: LayerSpec | None = "NPP",
layer_via: LayerSpec | None = None,
width_via: float = 1.0,
layer_metal: LayerSpec | None = None,
width_metal: float = 1.0,
port_names: tuple[str, str] = ("o1", "o2"),
bbox_layers: list[Layer] | None = None,
bbox_offsets: list[float] | None = None,
cladding_layers: Layers | None = cladding_layers_optical,
cladding_offsets: Floats | None = cladding_offsets_optical,
cladding_simplify: Floats | None = cladding_simplify_optical,
mirror: bool = False,
**kwargs) -> CrossSection
Rib PN doped cross_section.
Arguments:
width
- width of the ridge in um.layer
- ridge layer.layer_slab
- slab layer.gap_low_doping
- from waveguide center to low doping. Only used for PIN.gap_medium_doping
- from waveguide center to medium doping. None removes medium doping.gap_high_doping
- from center to high doping. None removes it.offset_low_doping
- from center to junction center.width_doping
- in um.width_slab
- in um.layer_p
- p doping layer.layer_pp
- p+ doping layer.layer_ppp
- p++ doping layer.layer_n
- n doping layer.layer_np
- n+ doping layer.layer_npp
- n++ doping layer.layer_via
- via layer.width_via
- via width in um.layer_metal
- metal layer.width_metal
- metal width in um.port_names
- input and output port names.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- optional list of cladding layers.cladding_offsets
- optional list of cladding offsets.cladding_simplify
- Optional Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed.mirror
- if True, reflects all doping sections... code::
offset_low_doping <------> | | wg junction center center | | ______|_| | | | | | | | || P | | N | width_p | | width_n | <----------------------------->|<--------------------->| | | N+ | | | width_n | | |<------------->| |<------------->| gap_medium_doping
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.pn(width=0.5, gap_low_doping=0, width_doping=2.) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
pn_with_trenches¶
@xsection
def pn_with_trenches(width: float = 0.5,
layer: LayerSpec | None = None,
layer_trench: LayerSpec = "DEEP_ETCH",
gap_low_doping: float = 0.0,
gap_medium_doping: float | None = 0.5,
gap_high_doping: float | None = 1.0,
offset_low_doping: float | None = 0.0,
width_doping: float = 8.0,
width_slab: float = 7.0,
width_trench: float = 2.0,
layer_p: LayerSpec | None = "P",
layer_pp: LayerSpec | None = "PP",
layer_ppp: LayerSpec | None = "PPP",
layer_n: LayerSpec | None = "N",
layer_np: LayerSpec | None = "NP",
layer_npp: LayerSpec | None = "NPP",
layer_via: LayerSpec | None = None,
width_via: float = 1.0,
layer_metal: LayerSpec | None = None,
width_metal: float = 1.0,
port_names: tuple[str, str] = ("o1", "o2"),
bbox_layers: list[Layer] | None = None,
bbox_offsets: list[float] | None = None,
cladding_layers: Layers | None = cladding_layers_optical,
cladding_offsets: Floats
| None = cladding_offsets_optical,
cladding_simplify: Floats
| None = cladding_simplify_optical,
mirror: bool = False,
wg_marking_layer: LayerSpec | None = None,
**kwargs) -> CrossSection
Rib PN doped cross_section.
Arguments:
width
- width of the ridge in um.layer
- ridge layer. None adds only ridge.layer_trench
- layer to etch trenches.gap_low_doping
- from waveguide center to low doping. Only used for PIN.gap_medium_doping
- from waveguide center to medium doping. None removes medium doping.gap_high_doping
- from center to high doping. None removes it.offset_low_doping
- from center to junction center.width_doping
- in um.width_slab
- in um.width_trench
- in um.layer_p
- p doping layer.layer_pp
- p+ doping layer.layer_ppp
- p++ doping layer.layer_n
- n doping layer.layer_np
- n+ doping layer.layer_npp
- n++ doping layer.layer_via
- via layer.width_via
- via width in um.layer_metal
- metal layer.width_metal
- metal width in um.port_names
- input and output port names.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- optional list of cladding layers.cladding_offsets
- optional list of cladding offsets.cladding_simplify
- Optional Tolerance value for the simplification algorithm. All points that can be removed without changing the resulting. polygon by more than the value listed here will be removed.mirror
- if True, reflects all doping sections.kwargs
- cross_section settings... code::
offset_low_doping <------> | | wg junction center center | | _____ | ______ ________ | | | | | | | || | |________| | P | | N | width_p | width_n | <-------------------------------->|<--------------------->| <-------> | | N+ | width_trench | | width_n | | |<------------->| |<------------->| gap_medium_doping <------------------------------------------------------------> width_slab
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.pn_with_trenches(width=0.5, gap_low_doping=0, width_doping=2.) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
pn_with_trenches_asymmetric¶
@xsection
def pn_with_trenches_asymmetric(width: float = 0.5,
layer: LayerSpec | None = None,
layer_trench: LayerSpec = "DEEP_ETCH",
gap_low_doping: float
| tuple[float, float] = (0.0, 0.0),
gap_medium_doping: float | tuple[float, float]
| None = (0.5, 0.2),
gap_high_doping: float | tuple[float, float]
| None = (1.0, 0.8),
width_doping: float = 8.0,
width_slab: float = 7.0,
width_trench: float = 2.0,
layer_p: LayerSpec | None = "P",
layer_pp: LayerSpec | None = "PP",
layer_ppp: LayerSpec | None = "PPP",
layer_n: LayerSpec | None = "N",
layer_np: LayerSpec | None = "NP",
layer_npp: LayerSpec | None = "NPP",
layer_via: LayerSpec | None = None,
width_via: float = 1.0,
layer_metal: LayerSpec | None = None,
width_metal: float = 1.0,
port_names: tuple[str, str] = ("o1", "o2"),
bbox_layers: list[Layer] | None = None,
bbox_offsets: list[float] | None = None,
cladding_layers: Layers
| None = cladding_layers_optical,
cladding_offsets: Floats
| None = cladding_offsets_optical,
mirror: bool = False,
wg_marking_layer: LayerSpec | None = None,
**kwargs) -> CrossSection
Rib PN doped cross_section with asymmetric dimensions left and right.
Arguments:
width
- width of the ridge in um.layer
- ridge layer. None adds only ridge.layer_trench
- layer to etch trenches.gap_low_doping
- from waveguide center to low doping. Only used for PIN. If a list, it considers the first element is [p_side, n_side]. If a number, it assumes the same for both sides.gap_medium_doping
- from waveguide center to medium doping. None removes medium doping. If a list, it considers the first element is [p_side, n_side]. If a number, it assumes the same for both sides.gap_high_doping
- from center to high doping. None removes it. If a list, it considers the first element is [p_side, n_side]. If a number, it assumes the same for both sides.width_doping
- in um.width_slab
- in um.width_trench
- in um.layer_p
- p doping layer.layer_pp
- p+ doping layer.layer_ppp
- p++ doping layer.layer_n
- n doping layer.layer_np
- n+ doping layer.layer_npp
- n++ doping layer.layer_via
- via layer.width_via
- via width in um.layer_metal
- metal layer.width_metal
- metal width in um.port_names
- input and output port names.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- optional list of cladding layers.cladding_offsets
- optional list of cladding offsets.mirror
- if True, reflects all doping sections.kwargs
- cross_section settings... code::
gap_low_doping[1] <------> | | wg junction center center | | _____ | ______ ________ | | | | | | | || | |________| | P | | N | width_p | width_n | <-------------------------------->|<--------------------->| <-------> | | N+ | width_trench | | width_n | | |<------------->| |<------------->| gap_medium_doping[1] <------------------------------------------------------------> width_slab
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.pn_with_trenches_assymmetric(width=0.5, gap_low_doping=0, width_doping=2.) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
l_wg_doped_with_trenches¶
@xsection
def l_wg_doped_with_trenches(width: float = 0.5,
layer: LayerSpec | None = None,
layer_trench: LayerSpec = "DEEP_ETCH",
gap_low_doping: float = 0.0,
gap_medium_doping: float | None = 0.5,
gap_high_doping: float | None = 1.0,
width_doping: float = 8.0,
width_slab: float = 7.0,
width_trench: float = 2.0,
layer_low: LayerSpec = "P",
layer_mid: LayerSpec = "PP",
layer_high: LayerSpec = "PPP",
layer_via: LayerSpec | None = None,
width_via: float = 1.0,
layer_metal: LayerSpec | None = None,
width_metal: float = 1.0,
port_names: tuple[str, str] = ("o1", "o2"),
bbox_layers: list[Layer] | None = None,
bbox_offsets: list[float] | None = None,
cladding_layers: Layers
| None = cladding_layers_optical,
cladding_offsets: Floats
| None = cladding_offsets_optical,
mirror: bool = False,
wg_marking_layer: LayerSpec | None = None,
**kwargs) -> CrossSection
L waveguide PN doped cross_section.
Arguments:
width
- width of the ridge in um.layer
- ridge layer. None adds only ridge.layer_trench
- layer to etch trenches.gap_low_doping
- from waveguide outer edge to low doping. Only used for PIN.gap_medium_doping
- from waveguide edge to medium doping. None removes medium doping.gap_high_doping
- from edge to high doping. None removes it.width_doping
- in um.width_slab
- in um.width_trench
- in um.layer_low
- low doping layer.layer_mid
- mid doping layer.layer_high
- high doping layer.layer_via
- via layer.width_via
- via width in um.layer_metal
- metal layer.width_metal
- metal width in um.port_names
- input and output port names.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- optional list of cladding layers.cladding_offsets
- optional list of cladding offsets.mirror
- if True, reflects all doping sections.wg_marking_layer
- layer to mark where the actual guiding section is.kwargs
- cross_section settings... code::
gap_low_doping <------> | wg edge |
| | | |_____________________| | | | <------------> width <---------------------> | width_trench | | | | |<----------------->| gap_medium_doping |<--------------------------->| gap_high_doping <-------------------------------------------> width_slab
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.pn_with_trenches(width=0.5, gap_low_doping=0, width_doping=2.) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
strip_heater_metal_undercut¶
@xsection
def strip_heater_metal_undercut(width: float = 0.5,
layer: LayerSpec = "WG",
heater_width: float = 2.5,
trench_width: float = 6.5,
trench_gap: float = 2.0,
layer_heater: LayerSpec = "HEATER",
layer_trench: LayerSpec = "DEEPTRENCH",
**kwargs) -> CrossSection
Returns strip cross_section with top metal and undercut trenches on both.
sides.
dimensions from Dong et al. (2010)
Arguments:
width
- waveguide width.layer
- waveguide layer.heater_width
- of metal heater.trench_width
- in um.trench_gap
- from waveguide edge to trench edge.layer_heater
- heater layer.layer_trench
- tench layer.kwargs
- cross_section settings... code::
|<-------heater_width--------->|
| | | layer_heater | |______________________________|
|<------width------>| ____________________ trench_gap | |<----------->| | | | | undercut | | width | | | | | |<------------>| |___________________| | trench_width | | | | |
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.strip_heater_metal_undercut(width=0.5, heater_width=2, trench_width=4, trench_gap=4) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
strip_heater_metal¶
@xsection
def strip_heater_metal(width: float = 0.5,
layer: LayerSpec = "WG",
heater_width: float = 2.5,
layer_heater: LayerSpec = "HEATER",
**kwargs) -> CrossSection
Returns strip cross_section with top heater metal.
dimensions from Dong et al. (2010)
Arguments:
width
- waveguide width (um).layer
- waveguide layer.heater_width
- of metal heater.layer_heater
- for the metal... plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.strip_heater_metal(width=0.5, heater_width=2) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
strip_heater_doped¶
@xsection
def strip_heater_doped(width: float = 0.5,
layer: LayerSpec = "WG",
heater_width: float = 2.0,
heater_gap: float = 0.8,
layers_heater: LayerSpecs = ("WG", "NPP"),
bbox_offsets_heater: tuple[float, ...] = (0, 0.1),
**kwargs) -> CrossSection
Returns strip cross_section with N++ doped heaters on both sides.
Arguments:
width
- in um.layer
- waveguide spec.heater_width
- in um.heater_gap
- in um.layers_heater
- for doped heater.bbox_offsets_heater
- for each layers_heater.kwargs
- cross_section settings... code::
|<------width------>|
| | | undoped Si | | | |layer_heater| | intrinsic region |<----------->| layer_heater | || |_______| |______________| <------------> heater_gap heater_width
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.strip_heater_doped(width=0.5, heater_width=2, heater_gap=0.5) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
rib_heater_doped¶
@xsection
def rib_heater_doped(width: float = 0.5,
layer: LayerSpec = "WG",
heater_width: float = 2.0,
heater_gap: float = 0.8,
layer_heater: LayerSpec = "NPP",
layer_slab: LayerSpec = "SLAB90",
slab_gap: float = 0.2,
with_top_heater: bool = True,
with_bot_heater: bool = True,
**kwargs) -> CrossSection
Returns rib cross_section with N++ doped heaters on both sides.
dimensions from Jacques et al. (2019)
.. code::
|<------width------>|
____________________ heater_gap slab_gap
| |<----------->| <-->
___ _______________________| |__________________________|___
| | | undoped Si | | |
| |layer_heater| intrinsic region |layer_heater| |
|___|____________|____________________________________________|____________|___|
<---------->
heater_width
<------------------------------------------------------------------------------>
slab_width
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.rib_heater_doped(width=0.5, heater_width=2, heater_gap=0.5, layer_heater='NPP')
p = gf.path.arc(radius=10, angle=45)
c = p.extrude(xs)
c.plot()
rib_heater_doped_via_stack¶
@xsection
def rib_heater_doped_via_stack(width: float = 0.5,
layer: LayerSpec = "WG",
heater_width: float = 1.0,
heater_gap: float = 0.8,
layer_slab: LayerSpec = "SLAB90",
layer_heater: LayerSpec = "NPP",
via_stack_width: float = 2.0,
via_stack_gap: float = 0.8,
layers_via_stack: LayerSpecs = ("NPP", "VIAC"),
bbox_offsets_via_stack: tuple[float,
...] = (0, -0.2),
slab_gap: float = 0.2,
slab_offset: float = 0,
with_top_heater: bool = True,
with_bot_heater: bool = True,
**kwargs) -> CrossSection
Returns rib cross_section with N++ doped heaters on both sides.
dimensions from Jacques et al. (2019)
Arguments:
width
- in um.layer
- for main waveguide section.heater_width
- in um.heater_gap
- in um.layer_slab
- for pedestal.layer_heater
- for doped heater.via_stack_width
- for the contact.via_stack_gap
- in um.layers_via_stack
- for the contact.bbox_offsets_via_stack
- for the contact.slab_gap
- from heater edge.slab_offset
- over the center of the slab.with_top_heater
- adds top/left heater.with_bot_heater
- adds bottom/right heater... code::
|<----width------>| slab_gap __________________ via_stack_gap via_stack width <--> | |<------------>|<---------------> | | heater_gap | | |<---------->| ___ | |____ ____ | | | undoped Si | | | | |layer_heater| intrinsic region |layer_heater | | |||__________________||____| <------------> heater_width <------------------------------------------------------------------------------> slab_width
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.rib_heater_doped_via_stack(width=0.5, heater_width=2, heater_gap=0.5, layer_heater=‘NPP’) p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
pn_ge_detector_si_contacts¶
@xsection
def pn_ge_detector_si_contacts(
width_si: float = 6.0,
layer_si: LayerSpec = "WG",
width_ge: float = 3.0,
layer_ge: LayerSpec = "GE",
gap_low_doping: float = 0.6,
gap_medium_doping: float | None = 0.9,
gap_high_doping: float | None = 1.1,
width_doping: float = 8.0,
layer_p: LayerSpec = "P",
layer_pp: LayerSpec = "PP",
layer_ppp: LayerSpec = "PPP",
layer_n: LayerSpec = "N",
layer_np: LayerSpec = "NP",
layer_npp: LayerSpec = "NPP",
layer_via: LayerSpec | None = None,
width_via: float = 1.0,
layer_metal: LayerSpec | None = None,
port_names: tuple[str, str] = ("o1", "o2"),
bbox_layers: list[Layer] | None = None,
bbox_offsets: list[float] | None = None,
cladding_layers: Layers | None = cladding_layers_optical,
cladding_offsets: Floats | None = cladding_offsets_optical
) -> CrossSection
Linear Ge detector cross section based on a lateral p(i)n junction.
It has silicon contacts (no contact on the Ge). The contacts need to be created in the component generating function (they can’t be created here).
See Chen et al., “High-Responsivity Low-Voltage 28-Gb/s Ge p-i-n Photodetector With Silicon Contacts”, Journal of Lightwave Technology 33(4), 2015.
Notice it is possible to have dopings going beyond the ridge waveguide. This is fine, and it is to account for the presence of the contacts. Such contacts can be subwavelength or not.
Arguments:
width_si
- width of the full etch si in um.layer_si
- si ridge layer.width_ge
- width of the ge in um.layer_ge
- ge layer.gap_low_doping
- from waveguide center to low doping.gap_medium_doping
- from waveguide center to medium doping. None removes medium doping.gap_high_doping
- from center to high doping. None removes it.width_doping
- distance from the waveguide center to the edge of the p (or n) dopings in um.layer_p
- p doping layer.layer_pp
- p+ doping layer.layer_ppp
- p++ doping layer.layer_n
- n doping layer.layer_np
- n+ doping layer.layer_npp
- n++ doping layer.layer_via
- via layer.width_via
- via width in um.layer_metal
- metal layer.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.port_names
- for input and output (‘o1’, ‘o2’).bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets... code::
layer_si |<------width_si---->|
layer_ge |<--width_ge->|
| | |__________| | | | | | | | | P | | | | N | width_p ||_______|__| width_n | <----------------------->| |<------------------------------>| |<->| gap_low_doping | | N+ | | | width_np | | |<------------------------>| |<------->| | gap_medium_doping | |<---------------------------------->| width_doping
.. plot:: :include-source:
import gdsfactory as gf
xs = gf.cross_section.pn() p = gf.path.arc(radius=10, angle=45) c = p.extrude(xs) c.plot()
get_cross_section_factories¶
def get_cross_section_factories(modules,
verbose: bool = False
) -> dict[str, CrossSectionFactory]
Returns cross_section factories from a module or list of modules.
Arguments:
modules
- module or iterable of modules.verbose
- prints in case any errors occur.
gdsfactory.config¶
Gdsfactory loads configuration pydantic.
You can set environment variables.
print_version_plugins¶
def print_version_plugins() -> None
Print gdsfactory plugin versions and paths.
print_version_plugins_raw¶
def print_version_plugins_raw() -> None
Print gdsfactory plugin versions and paths.
print_version_pdks¶
def print_version_pdks() -> None
Print gdsfactory PDK versions and paths.
get_number_of_cores¶
def get_number_of_cores() -> int
Get number of cores/threads available.
On (most) linux we can get it through the scheduling affinity. Otherwise, fall back to the multiprocessing cpu count.
tracing_formatter¶
def tracing_formatter(record: loguru.Record) -> str
Traceback filtering.
Filter out frames coming from Loguru internals.
Settings Objects¶
class Settings(BaseSettings)
GDSFACTORY settings object.
Attributes:
n_threads
- Number of threads to use for multiprocessing.display_type
- Display type for components.last_saved_files
- List of last saved files.max_name_length
- Maximum length of component names.model_config
- Pydantic model configuration.loglevel
- Log level.pdk
- PDK to use. Defaults to generic.difftest_ignore_cell_name_differences
- Ignore cell name differences in difftest.
from_config¶
@classmethod
def from_config(cls) -> Settings
Load settings from YAML config file.
Recursively search for a gfconfig.yml
file in the current working directory.
Paths Objects¶
class Paths()
sparameters_repo¶
repo with some demo sparameters
rich_output¶
def rich_output() -> None
Enables rich output.
write_config¶
def write_config(config: Any, json_out_path: Path) -> None
Write config to a JSON file.
print_config¶
def print_config(key: str | None = None) -> None
Prints a key for the config or all the keys.
call_if_func¶
def call_if_func(f: Any, **kwargs) -> Any
Calls function if it’s a function Useful to create objects from.
functions if it’s an object it just returns the object.
get_git_hash¶
def get_git_hash()
Returns repository git hash.
set_plot_options¶
def set_plot_options(show_ports: bool = True,
show_subports: bool = False,
label_aliases: bool = False,
new_window: bool = False,
blocking: bool = False,
zoom_factor: float = 1.4) -> None
Set plot options for matplotlib.
gdsfactory.plugins¶
gdsfactory.name¶
Define names, clean values for names.
get_name_short¶
@pydantic.validate_call
def get_name_short(name: str, max_name_length=CONF.max_name_length) -> str
Returns a short name.
join_first_letters¶
def join_first_letters(name: str) -> str
Join the first letter of a name separated with underscores.
taper_length -> TL
get_component_name¶
def get_component_name(component_type: str, *args, **kwargs) -> str
Returns concatenated kwargs Key_Value.
dict2name¶
def dict2name(prefix: str = "", **kwargs) -> str
Returns name from a dict.
assert_first_letters_are_different¶
def assert_first_letters_are_different(**kwargs)
Assert that the first letters for each key are different.
Avoids different args that start with the same first letter getting the same hash.
print_first_letters_warning¶
def print_first_letters_warning(**kwargs) -> None
Prints kwargs that have same cell.
clean_name¶
def clean_name(name: str,
remove_dots: bool = False,
allowed_characters: list[str] | None = None) -> str
Return a string with correct characters for a cell name.
By default, the characters [a-zA-Z0-9] are allowed.
Arguments:
name
str - The name to clean.remove_dots
bool, optional - Whether to remove dots from the name. Defaults to False.allowed_characters
list[str], optional - List of additional allowed characters. Defaults to an empty list.
Returns:
str
- The cleaned name.
gdsfactory.watch¶
FileWatcher based on watchdog. Looks for changes in files with .pic.yml extension.
FileWatcher Objects¶
class FileWatcher(FileSystemEventHandler)
Captures *.py or *.pic.yml file change events.
__init__¶
def __init__(logger=None, path: str | None = None) -> None
Initialize the YAML event handler.
update_cell¶
def update_cell(src_path, update: bool = False) -> Callable
Parses a YAML file to a cell function and registers into active pdk.
Arguments:
src_path
- the path to the fileupdate
- if True, will update an existing cell function of the same name without raising an error
Returns:
The cell function parsed from the yaml file.
gdsfactory.klive¶
Stream GDS to Klayout. Requires gdsfactory KLayout integration.
show¶
def show(gds_filename: Path | str,
keep_position: bool = True,
technology: str | None = None,
port: int = 8082,
delete: bool = False) -> None
Show GDS in klayout.
Arguments:
gds_filename
- to show.keep_position
- keep position and active layers.technology
- Name of the KLayout technology to use.port
- klayout server port.delete
- deletes file.
gdsfactory.simulation¶
gdsfactory.constants¶
gdsfactory.functions¶
All functions return a Component so you can easily pipe or compose them.
There are two types of functions:
- decorators: return the original component
- containers: return a new component that contains the old one.
add_port¶
def add_port(component: Component, **kwargs) -> Component
Return Component with a new port.
add_text¶
@cell
def add_text(
component: ComponentSpec,
text: str = "",
text_offset: Float2 = (0, 0),
text_anchor: Anchor = "cc",
text_factory: ComponentSpec = text_rectangular_multi_layer
) -> Component
Return component inside a new component with text geometry.
Arguments:
component
- component spec.text
- text string.text_offset
- relative to component anchor. Defaults to center (cc).text_anchor
- relative to component (ce cw nc ne nw sc se sw center cc).text_factory
- function to add text labels.
add_texts¶
def add_texts(components: list[ComponentSpec],
prefix: str = "",
index0: int = 0,
**kwargs) -> list[Component]
Return a list of Component with text labels.
Arguments:
components
- list of component specs.prefix
- Optional prefix for the labels.index0
- defaults to 0 (0, for first component, 1 for second ...).keyword Args:
text_offset
- relative to component size info anchor. Defaults to center.text_anchor
- relative to component (ce cw nc ne nw sc se sw center cc).text_factory
- function to add text labels.
rotate¶
@cell
def rotate(component: ComponentSpec,
angle: float = 90,
recenter: bool = False) -> Component
Return rotated component inside a new component.
Most times you just need to place a reference and rotate it. This rotate function just encapsulates the rotated reference into a new component.
Arguments:
component
- spec.angle
- to rotate in degrees.recenter
- recenter component after rotating.
mirror¶
@cell
def mirror(
component: ComponentSpec, p1: Float2 = (0, 1), p2: Float2 = (0, 0)
) -> Component
Return new Component with a mirrored reference.
Arguments:
component
- component spec.p1
- first point to define mirror axis.p2
- second point to define mirror axis.
move¶
@cell
def move(component: Component,
origin=(0, 0),
destination=None,
axis: Axis | None = None) -> Component
Return new Component with a moved reference to the original component.
Arguments:
component
- to move.origin
- of component.destination
- Optional x, y.axis
- x or y axis.
transformed¶
@cell
def transformed(ref: ComponentReference)
Returns flattened cell with reference transformations applied.
Arguments:
ref
- the reference to flatten into a new cell.
move_port_to_zero¶
def move_port_to_zero(component: Component, port_name: str = "o1")
Return a container that contains a reference to the original component.
The new component has port_name in (0, 0).
update_info¶
def update_info(component: Component, **kwargs) -> Component
Return Component with updated info.
add_settings_label¶
@validate_call
def add_settings_label(
component: ComponentSpec = straight,
layer_label: LayerSpec = (66, 0),
settings: Strs | None = None,
ignore: Strs | None = ("decorator", )
) -> Component
Add a settings label to a component. Use it as a decorator.
Arguments:
component
- spec.layer_label
- for label.settings
- list of settings to include. if None, adds all changed settings.ignore
- list of settings to ignore.
gdsfactory.generic_tech.klayout.tech.layers¶
gdsfactory.generic_tech.klayout.lvs.drc_malformed.run_drc¶
Run GENERIC TECH DRC-malformed runset.
Usage: run_drc.py (--help| -h) run_drc.py (--path=<file_path>) [--verbose] [--mp=<num_cores>] [--run_dir=<run_dir_path>] [--topcell=<topcell_name>] [--thr=] [--run_mode=<run_mode>] [--offgrid]
Options: --help -h Print this help message. --path=<file_path> The input GDS file path. --topcell=<topcell_name> Topcell name to use. --mp=<num_cores> Run the rule deck in parts in parallel to speed up the run. [default: 1] --run_dir=<run_dir_path> Run directory to save all the results [default: pwd] --thr= The number of threads used in run. --run_mode=<run_mode> Select klayout mode Allowed modes (flat , deep, tiling). [default: deep] --verbose Detailed rule execution log for debugging.
get_rules_with_violations¶
def get_rules_with_violations(results_database)
This function will find all the rules that has violated in a database.
Parameters¶
results_database : string or Path object Path string to the results file
Returns¶
set A set that contains all rules in the database with violations
check_drc_results¶
def check_drc_results(results_db_files: list) -> None
check_drc_results Checks the results db generated from run and report at the end if the DRC run failed or passed. This function will exit with 1 if there are violations.
Parameters¶
results_db_files : list A list of strings that represent paths to results databases of all the DRC runs.
get_top_cell_names¶
def get_top_cell_names(gds_path)
get_top_cell_names get the top cell names from the GDS file.
Parameters¶
gds_path : string Path to the target GDS file.
Returns¶
List of string Names of the top cell in the layout.
get_run_top_cell_name¶
def get_run_top_cell_name(arguments, layout_path)
get_run_top_cell_name Get the top cell name to use for running. If it’s provided by the user, we use the user input. If not, we get it from the GDS file.
Parameters¶
arguments : dict Dictionary that holds the user inputs for the script generated by docopt. layout_path : string Path to the target layout.
Returns¶
string Name of the topcell to use in run.
generate_klayout_switches¶
def generate_klayout_switches(arguments, layout_path)
parse_switches Function that parse all the args from input to prepare switches for DRC run.
Parameters¶
arguments : dict Dictionary that holds the arguments used by user in the run command. This is generated by docopt library. layout_path : string Path to the layout file that we will run DRC on.
Returns¶
dict Dictionary that represent all run switches passed to klayout.
check_klayout_version¶
def check_klayout_version() -> None
check_klayout_version checks klayout version and makes sure it would work with the DRC.
check_layout_path¶
def check_layout_path(layout_path)
check_layout_type checks if the layout provided is GDS or OAS. Otherwise, kill the process. We only support GDS or OAS now.
Parameters¶
layout_path : string string that represent the path of the layout.
Returns¶
string string that represent full absolute layout path.
build_switches_string¶
def build_switches_string(sws: dict)
build_switches_string Build switches string from dictionary.
Parameters¶
sws : dict Dictionary that holds the Antenna switches.
run_check¶
def run_check(drc_file: str, drc_name: str, path: str, run_dir: str,
sws: dict)
run_antenna_check run DRC check based on DRC file provided.
Parameters¶
drc_file : str String that has the file full path to run. path : str String that holds the full path of the layout. run_dir : str String that holds the full path of the run location. sws : dict Dictionary that holds all switches that needs to be passed to the antenna checks.
Returns¶
string string that represent the path to the results output database for this run.
run_single_processor¶
def run_single_processor(arguments: dict, rule_deck_full_path: str,
layout_path: str, switches: dict,
drc_run_dir: str) -> None
run_single_processor run the drc checks as single run.
Parameters¶
arguments : dict Dictionary that holds the arguments passed to the run_drc script. rule_deck_full_path : str String that holds the path of the rule deck files. layout_path : str Path to the target layout. switches : dict Dictionary that holds all the switches that will be passed to klayout run. drc_run_dir : str Path to the run location.
main¶
def main(drc_run_dir: str, now_str: str, arguments: dict) -> None
main function to run the DRC.
Parameters¶
drc_run_dir : str String with absolute path of the full run dir. now_str : str String with the run name for logs. arguments : dict Dictionary that holds the arguments used by user in the run command. This is generated by docopt library.
gdsfactory.generic_tech.klayout.lvs.run_lvs¶
Run GENERIC TECHs LVS.
Usage: run_lvs.py (--help| -h) run_lvs.py (--layout=<layout_path>) (--netlist=<netlist_path>) [--thr=] [--run_dir=<run_dir_path>] [--topcell=<topcell_name>] [--run_mode=<run_mode>] [--verbose] [--lvs_sub=<sub_name>] [--no_net_names] [--spice_comments] [--scale]
Options: --help -h Print this help message. --layout=<layout_path> The input GDS file path. --netlist=<netlist_path> The input netlist file path. --thr= The number of threads used in run. --run_dir=<run_dir_path> Run directory to save all the results [default: pwd] --topcell=<topcell_name> Topcell name to use. --run_mode=<run_mode> Select klayout mode Allowed modes (flat , deep, tiling). [default: deep ] --lvs_sub=<sub_name> Substrate name used in your design. --verbose Detailed rule execution log for debugging. --no_net_names Discard net names in extracted netlist. --spice_comments Enable netlist comments in extracted netlist. --scale Enable scale of 1e6 in extracted netlist.
check_klayout_version¶
def check_klayout_version() -> None
check_klayout_version checks klayout version and makes sure it would work with the LVS.
check_layout_type¶
def check_layout_type(layout_path)
check_layout_type checks if the layout provided is GDS or OAS. Otherwise, kill the process. We only support GDS or OAS now.
Parameters¶
layout_path : string string that represent the path of the layout.
Returns¶
string string that represent full absolute layout path.
get_top_cell_names¶
def get_top_cell_names(gds_path)
get_top_cell_names get the top cell names from the GDS file.
Parameters¶
gds_path : string Path to the target GDS file.
Returns¶
List of string Names of the top cell in the layout.
get_run_top_cell_name¶
def get_run_top_cell_name(arguments, layout_path)
get_run_top_cell_name Get the top cell name to use for running. If it’s provided by the user, we use the user input. If not, we get it from the GDS file.
Parameters¶
arguments : dict Dictionary that holds the user inputs for the script generated by docopt. layout_path : string Path to the target layout.
Returns¶
string Name of the topcell to use in run.
generate_klayout_switches¶
def generate_klayout_switches(arguments, layout_path, netlist_path)
parse_switches Function that parse all the args from input to prepare switches for LVS run.
Parameters¶
arguments : dict Dictionary that holds the arguments used by user in the run command. This is generated by docopt library. layout_path : string Path to the layout file that we will run LVS on. netlist_path : string Path to the netlist file that we will run LVS on.
Returns¶
dict Dictionary that represent all run switches passed to klayout.
build_switches_string¶
def build_switches_string(sws: dict)
build_switches_string Build switches string from dictionary.
Parameters¶
sws : dict Dictionary that holds the Antenna switches.
check_lvs_results¶
def check_lvs_results(results_db_files: list) -> None
check_lvs_results Checks the results db generated from run and report at the end if the LVS run failed or passed.
Parameters¶
results_db_files : list A list of strings that represent paths to results databases of all the LVS runs.
run_check¶
def run_check(lvs_file: str, path: str, run_dir: str, sws: dict)
run_check run LVS check.
Parameters¶
lvs_file : str String that has the file full path to run. path : str String that holds the full path of the layout. run_dir : str String that holds the full path of the run location. sws : dict Dictionary that holds all switches that needs to be passed to the antenna checks.
Returns¶
string string that represent the path to the results output database for this run.
main¶
def main(lvs_run_dir: str, arguments: dict) -> None
main function to run the LVS.
Parameters¶
lvs_run_dir : str String with absolute path of the full run dir. arguments : dict Dictionary that holds the arguments used by user in the run command. This is generated by docopt library.
gdsfactory.generic_tech.klayout.lvs.testing.testcases.unit.heater_devices.layout.straight_heater_metal¶
gdsfactory.generic_tech.klayout.drc.errors¶
enclosing¶
@gf.cell
def enclosing(
enclosing: float = 0.1,
layer1: Layer = (40, 0),
layer2: Layer = (41, 0)
) -> Component
Layer1 must be enclosed by layer2 by value.
checks if layer1 encloses (is bigger than) layer2 by value
not_inside¶
@gf.cell
def not_inside(layer: Layer = (40, 0),
not_inside: Layer = (24, 0)) -> Component
Layer must be inside by layer.
gdsfactory.generic_tech.klayout.drc¶
gdsfactory.generic_tech.klayout.python.kgdsfactory.shortcuts¶
Keybindings inspired by SiEPIC tools.
gdsfactory.generic_tech.klayout.python.kgdsfactory¶
gdsfactory.generic_tech.klayout.python¶
gdsfactory.generic_tech¶
gdsfactory.generic_tech.simulation_settings¶
SimulationSettingsLumericalFdtd Objects¶
class SimulationSettingsLumericalFdtd(BaseModel)
Lumerical FDTD simulation_settings.
Arguments:
background_material
- for the background.port_margin
- on both sides of the port width (um).port_height
- port height (um).port_extension
- port extension (um).mesh_accuracy
- 2 (1: coarse, 2: fine, 3: superfine).zmargin
- for the FDTD region (um).ymargin
- for the FDTD region (um).xmargin
- for the FDTD region (um).wavelength_start
- 1.2 (um).wavelength_stop
- 1.6 (um).wavelength_points
- 500.simulation_time
- (s) related to max path length 3e8/2.410e-121e6 = 1.25mm.simulation_temperature
- in kelvin (default = 300).frequency_dependent_profile
- compute mode profiles for each wavelength.field_profile_samples
- number of wavelengths to compute field profile.
Config Objects¶
class Config()
pydantic basemodel config.
gdsfactory.generic_tech.layer_map¶
GenericLayerMap Objects¶
class GenericLayerMap(LayerMap)
Generic layermap based on book.
Lukas Chrostowski, Michael Hochberg, “Silicon Photonics Design”, Cambridge University Press 2015, page 353 You will need to create a new LayerMap with your specific foundry layers.
gdsfactory.generic_tech.containers¶
Containers are Pcells that contain another Pcell.
gdsfactory.generic_tech.layer_stack¶
LayerStackParameters Objects¶
class LayerStackParameters()
values used by get_layer_stack and get_process.
get_layer_stack¶
def get_layer_stack(
thickness_wg=LayerStackParameters.thickness_wg,
thickness_slab_deep_etch=LayerStackParameters.thickness_slab_deep_etch,
thickness_slab_shallow_etch=LayerStackParameters.
thickness_slab_shallow_etch,
sidewall_angle_wg=LayerStackParameters.sidewall_angle_wg,
thickness_clad=LayerStackParameters.thickness_clad,
thickness_nitride=LayerStackParameters.thickness_nitride,
thickness_ge=LayerStackParameters.thickness_ge,
gap_silicon_to_nitride=LayerStackParameters.gap_silicon_to_nitride,
zmin_heater=LayerStackParameters.zmin_heater,
zmin_metal1=LayerStackParameters.zmin_metal1,
thickness_metal1=LayerStackParameters.thickness_metal1,
zmin_metal2=LayerStackParameters.zmin_metal2,
thickness_metal2=LayerStackParameters.thickness_metal2,
zmin_metal3=LayerStackParameters.zmin_metal3,
thickness_metal3=LayerStackParameters.thickness_metal3,
substrate_thickness=LayerStackParameters.substrate_thickness,
box_thickness=LayerStackParameters.box_thickness,
undercut_thickness=LayerStackParameters.undercut_thickness
) -> LayerStack
Returns generic LayerStack.
based on paper https://
Arguments:
thickness_wg
- waveguide thickness in um.thickness_slab_deep_etch
- for deep etched slab.thickness_shallow_etch
- thickness for the etch in um.sidewall_angle_wg
- waveguide side angle.thickness_clad
- cladding thickness in um.thickness_nitride
- nitride thickness in um.thickness_ge
- germanium thickness.gap_silicon_to_nitride
- distance from silicon to nitride in um.zmin_heater
- TiN heater.zmin_metal1
- metal1.thickness_metal1
- metal1 thickness.zmin_metal2
- metal2.thickness_metal2
- metal2 thickness.zmin_metal3
- metal3.thickness_metal3
- metal3 thickness.substrate_thickness
- substrate thickness in um.box_thickness
- bottom oxide thickness in um.undercut_thickness
- thickness of the silicon undercut.
get_process¶
def get_process()
Returns generic process to generate LayerStack.
Represents processing steps that will result in the GenericLayerStack, starting from the waferstack LayerStack.
based on paper https://
gdsfactory.generic_tech.get_klayout_pyxs¶
write xsection script for KLayout plugin.
https://
get_klayout_pyxs¶
def get_klayout_pyxs(t_box=1.0,
t_slab=90 * nm,
t_si=0.22,
t_ge=0.4,
t_nitride=0.4,
h_etch1=0.07,
h_etch2=0.06,
h_etch3=0.09,
t_clad=0.6,
t_m1=0.5,
t_m2=0.5,
t_m3=2.0,
gap_m1_m2=0.6,
gap_m2_m3=0.3,
t_heater=0.1,
gap_oxide_nitride=0.82,
t_m1_oxide=0.6,
t_m2_oxide=2.0,
t_m3_oxide=0.5,
layer_wg=LAYER.WG,
layer_fc=LAYER.SLAB150,
layer_rib=LAYER.SLAB90,
layer_n=LAYER.N,
layer_np=LAYER.NP,
layer_npp=LAYER.NPP,
layer_p=LAYER.P,
layer_pp=LAYER.PP,
layer_ppp=LAYER.PPP,
layer_PDPP=LAYER.GEP,
layer_nitride=LAYER.WGN,
layer_Ge=LAYER.GE,
layer_GePPp=LAYER.GEP,
layer_GeNPP=LAYER.GEN,
layer_viac=LAYER.VIAC,
layer_viac_slot=LAYER.VIAC,
layer_m1=LAYER.M1,
layer_mh=LAYER.HEATER,
layer_via1=LAYER.VIA1,
layer_m2=LAYER.M2,
layer_via2=LAYER.VIA2,
layer_m3=LAYER.M3,
layer_open=LAYER.PADOPEN) -> str
Returns klayout_pyxs plugin script to show chip cross-section in klayout.
https://
gdsfactory.picmodel¶
gdsfactory.add_termination¶
add_termination¶
@cell
def add_termination(component: Component,
ports: list[Port] | None = None,
terminator: ComponentSpec = terminator_function,
port_name: str | None = None,
port_type: str = "optical",
**kwargs) -> Component
Returns component with terminator on some ports.
Arguments:
component
- to add terminator.ports
- optional list of ports to terminate (defaults to all).terminator
- factory for the terminator.port_name
- for the terminator to connect to the component ports.port_type
- of the ports that you want to terminate.kwargs
- for the ports you want to terminate (orientation, width).
gdsfactory.add_tapers_cross_section¶
add_tapers¶
@cell
def add_tapers(component: Component,
taper: ComponentSpec = taper_cross_section,
select_ports: Callable | None = select_ports_optical,
taper_port_name1: str = "o1",
taper_port_name2: str = "o2",
cross_section2: CrossSectionSpec = strip,
**kwargs) -> Component
Returns new component with taper in all optical ports.
Arguments:
component
- to add tapers.taper
- taper spec.select_ports
- function to select ports.taper_port_name1
- name.taper_port_name2
- name.cross_section2
- end cross_section factory (cross_section).
Arguments:
cross_section1
- start cross_section factory.length
- transition length.npoints
- number of points.linear
- shape of the transition, sine when False.kwargs
- cross_section settings for section2.
gdsfactory.component_reference¶
Component references.
Adapted from PHIDL https://
SizeInfo Objects¶
class SizeInfo()
__init__¶
def __init__(bbox: ndarray) -> None
Initialize this object.
__str__¶
def __str__() -> str
Return a string representation of the object.
ComponentReference Objects¶
class ComponentReference(_GeometryHelper)
Pointer to a Component with x, y, rotation, mirror.
Arguments:
component
- Component The referenced Component.columns
- Number of columns in the array.rows
- Number of rows in the array.spacing
- Distances between adjacent columns and adjacent rows.origin
- array-like[2] of int or float Position where the cell is inserted. rotation : int or float Angle of rotation of the reference (indegrees
). magnification : int or float Magnification factor for the reference. x_reflection : bool If True, the reference is reflected parallel to the x direction before being rotated. name : str (optional) A name for the reference (if provided).
__init__¶
def __init__(component: Component,
origin: Coordinate = (0, 0),
rotation: float = 0,
magnification: float = 1,
x_reflection: bool = False,
visual_label: str = "",
columns: int = 1,
rows: int = 1,
spacing=None,
name: str | None = None,
v1: tuple[float, float] | None = None,
v2: tuple[float, float] | None = None) -> None
Initialize the ComponentReference object.
get_polygon_bbox¶
def get_polygon_bbox(default: float = 0.0,
top: float | None = None,
bottom: float | None = None,
right: float | None = None,
left: float | None = None) -> shapely.Polygon
Returns shapely Polygon with padding.
Arguments:
default
- default padding in um.top
- north padding in um.bottom
- south padding in um.right
- east padding in um.left
- west padding in um.
get_polygons¶
def get_polygons(
by_spec: bool = False,
depth: int | None = None,
include_paths: bool = True,
as_array: bool = True,
as_shapely: bool = False,
as_shapely_merged: bool = False
) -> list[Polygon] | dict[tuple[int, int], list[Polygon]]
Return the list of polygons created by this reference.
Arguments:
by_spec : bool or tuple
If True, the return value is a dictionary with the
polygons of each individual pair (layer, datatype).
If set to a tuple of (layer, datatype), only polygons
with that specification are returned.
depth : integer or None
If not None, defines from how many reference levels to
retrieve polygons. References below this level will result
in a bounding box. If by_spec
is True the key will be the
name of the referenced cell.
include_paths
- If True, polygonal representation of paths are also included in the result.as_array
- when as_array=false, return the Polygon objects instead. polygon objects have more information (especially when by_spec=False) and are faster to retrieve.as_shapely
- returns shapely polygons.as_shapely_merged
- returns a shapely polygonize.Returns out : list of array-like[N][2] or dictionary List containing the coordinates of the vertices of each polygon, or dictionary with the list of polygons (if
by_spec
is True).
Notes:
Instances of FlexPath
and RobustPath
are also included in
the result by computing their polygonal boundary.
get_labels¶
def get_labels(depth=None, set_transform=True)
Return the list of labels created by this reference.
Arguments:
depth : integer or None If not None, defines from how many reference levels to retrieve labels from. set_transform : bool If True, labels will include the transformations from the reference.
Returns:
out : list of Label
List containing the labels in this cell and its references.
get_paths¶
def get_paths(depth=None)
Return the list of paths created by this reference.
Arguments:
depth : integer or None If not None, defines from how many reference levels to retrieve paths from.
Returns:
list of FlexPath
or RobustPath
List containing the paths in this cell and its references.
area¶
def area(by_spec=False)
Calculate total area.
Arguments:
by_spec : bool If True, the return value is a dictionary with the areas of each individual pair (layer, datatype).
Returns:
out : number, dictionary Area of this cell.
__repr__¶
def __repr__() -> str
Return a string representation of the object.
bbox¶
@property
def bbox()
Return the bounding box of the ComponentReference.
it snaps to 3 decimals in um (0.001um = 1nm precision)
__get_validators__¶
@classmethod
def __get_validators__(cls)
Get validators.
validate¶
@classmethod
def validate(cls, v, _info)
Check with pydantic ComponentReference valid type.
__getitem__¶
def __getitem__(key)
Access reference ports.
ports¶
@property
def ports() -> dict[str, Port]
This property allows you to access myref.ports, and receive a copy.
of the ports dict which is correctly rotated and translated.
pprint_ports¶
def pprint_ports() -> None
Pretty print component ports.
move¶
def move(origin: Port | Coordinate | str = (0, 0),
destination: Port | Coordinate | str | None = None,
axis: str | None = None) -> ComponentReference
Move the ComponentReference from origin point to destination.
Both origin and destination can be 1x2 array-like, Port, or a key corresponding to one of the Ports in this device_ref.
Arguments:
origin
- Port, port_name or Coordinate.destination
- Port, port_name or Coordinate.axis
- for the movement.
Returns:
ComponentReference.
rotate¶
def rotate(
angle: float = 45,
center: Coordinate | str | int = (0.0, 0.0)
) -> ComponentReference
Return rotated ComponentReference.
Arguments:
angle
- in degrees.center
- x, y.
mirror_x¶
def mirror_x(port_name: str | None = None,
x0: Coordinate | None = None) -> ComponentReference
Perform horizontal mirror using x0 or port as axis (default, x0=0).
This is the default for mirror along X=x0 axis
mirror_y¶
def mirror_y(port_name: str | None = None,
y0: float | None = None) -> ComponentReference
Perform vertical mirror using y0 as axis (default, y0=0).
mirror¶
def mirror(p1: Coordinate = (0.0, 1.0),
p2: Coordinate = (0.0, 0.0)) -> ComponentReference
Mirrors.
Arguments:
p1
- point 1.p2
- point 2.
connect¶
def connect(port: str | Port,
destination: Port,
overlap: float = 0.0,
preserve_orientation: bool = False) -> ComponentReference
Return ComponentReference where port connects to a destination.
Arguments:
port
- origin (port, or port name) to connect.destination
- destination port.overlap
- how deep does the port go inside.preserve_orientation
- True, does not rotate the reference to align port orientation and reference keep its orientation pre-connection.
Returns:
ComponentReference
- with correct rotation to connect to destination.
get_ports_list¶
def get_ports_list(**kwargs) -> list[Port]
Return a list of ports.
Arguments:
layer
- port GDS layer.prefix
- port name prefix.orientation
- in degrees.width
- port width.layers_excluded
- List of layers to exclude.port_type
- optical, electrical, ...clockwise
- if True, sort ports clockwise, False: counter-clockwise.
get_ports_dict¶
def get_ports_dict(**kwargs) -> dict[str, Port]
Return a dict of ports.
Arguments:
layer
- port GDS layer.prefix
- port name prefix.orientation
- in degrees.width
- port width.layers_excluded
- List of layers to exclude.port_type
- optical, electrical, ...clockwise
- if True, sort ports clockwise, False: counter-clockwise.
ports_layer¶
@property
def ports_layer() -> dict[str, str]
Return a mapping from layer0_layer1_E0: portName.
port_by_orientation_cw¶
def port_by_orientation_cw(key: str, **kwargs)
Return port by indexing them clockwise.
port_by_orientation_ccw¶
def port_by_orientation_ccw(key: str, **kwargs)
Return port by indexing them clockwise.
get_ports_xsize¶
def get_ports_xsize(**kwargs) -> float
Return xdistance from east to west ports.
Arguments:
kwargs
- orientation, port_type, layer.
get_ports_ysize¶
def get_ports_ysize(**kwargs) -> float
Returns ydistance from east to west ports.
gdsfactory.technology.xml_utils¶
gdsfactory.technology.yaml_utils¶
gdsfactory.technology.layer_views¶
A GDS layer is a tuple of two integers.
You can maintain LayerViews in YAML (.yaml) or Klayout XML file (.lyp)
HatchPattern Objects¶
class HatchPattern(BaseModel)
Custom dither pattern. See KLayout documentation for more info.
Attributes:
name
- Name of the pattern.order
- Order of pattern.custom_pattern
- Pattern defining custom shape.
LineStyle Objects¶
class LineStyle(BaseModel)
Custom line style. See KLayout documentation for more info.
Attributes:
name
- Name of the line style.order
- Order of line style.custom_style
- Line style to use.
LayerView Objects¶
class LayerView(BaseModel)
KLayout layer properties.
Docstrings adapted from KLayout documentation:
https://
Attributes:
name
- Layer name.info
- Extra info to include in the LayerView.layer
- GDSII layer.layer_in_name
- Whether to display the name as ‘name layer/datatype’ rather than just the layer.width
- This is the line width of the frame in pixels (or empty for the default which is 1).line_style
- This is the number of the line style used to draw the shape boundaries. An empty string is “solid line”. The values are “Ix” for one of the built-in styles where “I0” is “solid”, “I1” is “dotted” etc.hatch_pattern
- This is the number of the dither pattern used to fill the shapes. The values are “Ix” for one of the built-in pattern where “I0” is “solid” and “I1” is “clear”.fill_color
- Display color of the layer fill.frame_color
- Display color of the layer frame. Accepts Pydantic Color types. See: https://docs .pydantic .dev /usage /types for more info. fill_brightness
- Brightness of the fill.frame_brightness
- Brightness of the frame.animation
- This is a value indicating the animation mode. 0 is “none”, 1 is “scrolling”, 2 is “blinking” and 3 is “inverse blinking”. (Only applies to KLayout layer properties)xfill
- Whether boxes are drawn with a diagonal cross. (Only applies to KLayout layer properties)marked
- Whether the entry is marked (drawn with small crosses). (Only applies to KLayout layer properties)transparent
- Whether the entry is transparent.visible
- Whether the entry is visible.valid
- Whether the entry is valid. Invalid layers are drawn but you can’t select shapes on those layers. (Only applies to KLayout layer properties)group_members
- Add a list of group members to the LayerView.
group_members¶
noqa: UP006
__init__¶
def __init__(gds_layer: int | None = None,
gds_datatype: int | None = None,
color: ColorType | None = None,
brightness: int | None = None,
**data) -> None
Initialize LayerView object.
dict¶
def dict(*,
include: AbstractSetIntStr | MappingIntStrAny | None = None,
exclude: AbstractSetIntStr | MappingIntStrAny | None = None,
by_alias: bool = False,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
simplify: bool = True) -> DictStrAny
Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
Specify “simplify” to consolidate fill and frame color/brightness if they are the same.
Arguments:
mode
- The mode in whichto_python
should run. If mode is ‘json’, the dictionary will only contain JSON serializable types. If mode is ‘python’, the dictionary may contain any Python objects.include
- A list of fields to include in the output.exclude
- A list of fields to exclude from the output.by_alias
- Whether to use the field’s alias in the dictionary key if defined.exclude_unset
- Whether to exclude fields that are unset or None from the output.exclude_defaults
- Whether to exclude fields that are set to their default value from the output.exclude_none
- Whether to exclude fields that have a value ofNone
from the output.simplify
- Whether to consolidate fill and frame color/brightness if they are the same.
Returns:
A dictionary representation of the model.
__str__¶
def __str__() -> str
Returns a formatted view of properties and their values.
__repr__¶
def __repr__() -> str
Returns a formatted view of properties and their values.
to_klayout_xml¶
def to_klayout_xml(custom_hatch_patterns: dict,
custom_line_styles: dict) -> ET.Element
Return an XML representation of the LayerView.
from_xml_element¶
@classmethod
def from_xml_element(cls, element: ET.Element,
layer_pattern: str | re.Pattern) -> LayerView | None
Read properties from .lyp XML and generate LayerViews from them.
Arguments:
element
- XML Element to iterate over.layer_pattern
- Regex pattern to match layers with.
LayerViews Objects¶
class LayerViews(BaseModel)
A container for layer properties for KLayout layer property (.lyp) files.
Attributes:
layer_views
- Dictionary of LayerViews describing how to display gds layers.custom_dither_patterns
- Custom dither patterns.custom_line_styles
- Custom line styles.layer_map
- Specify a layer_map to get the layer tuple based on the name of the LayerView, rather than the ‘layer’ argument.
__init__¶
def __init__(filepath: PathLike | None = None,
layer_map: dict[str, Layer] | BaseModel | None = None,
**data) -> None
Initialize LayerViews object.
Arguments:
filepath
- can be YAML or LYP.layer_map
- Optional layermap.
add_layer_view¶
def add_layer_view(name: str,
layer_view: LayerView | None = None,
**kwargs) -> None
Adds a layer to LayerViews.
Arguments:
name
- Name of the LayerView.layer_view
- LayerView to add.
get_layer_views¶
def get_layer_views(exclude_groups: bool = False) -> dict[str, LayerView]
Return all LayerViews.
Arguments:
exclude_groups
- Whether to exclude LayerViews that contain other LayerViews.
get_layer_view_groups¶
def get_layer_view_groups() -> dict[str, LayerView]
Return the LayerViews that contain other LayerViews.
__str__¶
def __str__() -> str
Prints the number of LayerView objects in the LayerViews object.
get¶
def get(name: str) -> LayerView
Returns Layer from name.
Arguments:
name
- Name of layer.
__getitem__¶
def __getitem__(val: str)
Allows accessing to the layer names like ls[‘gold2’].
Arguments:
val
- Layer name to access within the LayerViews.
Returns:
self.layers[val]
- LayerView in the LayerViews.
get_from_tuple¶
def get_from_tuple(layer_tuple: Layer) -> LayerView
Returns LayerView from layer tuple.
Arguments:
layer_tuple
- Tuple of (gds_layer, gds_datatype).
Returns:
LayerView.
get_layer_tuples¶
def get_layer_tuples() -> set[Layer]
Returns a tuple for each layer.
clear¶
def clear() -> None
Deletes all layers in the LayerViews.
preview_layerset¶
def preview_layerset(size: float = 100.0, spacing: float = 100.0) -> object
Generates a Component with all the layers.
Arguments:
size
- square size in um.spacing
- spacing between each square in um.
to_lyp¶
def to_lyp(filepath: str | pathlib.Path,
overwrite: bool = True) -> pathlib.Path
Write all layer properties to a KLayout .lyp file.
Arguments:
filepath
- to write the .lyp file to (appends .lyp extension if not present).overwrite
- Whether to overwrite an existing file located at the filepath.
from_lyp¶
@staticmethod
def from_lyp(filepath: str | pathlib.Path,
layer_pattern: str | re.Pattern | None = None) -> LayerViews
Write all layer properties to a KLayout .lyp file.
Arguments:
filepath
- to write the .lyp file to (appends .lyp extension if not present).layer_pattern
- Regex pattern to match layers with. Defaults to r’(\d+|*)/(\d+|*)'.
to_yaml¶
def to_yaml(layer_file: str | pathlib.Path,
prefer_named_color: bool = True) -> None
Export layer properties to a YAML file.
Arguments:
layer_file
- Name of the file to write LayerViews to.prefer_named_color
- Write the name of a color instead of its hex representation when possible.
from_yaml¶
@staticmethod
def from_yaml(layer_file: str | pathlib.Path) -> LayerViews
Import layer properties from two yaml files.
Arguments:
layer_file
- Name of the file to read LayerViews, CustomDitherPatterns, and CustomLineStyles from.
gdsfactory.technology.klayout_tech¶
Classes and utils for working with KLayout technology files (.lyp, .lyt).
This module enables conversion between gdsfactory settings and KLayout technology.
KLayoutTechnology Objects¶
class KLayoutTechnology(BaseModel)
A container for working with KLayout technologies (requires KLayout Python package).
Useful to import/export Layer Properties (.lyp) and Technology (.lyt) files.
Properties: name: technology name. layer_map: Maps names to GDS layer numbers. layer_views: Defines all the layer display properties needed for a .lyp file from LayerView objects. technology: KLayout Technology object from the KLayout API. Set name, dbu, etc. connectivity: List of layer names connectivity for netlist tracing.
write_tech¶
def write_tech(tech_dir: PathType,
lyp_filename: str = "layers.lyp",
lyt_filename: str = "tech.lyt",
d25_filename: str | None = None,
mebes_config: dict | None = None) -> None
Write technology files into ‘tech_dir’.
Arguments:
tech_dir
- Where to write the technology files to.lyp_filename
- Name of the layer properties file.lyt_filename
- Name of the layer technology file.d25_filename
- Name of the 2.5D stack file (only works on KLayout >= 0.28). Defaults to self.name.mebes_config
- A dictionary specifying the KLayout mebes reader config.
gdsfactory.technology¶
gdsfactory.technology.processes¶
ProcessStep Objects¶
@dataclass(kw_only=True)
class ProcessStep()
Generic process step.
Lithography Objects¶
@dataclass(kw_only=True)
class Lithography(ProcessStep)
Simulates lithography by generating a logical on-wafer mask from one or many layers to be used in processing operations.
(1) First, a mask is created from the layer arguments:
if layer=None, behaviour should be:
mask opening <----------------> -----> || ||
0 1 2 3 0 1 2 3
if argument_layers is provided to layers_or, for those layers:
layer mask opening <----------------> <---------------------------> -----> || |||| |__________| 0 1 2 3 0 1 2 3 <------------------> layers_or
if argument_layers is provided to layers_and, for those layers:
layer mask opening <----------------> <---------> -----> || | || | |___________| 0 1 2 3 0 1 2 3 <------------------> layers_and
if argument_layers is provided to layers_diff, for those layers:
layer mask opening <----------------> <-------> -----> |______| || | | || 0 1 2 3 0 1 2 3 <------------------> layers_and
if argument_layers is provided to layers_xor, for those layers:
layer mask opening <----------------> <--------> <---------> -----> || || || |__________________| 0 1 2 3 0 1 2 3 <------------------> layers_xor
(2) Convert the logical mask into a wafer mask, opening up parts of the wafer for processing:
if positive_tone:
mask opening wafer mask opened <------> <------>
| | | | -----> | | | | mask_thickness ________________ ||||
else (negative tone):
mask opening wafer mask NOT opened <------> <------>
| | -----> | | mask_thickness ________________ ||__
(3) (Optional) Planarize the resist
Arguments:
layer
- main layer to use as a mask for this lithography steplayers_union
List[Layers] - other layers to use to form the mask (see diagram)layers_diff
List[Layers] - other layers to use to form a mask (see diagram)layers_intersect
List[Layers] - other layers to use to form a mask (see diagram)positive_tone
bool - whether to invert the resulting mask (False) or not (True)resist_thickness
float - resist mask thickness, used in some simulatorsplanarization_height
float - height at which to “clip” the resist above the wafer
Grow Objects¶
@dataclass(kw_only=True)
class Grow(Lithography)
Simulates masking + addition of material + liftoff.
wafer mask opened wafer mask opened <------> <------>
| | -----> | mat | thickness ________________ ||__
Arguments:
material
str - material tag of material to addthickness
float - thickness to add [nm]type
str - of growth/deposition (isotropic, anisotropic, etc.)rate
float - of growth [nm/s]
Etch Objects¶
@dataclass(kw_only=True)
class Etch(Lithography)
Simulates masking + removal of material + strip.
wafer mask opened wafer mask opened <------> <----->
| | | | | mat | -----> mat | etch | mat depth |____________| ||____
Arguments:
material
str - material tag to etch intothickness
float - thickness to remove [nm]type
str - of etch (isotropic, anisotropic, etc.)rate
float - of removal [nm/s]
ImplantPhysical Objects¶
@dataclass(kw_only=True)
class ImplantPhysical(Lithography)
Simulates masking + physical ion implantation + strip.
wafer mask opened wafer mask opened <------> <----->
| | | | | | -----> | ------- <---- range (depends on energy) |______________| |________________|
Arguments:
ion
str - ion tagenergy
float - of the ionsdose
float - in /cm^2tilt
float - ion angle from out-of-plane axis. in degrees. If None, uses simulator defaulttwist
float - ion angle from wafer “x-axis”, in degrees. If None, uses simulator defaultrotation
float - if twist is None, toggle to split the dose 4-ways between 4 cardinal twist angles (simulates substrate rotation during implantation)
ImplantAnalytical Objects¶
@dataclass(kw_only=True)
class ImplantAnalytical(Lithography)
Simulates masking + physical ion implantation + strip.
wafer mask opened wafer mask opened <------> <----->
| | | | | | -----> | ------- <---- range (depends on energy) |______________| |________________|
Arguments:
ion
str - ion tagpeak_conc
float - peak concentrationrange
float - of the ions (center of distribution)straggle
float - of the ions (spread of distribution)
Anneal Objects¶
@dataclass(kw_only=True)
class Anneal(ProcessStep)
Simulates thermal diffusion of impurities and healing of defects.
Arguments:
time (float)
temperature
float - temperatureTODO
long term - heating/cooling time profiles
Planarize Objects¶
@dataclass(kw_only=True)
class Planarize(ProcessStep)
Simulates chip planarization, “clipping” the structure above some height. Does not use masking.
__ | |__ | |__ | | ___ _________________ | | | height -----> | | || | z=0 |_|
Arguments:
depth
float - how much to remove
ArbitraryStep Objects¶
@dataclass(kw_only=True)
class ArbitraryStep(ProcessStep)
Arbitrary process step, used to handle all other cases.
gdsfactory.technology.color_utils¶
gdsfactory.technology.layer_map¶
LayerMap Objects¶
class LayerMap(BaseModel)
You will need to create a new LayerMap with your specific foundry layers.
lyp_to_dataclass¶
def lyp_to_dataclass(lyp_filepath: str | pathlib.Path,
overwrite: bool = True) -> str
Returns python LayerMap script from a klayout layer properties file lyp.
gdsfactory.technology.layer_stack¶
LayerLevel Objects¶
class LayerLevel(BaseModel)
Level for 3D LayerStack.
Arguments:
layer
- (GDSII Layer number, GDSII datatype).thickness
- layer thickness in um.thickness_tolerance
- layer thickness tolerance in um.zmin
- height position where material starts in um.zmin_tolerance
- layer height tolerance in um.material
- material name.sidewall_angle
- in degrees with respect to normal.sidewall_angle_tolerance
- in degrees.width_to_z
- if sidewall_angle, relative z-position (0 --> zmin, 1 --> zmin + thickness).z_to_bias
- parametrizes shrinking/expansion of the design GDS layer when extruding from zmin (0) to zmin + thickness (1). Defaults no buffering [[0, 1], [0, 0]].mesh_order
- lower mesh order (1) will have priority over higher mesh order (2) in the regions where materials overlap.refractive_index
- refractive_index can be int, complex or function that depends on wavelength (um).type
- grow, etch, implant, or background.mode
- octagon, taper, round. https://gdsfactory .github .io /klayout _pyxs /DocGrow .html into
- etch into another layer. https://gdsfactory .github .io /klayout _pyxs /DocGrow .html background_doping_concentration
- uniform base doping level in the material (cm-3)background_doping_ion
- uniform base doping ion in the materialorientation
- of the wafer (Miller indices of the plane)resistivity
- for metals.bias
- in um for the etch. Can be a single number or 2 numbers (bias_x, bias_y)derived_layer
- Optional derived layer, used for layer_type=‘etch’ to define the slab.info
- simulation_info and other types of metadata.
LayerStack Objects¶
class LayerStack(BaseModel)
For simulation and 3D rendering. Captures design intent of the chip layers after fabrication.
Arguments:
layers
- dict of layer_levels.
__init__¶
def __init__(**data: Any) -> None
Add LayerLevels automatically for subclassed LayerStacks.
get_layer_to_thickness¶
def get_layer_to_thickness() -> dict[tuple[int, int], float]
Returns layer tuple to thickness (um).
get_component_with_derived_layers¶
def get_component_with_derived_layers(component, **kwargs)
Returns component with derived layers.
get_component_with_net_layers¶
def get_component_with_net_layers(component,
portnames: list[str],
delimiter: str = "#",
new_layers_init: tuple[int,
int] = (10010, 0),
add_to_layerstack: bool = True)
Returns component with new layers that combine port names and original layers, and modifies the layerstack accordingly.
Uses port’s “layer” attribute to decide which polygons need to be renamed. New layers are named “layername{delimiter}portname”.
Arguments component: to process portnames: list of portnames to process into new layers. delimiter: the new layer created is called “layername{delimiter}portname” new_layers_init: initial layer number for the temporary new layers. add_to_layerstack: True by default, but can be set to False to disable parsing of the layerstack
get_layer_to_zmin¶
def get_layer_to_zmin() -> dict[tuple[int, int], float]
Returns layer tuple to z min position (um).
get_layer_to_material¶
def get_layer_to_material() -> dict[tuple[int, int], str]
Returns layer tuple to material name.
get_layer_to_sidewall_angle¶
def get_layer_to_sidewall_angle() -> dict[tuple[int, int], str]
Returns layer tuple to material name.
get_layer_to_info¶
def get_layer_to_info() -> dict[tuple[int, int], dict]
Returns layer tuple to info dict.
get_layer_to_layername¶
def get_layer_to_layername() -> dict[tuple[int, int], str]
Returns layer tuple to layername.
__getitem__¶
def __getitem__(key) -> LayerLevel
Access layer stack elements.
get_klayout_3d_script¶
def get_klayout_3d_script(layer_views: LayerViews | None = None,
dbu: float | None = 0.001) -> str
Returns script for 2.5D view in KLayout.
You can include this information in your tech.lyt
Arguments:
layer_views
- optional layer_views.dbu
- Optional database unit. Defaults to 1nm.
filtered¶
def filtered(layers) -> LayerStack
Filtered layerstack, given layer specs.
z_offset¶
def z_offset(dz) -> LayerStack
Translates the z-coordinates of the layerstack.
invert_zaxis¶
def invert_zaxis() -> LayerStack
Flips the zmin values about the origin.
gdsfactory.technology.read_from_layers_info¶
read_from_layers_info¶
def read_from_layers_info(filepath: PathType) -> str
Returns a layermap python script from layers.info file
gdsfactory.events¶
Event Objects¶
class Event()
__init__¶
def __init__() -> None
Initialize the object.
__iadd__¶
def __iadd__(handler: Callable)
Add item.
__isub__¶
def __isub__(handler: Callable)
Subtract item.
add_handler¶
def add_handler(handler: Callable) -> None
Adds a handler that will be executed when this event is fired.
Arguments:
handler
- a function which matches the signature fired by this event
clear_handlers¶
def clear_handlers() -> None
Clear all handlers.
fire¶
def fire(*args, **kwargs) -> None
Fires an event, calling all handlers with the passed arguments.
gdsfactory.cli¶
layermap_to_dataclass¶
@app.command()
def layermap_to_dataclass(
filepath: str,
force: bool = typer.Option(False, "--force", "-f", help="Force deletion")
) -> None
Converts KLayout LYP to a dataclass.
write_cells¶
@app.command()
def write_cells(gdspath: str, dirpath: str = None) -> None
Write each all level cells into separate GDS files.
merge_gds¶
@app.command()
def merge_gds(dirpath: str = None, gdspath: str = None) -> None
Merges GDS cells from a directory into a single GDS.
web¶
@app.command()
def web(pdk: str = "generic",
host: str = "localhost",
port: int = 8765) -> None
Opens web viewer.
watch¶
@app.command()
def watch(path: str = str(pathlib.Path.cwd()), pdk: str = None) -> None
Filewatch a folder for changes in *.py or *.pic.yml files.
show¶
@app.command()
def show(filename: str) -> None
Show a GDS file using klive.
gds_diff¶
@app.command()
def gds_diff(gdspath1: str, gdspath2: str, xor: bool = False) -> None
Show boolean difference between two GDS files.
install_klayout_genericpdk¶
@app.command()
def install_klayout_genericpdk() -> None
Install Klayout generic PDK.
install_git_diff¶
@app.command()
def install_git_diff() -> None
Install git diff.
print_plugins¶
@app.command()
def print_plugins() -> None
Show installed plugin versions.
print_pdks¶
@app.command()
def print_pdks() -> None
Show installed PDK versions.
from_updk_command¶
@app.command(name="from_updk")
def from_updk_command(filepath: str, filepath_out: str = None) -> None
Writes a PDK in python from uPDK YAML spec.
text_from_pdf_command¶
@app.command(name="text_from_pdf")
def text_from_pdf_command(filepath: str) -> None
Converts a PDF to text.
gdsfactory.asserts¶
version¶
def version(requirement: str,
current: str = __version__,
package_name="gdsfactory") -> None
Raises error if current version does not match requirement.
gdsfactory.quickplotter¶
Plot gdsfactory Components in matplotlib.
based on phidl.quickplotter.
set_quickplot_options¶
def set_quickplot_options(show_ports: bool | None = None,
show_subports: bool | None = None,
label_aliases: bool | None = None,
new_window: bool | None = None,
blocking: bool | None = None,
zoom_factor: float | None = None,
interactive_zoom: bool | None = None,
fontsize: int | None = None) -> None
Sets plotting options for quickplot().
Arguments:
show_ports
- Sets whether ports are drawn.show_subports
- Sets whether subports (ports that belong to references) are drawn.label_aliases
- Sets whether aliases are labeled with a text name.new_window
- If True, each call to quickplot() will generate a separate window.blocking
- If True, calling quickplot() will pause execution of (“block”) the remainder of the python code until the quickplot() window is closed. If False, the window will be opened and code will continue to run.zoom_factor
- Sets the scaling factor when zooming the quickplot window with the mousewheel/trackpad.interactive_zoom
- Enables using mousewheel/trackpad to zoom.fontsize
- for labels.
quickplot¶
def quickplot(items, **kwargs)
Takes a list of devices/references/polygons or single one of those, and plots them. Use set_quickplot_options()
to modify the viewer behavior (e.g. displaying ports, creating new windows, etc).
Arguments:
items
- object or list of objects to plot.Kwargs:
show_ports
- Sets whether ports are drawn.show_subports
- Sets whether subports (ports that belong to references) are drawn.label_aliases
- Sets whether aliases are labeled with a text name.new_window
- If True, each call to quickplot() will generate a separate window.blocking
- If True, calling quickplot() will pause execution of (“block”) the remainder of the python code until the quickplot() window is closed. If False, the window will be opened and code will continue to run.zoom_factor
- Sets the scaling factor when zooming the quickplot window with the mousewheel/trackpad.interactive_zoom
- Enables using mousewheel/trackpad to zoom.fontsize
- for labels.Examples¶
import gdsfactory as gf R = gf.components.rectangle() R.plot()
E = gf.components.ellipse() E.plot()
ViewerWindow Objects¶
class ViewerWindow(QMainWindow)
__init__¶
def __init__() -> None
Initialize the object.
Viewer Objects¶
class Viewer(QGraphicsView)
__init__¶
def __init__(gridsize_label, position_label, help_label) -> None
Initialize the object.
quickplot2¶
def quickplot2(item_list, *args, **kwargs)
QT plot.
gdsfactory.add_pins¶
Add_pin adds a Pin to a port, add_pins adds Pins to all ports.
- pins
- outline
Some functions modify a component without changing its name. Make sure these functions are inside a new Component or called as a decorator They without modifying the cell name
add_bbox¶
def add_bbox(component: Component,
bbox_layer: LayerSpec = "DEVREC") -> Component
Add bbox on outline.
Arguments:
component
- component to add bbox.bbox_layer
- bbox layer.
add_bbox_siepic¶
def add_bbox_siepic(
component: Component,
bbox_layer: LayerSpec = "DEVREC",
remove_layers: LayerSpecs = ("PORT", "PORTE")
) -> Component
Add bounding box device recognition layer.
Arguments:
component
- to add bbox.bbox_layer
- bounding box.remove_layers
- remove other layers.
get_pin_triangle_polygon_tip¶
def get_pin_triangle_polygon_tip(
port: Port) -> tuple[list[float], tuple[float, float]]
Returns triangle polygon and tip position.
add_pin_triangle¶
def add_pin_triangle(component: Component,
port: Port,
layer: LayerSpec = "PORT",
layer_label: LayerSpec = "TEXT") -> None
Add triangle pin with a right angle, pointing out of the port.
Arguments:
component
- to add pin.port
- Port.layer
- for the pin marker.layer_label
- for the label.
add_pin_rectangle_inside¶
def add_pin_rectangle_inside(component: Component,
port: Port,
pin_length: float = 0.1,
layer: LayerSpec = "PORT",
layer_label: LayerSpec = "TEXT") -> None
Add square pin towards the inside of the port.
Arguments:
component
- to add pins.port
- Port.pin_length
- length of the pin marker for the port.layer
- for the pin marker.layer_label
- for the label... code::
| | | | | | || | || | | | | __ | |_______________|
add_pin_rectangle_double¶
def add_pin_rectangle_double(component: Component,
port: Port,
pin_length: float = 0.1,
layer: LayerSpec = "PORT",
layer_label: LayerSpec = "TEXT") -> None
Add two square pins: one inside with label, one outside.
Arguments:
component
- to add pins.port
- Port.pin_length
- length of the pin marker for the port.layer
- for the pin marker.layer_label
- for the label... code::
| | | | | | ||| | ||| | | | | __ | |_______________| __
add_pin_rectangle¶
def add_pin_rectangle(component: Component,
port: Port,
pin_length: float = 0.1,
layer: LayerSpec = "PORT",
layer_label: LayerSpec = "TEXT",
port_margin: float = 0.0) -> None
Add half out pin to a component.
Arguments:
component
- to add pin.port
- Port.pin_length
- length of the pin marker for the port.layer
- for the pin marker.layer_label
- for the label.port_margin
- margin to port edge... code::
| | | | | | ||| | ||| | | | | __ | |_______________| __
add_pin_path¶
def add_pin_path(component: Component,
port: Port,
pin_length: float = 2 * nm,
layer: LayerSpec = "PORT",
layer_label: LayerSpec | None = None) -> None
Add half out path pin to a component.
This port type is compatible with SiEPIC pdk.
Arguments:
component
- to add pin.port
- Port.pin_length
- length of the pin marker for the port.layer
- for the pin marker.layer_label
- optional layer label. Defaults to layer... code::
| | | | | | ||| | ||| | | | | __ | |_______________| __
add_outline¶
def add_outline(component: Component,
reference: ComponentReference | None = None,
layer: LayerSpec = "DEVREC",
**kwargs) -> None
Adds devices outline bounding box in layer.
Arguments:
component
- where to add the markers.reference
- to read outline from.layer
- to add padding.
Arguments:
default
- default padding.top
- North padding.bottom
- padding.right
- padding.left
- padding.
add_pins_siepic¶
def add_pins_siepic(component: Component,
function: Callable = add_pin_path,
port_type: str = "optical",
layer_pin: LayerSpec = "PORT",
pin_length: float = 10 * nm) -> Component
Add pins.
Enables you to run SiEPIC verification tools: To Run verification install SiEPIC-tools KLayout package then hit V shortcut in KLayout to run verification
- ensure no disconnected pins
- netlist extraction
Arguments:
component
- to add pins.function
- to add pin.port_type
- optical, electrical, ...layer_pin
- pin layer.pin_length
- length of the pin marker for the port.
add_pins¶
def add_pins(component: Component,
reference: ComponentReference | None = None,
function: Callable = add_pin_rectangle_inside,
select_ports: Callable | None = None,
**kwargs) -> Component
Add Pin port markers.
Be careful with this function as it modifies the component.
Arguments:
component
- to add ports to.reference
- to add pins.function
- to add each pin.select_ports
- function to select_ports.
Arguments:
kwargs
- add pins function settings.pin_length
- length of the pin marker for the port.layer
- layer for the pin marker.layer_label
- add label for the pin marker.
add_settings_label¶
def add_settings_label(component: Component,
reference: ComponentReference,
layer_label: LayerSpec = "LABEL_SETTINGS") -> None
Add settings in label.
Arguments:
component
- to add pins.reference
- ComponentReference.layer_label
- layer spec.
add_instance_label¶
def add_instance_label(component: Component,
reference: ComponentReference,
instance_name: str | None = None,
layer: LayerSpec = "LABEL_INSTANCE") -> None
Adds label to a reference in a component.
add_pins_and_outline¶
def add_pins_and_outline(
component: Component,
reference: ComponentReference | None = None,
add_outline_function: Callable | None = add_outline,
add_pins_function: Callable | None = add_pins,
add_settings_function: Callable | None = add_settings_label,
add_instance_label_function: Callable | None = add_settings_label
) -> None
Add markers.
- outline
- pins for the ports
- label for the name
- label for the settings
Arguments:
component
- where to add the markers.reference
- to add pins. add_outline_function.add_pins_function
- to add pins to ports.add_settings_function
- to add outline around the component.add_instance_label_function
- labels each instance.
gdsfactory.components.grating_coupler_elliptical_trenches¶
grating_coupler_elliptical_trenches¶
@gf.cell
def grating_coupler_elliptical_trenches(
polarization: str = "te",
taper_length: float = 16.6,
taper_angle: float = 30.0,
trenches_extra_angle: float = 9.0,
wavelength: float = 1.53,
fiber_angle: float = 15.0,
grating_line_width: float = 0.343,
neff: float = 2.638,
ncladding: float = 1.443,
layer_trench: LayerSpec | None = "SHALLOW_ETCH",
p_start: int = 26,
n_periods: int = 30,
end_straight_length: float = 0.2,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns Grating coupler with defined trenches.
Some foundries define the grating coupler by a shallow etch step (trenches) Others define the slab that they keep (see grating_coupler_elliptical)
Arguments:
polarization
- ‘te’ or ‘tm’.taper_length
- taper length from straight I/O.taper_angle
- grating flare angle.wavelength
- grating transmission central wavelength.fiber_angle
- fibre polish angle in degrees.grating_line_width
- of the 220 ridge.neff
- tooth effective index.ncladding
- cladding index.layer_trench
- for the trench.p_start
- first tooth.n_periods
- number of grating teeth.end_straight_length
- at the end of straight.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
fiber
/ / / / / / / / |-||-||-|__ WG o1 ______________|
gdsfactory.components.cutback_2x2¶
bendu_double¶
@gf.cell
def bendu_double(component: ComponentSpec,
cross_section: CrossSectionSpec = "strip",
bend180: ComponentSpec = bend_circular180,
port1: str = "o1",
port2: str = "o2",
**kwargs) -> ComponentSpec
Returns double bend.
Arguments:
component
- for cutback.cross_section
- specification (CrossSection, string or dict).bend180
- ubend.port1
- name of first optical port.port2
- name of second optical port.kwargs
- cross_section settings.
straight_double¶
@gf.cell
def straight_double(component: ComponentSpec,
cross_section: CrossSectionSpec = "strip",
port1: str = "o1",
port2: str = "o2",
straight_length: float | None = None,
**kwargs) -> ComponentSpec
Returns double straight.
Arguments:
component
- for cutback.cross_section
- specification (CrossSection, string or dict).port1
- name of first optical port.port2
- name of second optical port.straight_length
- length of straight.kwargs
- cross_section settings.
cutback_2x2¶
@gf.cell
def cutback_2x2(component: ComponentSpec = mmi2x2,
cols: int = 4,
rows: int = 5,
port1: str = "o1",
port2: str = "o2",
port3: str = "o3",
port4: str = "o4",
bend180: ComponentSpec = bend_circular180,
mirror: bool = False,
straight_length: float | None = None,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns a daisy chain of splitters for measuring their loss.
Arguments:
component
- for cutback.cols
- number of columns.rows
- number of rows.port1
- name of first optical port.port2
- name of second optical port.bend180
- ubend.straight
- waveguide spec to connect both sides.mirror
- Flips component. Useful when ‘o2’ is the port that you want to route to.straight_length
- length of the straight section between cutbacks.cross_section
- specification (CrossSection, string or dict).kwargs
- cross_section settings.
gdsfactory.components.bend_s¶
bend_s¶
@cell
def bend_s(size: Float2 = (11.0, 2.0),
npoints: int = 99,
cross_section: CrossSectionSpec = "strip",
check_min_radius: bool = False,
**kwargs) -> Component
Return S bend with bezier curve.
stores min_bend_radius property in self.info[‘min_bend_radius’] min_bend_radius depends on height and length
Arguments:
size
- in x and y direction.npoints
- number of points.cross_section
- spec.check_min_radius
- raise ValueError if radius below min_bend_radius.kwargs
- cross_section settings.
get_min_sbend_size¶
def get_min_sbend_size(size: Float2 = (None, 10.0),
cross_section: CrossSectionSpec = "strip",
num_points: int = 100,
**kwargs)
Returns the minimum sbend size to comply with bend radius requirements.
Arguments:
size
- in x and y direction. One of them is None, which is the size we need to figure out.cross_section
- spec.num_points
- number of points to iterate over between max_size and 0.1 * max_sizekwargs
- cross_section settings.
gdsfactory.components.text_rectangular_font¶
pixel_array¶
@cell
def pixel_array(pixels: str = character_a,
pixel_size: float = 10.0,
layer: LayerSpec = "M1") -> Component
Returns a pixel component from a string representing the pixels.
Arguments:
pixels
- string representing the pixelspixel_size
- width/height for each pixellayer
- layer for each pixel
rectangular_font¶
@cache
def rectangular_font() -> dict[str, str]
Returns a rectangular font dict The keys of the dictionary are the.
characters The values are the pixel representation of the character.
gdsfactory.components.coupler_bent¶
coupler_bent¶
@gf.cell
def coupler_bent(gap: float = 0.200,
radius: float = 26,
length: float = 8.6,
width1: float = 0.400,
width2: float = 0.400,
length_straight: float = 10) -> gf.Component
Returns Broadband SOI curved / straight directional coupler. based on: Chen et al. (2017)
Arguments:
gap
- gap.radius
- radius coupling.length
- coupler_length.width1
- width1.width2
- width2.length_straight
- input and output straight length.
gdsfactory.components.snspd¶
snspd¶
@cell
def snspd(
wire_width: float = 0.2,
wire_pitch: float = 0.6,
size: Float2 = (10, 8),
num_squares: int | None = None,
turn_ratio: float = 4,
terminals_same_side: bool = False,
layer: LayerSpec = (1, 0)) -> Component
Creates an optimally-rounded SNSPD.
Arguments:
width
- Width of the wire.pitch
- Distance between two adjacent wires. Must be greater thanwidth
.size
- None or array-like[2] of int or float (width, height) of the rectangle formed by the outer boundary of the SNSPD. Must be none ifnum_squares
is specified.num_squares
- int or None Total number of squares inside the SNSPD length. Must be none ifsize
is specified.turn_ratio
- int or float Specifies how much of the SNSPD width is dedicated to the 180 degree turn. Aturn_ratio
of 10 will result in 20% of the width being comprised of the turn. terminals_same_side : bool If True, both ports will be located on the same side of the SNSPD.layer
- layer spec to put polygon geometry on.
gdsfactory.components.resistance_sheet¶
resistance_sheet¶
@cell
def resistance_sheet(width: float = 10,
layers: LayerSpecs = ("SLAB90", "NPP"),
layer_offsets: Floats = (0, 0.2),
pad: ComponentSpec = pad_via_stack_slab_npp,
pad_pitch: float = 100.0,
ohms_per_square: float | None = None,
port_orientation1: int = 180,
port_orientation2: int = 0) -> Component
Returns Sheet resistance.
keeps connectivity for pads and first layer in layers
Arguments:
width
- in um.layers
- for the middle part.layer_offsets
- from edge, positive: over, negative: inclusion.pad
- function to create a pad.pad_pitch
- in um.ohms_per_square
- optional sheet resistance to compute info.resistance.port_orientation1
- in degrees.port_orientation2
- in degrees.
gdsfactory.components.taper¶
taper¶
@cell
def taper(length: float = 10.0,
width1: float = 0.5,
width2: float | None = None,
port: Port | None = None,
with_bbox: bool = True,
with_two_ports: bool = True,
cross_section: CrossSectionSpec = "strip",
port_order_name: tuple | None = ("o1", "o2"),
port_order_types: tuple | None = ("optical", "optical"),
**kwargs) -> Component
Linear taper.
Deprecated, use gf.components.taper_cross_section instead
Arguments:
length
- taper length.width1
- width of the west port.width2
- width of the east port.port
- can taper from a port instead of defining width1.with_bbox
- box in bbox_layers and bbox_offsets to avoid DRC sharp edges.with_two_ports
- includes a second port. False for terminator and edge coupler fiber interface.cross_section
- specification (CrossSection, string, CrossSectionFactory dict).port_order_name(tuple)
- Ordered tuple of port names. First port is default taper port, second name only if with_two_ports flags used.port_order_types(tuple)
- Ordered tuple of port types. First port is default taper port, second name only if with_two_ports flags used.kwargs
- cross_section settings.
taper_strip_to_ridge¶
@gf.cell
def taper_strip_to_ridge(length: float = 10.0,
width1: float = 0.5,
width2: float = 0.5,
w_slab1: float = 0.15,
w_slab2: float = 6.0,
layer_wg: LayerSpec = "WG",
layer_slab: LayerSpec = "SLAB90",
cross_section: CrossSectionSpec = "strip",
bbox_layers: list[LayerSpec] | None = None,
bbox_offsets: list[float] | None = None) -> Component
Linear taper from strip to rib.
Deprecated, use gf.components.taper_cross_section instead.
Arguments:
length
- taper length (um).width1
- in um.width2
- in um.w_slab1
- slab width in um.w_slab2
- slab width in um.layer_wg
- for input waveguide.layer_slab
- for output waveguide with slab.cross_section
- for input waveguide... code::
/ | /|_________ / | width1 |w_slab1 | w_slab2 width2 _|________ \ | __________________________
taper_strip_to_ridge_trenches¶
@gf.cell
def taper_strip_to_ridge_trenches(length: float = 10.0,
width: float = 0.5,
slab_offset: float = 3.0,
trench_width: float = 2.0,
trench_layer: LayerSpec = "DEEP_ETCH",
layer_wg: LayerSpec = "WG",
trench_offset: float = 0.1) -> gf.Component
Defines taper using trenches to define the etch.
Arguments:
length
- in um.width
- in um.slab_offset
- in um.trench_width
- in um.trench_layer
- trench layer.layer_wg
- waveguide layer.trench_offset
- after waveguide in um.
gdsfactory.components.extension¶
move_polar_rad_copy¶
def move_polar_rad_copy(pos: Coordinate, angle: float,
length: float) -> ndarray
Returns the points of a position (pos) with angle, shifted by length.
Arguments:
pos
- position.angle
- in radians.length
- extension length in um.
extend_port¶
@cell
def extend_port(port: Port,
length: float,
layer: Layer | None = None) -> Component
Returns a straight extension component out of a port.
Arguments:
port
- port to extend.length
- extension length in um.layer
- for the straight section.
extend_ports¶
@gf.cell
def extend_ports(component: ComponentSpec = mmi1x2,
port_names: tuple[str, ...] | None = None,
length: float = 5.0,
extension: ComponentSpec | None = None,
port1: str | None = None,
port2: str | None = None,
port_type: str = "optical",
centered: bool = False,
cross_section: CrossSectionSpec | None = None,
extension_port_names: list[str] | None = None,
**kwargs) -> Component
Returns a new component with some ports extended.
You can define extension Spec defaults to port cross_section of each port to extend.
Arguments:
component
- component to extend ports.port_names
- list of ports names to extend, if None it extends all ports.length
- extension length.extension
- function to extend ports (defaults to a straight).port1
- extension input port name.port2
- extension output port name.port_type
- type of the ports to extend.centered
- if True centers rectangle at (0, 0).cross_section
- extension cross_section, defaults to port cross_section if port has no cross_section it creates one using width and layer.extension_port_names
- extension port names add to the new component.
Arguments:
layer
- port GDS layer.prefix
- port name prefix.orientation
- in degrees.width
- port width.layers_excluded
- List of layers to exclude.port_type
- optical, electrical, ....clockwise
- if True, sort ports clockwise, False: counter-clockwise.
gdsfactory.components.coh_rx_dual_pol¶
coh_rx_dual_pol¶
@cell
def coh_rx_dual_pol(
bend: ComponentSpec = bend_euler,
cross_section: CrossSectionSpec = "strip",
lo_splitter: ComponentSpec = "mmi1x2",
signal_splitter: ComponentSpec | None = None,
spol_coh_rx: ComponentSpec = coh_rx_single_pol,
single_pol_rx_spacing: float = 50.0,
splitter_coh_rx_spacing: float = 40.0,
lo_input_coupler: ComponentSpec | None = None,
signal_input_coupler: ComponentSpec | None = None) -> Component
Dual polarization coherent receiver.
Arguments:
bend
- 90 degrees bend library.cross_section
- for routing (splitter to mzms and mzms to combiners).lo_splitter
- splitter function for the LO input.signal_splitter
- splitter function for the signal input.spol_coh_rx
- function generating a coherent rx for a single polarization.single_pol_rx_spacing
- vertical spacing between each single polarization coherent receiver.splitter_coh_rx_spacing
- horizontal spacing between the signal splitter and the single pol coh rxs.lo_input_coupler
- Optional coupler to add before the LO splitter.signal_input_coupler
- Optional coupler to add before the signal splitter.
gdsfactory.components.bezier¶
bezier_curve¶
def bezier_curve(t: ndarray, control_points: Coordinates) -> ndarray
Returns bezier coordinates.
Arguments:
t
- 1D array of points varying between 0 and 1. control_points:
bezier¶
@gf.cell
def bezier(control_points: Coordinates = ((0.0, 0.0), (5.0, 0.0), (5.0, 2.0),
(10.0, 2.0)),
npoints: int = 201,
with_manhattan_facing_angles: bool = True,
start_angle: int | None = None,
end_angle: int | None = None,
cross_section: CrossSectionSpec = "strip",
with_bbox: bool = True,
**kwargs) -> Component
Returns Bezier bend.
Arguments:
control_points
- list of points.npoints
- number of points varying between 0 and 1.with_manhattan_facing_angles
- bool.start_angle
- optional start angle in deg.end_angle
- optional end angle in deg.cross_section
- spec.with_bbox
- box in bbox_layers and bbox_offsets to avoid DRC sharp edges.
gdsfactory.components.delay_snake2¶
delay_snake2¶
@gf.cell
def delay_snake2(length: float = 1600.0,
length0: float = 0.0,
length2: float = 0.0,
n: int = 2,
bend180: ComponentSpec = "bend_euler180",
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns Snake with a starting straight and 180 bends.
Input faces west output faces east.
Arguments:
length
- total length.length0
- start length.length2
- end length.n
- number of loops.bend180
- ubend spec.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
| length0 | length1 |
---------| | bend180.length |-------------------| | |------------------->------- | length2 | delta_length | |
gdsfactory.components.grating_coupler_functions¶
get_grating_period_curved¶
def get_grating_period_curved(fiber_angle: float = 15.0,
wavelength: float = 1.55,
n_slab: float = (neff_ridge + neff_shallow) / 2,
n_clad: float = 1.0) -> tuple[float, float]
The following function calculates the confocal grating periods n_slab is.
the “average slab index” of the grating. For 220nm silicon it is 2.8, for 150nm it is 2.5. The average is approximately 2.65. n_clad is the cladding index in which the fiber is located, not the index of the layer above the straight. If the fiber is in air, then it is 1.0. If you use an index matching fluid or glue, then it should be 1.45.
Arguments:
fiber_angle
- in degrees.wavelength
- um.n_slab
- slab refractive index.n_clad
- cladding refractive index.
get_grating_period¶
def get_grating_period(fiber_angle: float = 13.45,
wavelength: float = 1.55,
neff_high: float = neff_ridge,
neff_low: float = neff_shallow,
n_clad: float = 1.45) -> float
Return grating coupler period.
based on lumerical slides.
gdsfactory.components.cutback_loss¶
cutback_loss¶
def cutback_loss(cutback_function: ComponentFactory = cutback_component,
loss: tuple[float, ...] = (1 + 1 * i for i in range(3)),
loss_dB: float = 10e-3,
cols: int | None = 4,
rows: int | None = None,
**kwargs) -> list[gf.Component]
Returns a list of component cutbacks.
Arguments:
cutback_function
- cutback function.loss
- list of target loss in dB.loss_dB
- loss per component.cols
- number of columns.rows
- number of rows.kwargs
- additional cutback arguments.
cutback_loss_spirals¶
def cutback_loss_spirals(spiral: ComponentFactory = spiral_inner_io,
loss: tuple[float,
...] = (4 + 3 * i for i in range(3)),
cross_section: CrossSectionSpec = "strip",
loss_dB_per_m: float = 300,
**kwargs) -> list[gf.Component]
Returns a list of spirals.
Arguments:
spiral
- spiral factory.loss
- list of target loss in dB.cross_section
- strip or rib.loss_dB_per_m
- loss per meter.**kwargs
- additional spiral arguments.
gdsfactory.components.coupler_ring¶
coupler_ring¶
@gf.cell
def coupler_ring(gap: float = 0.2,
radius: float = 5.0,
length_x: float = 4.0,
coupler90: ComponentSpec = coupler90,
bend: ComponentSpec = bend_euler,
coupler_straight: ComponentSpec = coupler_straight,
cross_section: CrossSectionSpec = "strip",
bend_cross_section: CrossSectionSpec | None = None,
length_extension: float = 3,
**kwargs) -> Component
Coupler for ring.
Arguments:
gap
- spacing between parallel coupled straight waveguides.radius
- of the bends.length_x
- length of the parallel coupled straight waveguides.coupler90
- straight coupled to a 90deg bend.bend
- bend spec.coupler_straight
- two parallel coupled straight waveguides.cross_section
- cross_section spec.bend_cross_section
- optional bend cross_section spec.length_extension
- for the ports.kwargs
- cross_section settings for bend and coupler... code::
2 3 | | \ / \ / ---=========--- 1 length_x 4
coupler_ring_point¶
@gf.cell
def coupler_ring_point(coupler_ring: ComponentFactory = coupler_ring,
open_layers: LayerSpecs = None,
open_sizes: Coordinates | None = None,
**kwargs) -> Component
Coupler ring that removes some layers at the coupling region.
This allows short interaction lengths (point couplers).
Arguments:
coupler_ring
- coupler_ring component to process.open_layers
- layers to perform the boolean operations on.open_sizes
- sizes of the boxes to use to remove layers, centered at bus center.
Arguments:
gap
- spacing between parallel coupled straight waveguides.radius
- of the bends.length_x
- length of the parallel coupled straight waveguides.coupler90
- straight coupled to a 90deg bend.bend
- bend spec.coupler_straight
- two parallel coupled straight waveguides.cross_section
- cross_section spec.bend_cross_section
- optional bend cross_section spec.length_extension
- for the ports.kwargs
- cross_section settings for bend and coupler.
gdsfactory.components.nxn¶
nxn¶
@gf.cell
def nxn(west: int = 1,
east: int = 4,
north: int = 0,
south: int = 0,
xsize: float = 8.0,
ysize: float = 8.0,
wg_width: float = 0.5,
layer: LayerSpec = "WG",
wg_margin: float = 1.0,
**kwargs) -> Component
Returns a nxn component with nxn ports (west, east, north, south).
Arguments:
west
- number of west ports.east
- number of east ports.north
- number of north ports.south
- number of south ports.xsize
- size in X.ysize
- size in Y.wg_width
- width of the straight ports.wg_margin
- margin from straight to component edge.kwargs
- port_settings... code::
3 4 || 2 -| |- 5 | | 1 -|____|- 6 | | 8 7
gdsfactory.components.text_freetype¶
text_freetype¶
@gf.cell
def text_freetype(text: str = "abcd",
size: int = 10,
justify: str = "left",
layer: LayerSpec = "WG",
font: str = "DEPLOF") -> Component
Returns text Component.
Arguments:
text
- string.size
- in um.position
- x, y position.justify
- left, right, center.layer
- for the text.font
- Font face to use. Default DEPLOF does not require additional libraries, otherwise freetype load fonts. You can choose font by name (e.g. “Times New Roman”), or by file OTF or TTF filepath.
gdsfactory.components.ring_double¶
ring_double¶
@gf.cell
def ring_double(gap: float = 0.2,
radius: float = 10.0,
length_x: float = 0.01,
length_y: float = 0.01,
coupler_ring: ComponentSpec = coupler_ring_function,
bend: ComponentSpec = bend_euler,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns a double bus ring.
two couplers (ct: top, cb: bottom) connected with two vertical straights (sl: left, sr: right)
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.length_x
- ring coupler length.length_y
- vertical straight length.coupler
- ring coupler spec.bend
- bend spec.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
--==ct==-- | | sl sr length_y | | --==cb==-- gap
length_x
gdsfactory.components.mmi¶
mmi¶
@gf.cell
def mmi(inputs: int = 1,
outputs: int = 4,
width: float | None = None,
width_taper: float = 1.0,
length_taper: float = 10.0,
length_mmi: float = 5.5,
width_mmi: float = 5,
gap_input_tapers: float = 0.25,
gap_output_tapers: float = 0.25,
taper: ComponentFactory = taper_function,
straight: ComponentFactory = straight_function,
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip",
input_positions: list[float] | None = None,
output_positions: list[float] | None = None) -> Component
mxn MultiMode Interferometer (MMI).
Arguments:
inputs
- number of inputs.outputs
- number of outputs.width
- input and output straight width. Defaults to cross_section.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_input_tapers
- gap between input tapers from edge to edge.gap_output_tapers
- gap between output tapers from edge to edge.taper
- taper function.straight
- straight function.with_bbox
- add rectangular box in cross_section bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- specification (CrossSection, string or dict).input_positions
- optional positions of the inputs.output_positions
- optional positions of the outputs... code::
length_mmi <------>
| | / _ o2 __ __ o3 \ / _ _ _ | | _ _ _ _| gap_output_tapers / _ o1 __ __ o4 \ / |_______| | | <-> length_taper
gdsfactory.components.mzi_arms¶
mzi_arms¶
@cell
def mzi_arms(delta_length: float = 10.0,
length_y: float = 0.8,
length_x: float = 0.1,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
straight_y: ComponentSpec | None = None,
straight_x_top: ComponentSpec | None = None,
straight_x_bot: ComponentSpec | None = None,
splitter: ComponentSpec = mmi1x2,
combiner: ComponentSpec | None = None,
with_splitter: bool = True,
delta_yright: float = 0,
**kwargs) -> Component
Mzi made with arms.
This MZI code is slightly deprecated. You can find a more robust mzi in gf.components.mzi
Arguments:
delta_length
- bottom arm vertical extra length.length_y
- vertical length for both and top arms.length_x
- horizontal length.bend
- 90 degrees bend library.straight
- straight spec.straight_y
- straight for length_y and delta_length.straight_x_top
- top straight for length_x.straight_x_bot
- bottom straight for length_x.splitter
- splitter spec.combiner
- combiner spec.with_splitter
- if False removes splitter.delta_yright
- extra length for right y-oriented waveguide.kwargs
- cross_section settings... code::
Lx | | Ly Lyr (not a parameter) | | splitter==| |==combiner | | Ly Lyr (not a parameter) | | | delta_length/2 | | |Lx|
| | | | | | | | | splitter d1 d2 combiner | ____ | | ____ | | | || |_______
gdsfactory.components.grating_coupler_tree¶
grating_coupler_tree¶
@gf.cell
def grating_coupler_tree(
n: int = 4,
straight_spacing: float = 4.0,
grating_coupler: ComponentSpec = grating_coupler_elliptical_te,
with_loopback: bool = False,
bend: ComponentSpec = "bend_euler",
fanout_length: float = 0.0,
layer_label: LayerSpec = "TEXT",
**kwargs) -> Component
Array of straights connected with grating couplers.
useful to align the 4 corners of the chip
Arguments:
n
- number of gratings.straight_spacing
- in um.grating_coupler
- spec.with_loopback
- adds loopback.bend
- bend spec.fanout_length
- in um.layer_label
- for layer.kwargs
- cross_section settings.
gdsfactory.components.cdsem_all¶
CD SEM structures.
cdsem_all¶
@cell
def cdsem_all(widths: tuple[float, ...] = (0.4, 0.45, 0.5, 0.6, 0.8, 1.0),
dense_lines_width: float | None = 0.3,
dense_lines_width_difference: float = 20e-3,
dense_lines_gap: float = 0.3,
dense_lines_labels: tuple[str, ...] = ("DL", "DM", "DH"),
straight: ComponentSpec = "straight",
bend90: ComponentSpec | None = "bend_circular",
cross_section: CrossSectionSpec = "strip",
text: ComponentSpec = text_rectangular_mini) -> Component
Column with all optical PCMs.
Arguments:
widths
- for straight lines.dense_lines_width
- in um.dense_lines_width_difference
- in um.dense_lines_gap
- in um.dense_lines_labels
- strings.straight
- spec.bend90
- spec.cross_section
- spec.text
- spec.
gdsfactory.components.fiber¶
fiber¶
@gf.cell
def fiber(core_diameter: float = 10,
cladding_diameter: float = 125,
layer_core: LayerSpec = "WG",
layer_cladding: LayerSpec = "WGCLAD") -> Component
Returns a fiber.
Arguments:
core_diameter
- in um.cladding_diameter
- in um.layer_core
- layer spec for fiber core.layer_cladding
- layer spec for fiber cladding.
gdsfactory.components.grating_coupler_array¶
grating_coupler_array¶
@gf.cell
def grating_coupler_array(
grating_coupler: ComponentSpec = grating_coupler_elliptical,
pitch: float = 127.0,
n: int = 6,
port_name: str = "o1",
rotation: int = 0,
with_loopback: bool = False) -> Component
Array of grating couplers.
Arguments:
grating_coupler
- ComponentSpec.pitch
- x spacing.n
- number of grating couplers.port_name
- port name.rotation
- rotation angle for each reference.with_loopback
- if True, adds a loopback between edge GCs. Only works for rotation = 90 for now.
gdsfactory.components.optimal_step¶
optimal_step¶
@cell
def optimal_step(
start_width: float = 10,
end_width: float = 22,
num_pts: int = 50,
width_tol: float = 1e-3,
anticrowding_factor: float = 1.2,
symmetric: bool = False,
layer: LayerSpec = (1, 0)) -> Component
Returns an optimally-rounded step geometry.
Arguments:
start_width
- Width of the connector on the left end of the step.end_width
- Width of the connector on the right end of the step.num_pts
- number of points comprising the entire step geometry.width_tol
- Point at which to terminate the calculation of the optimal stepanticrowding_factor
- Factor to reduce current crowding by elongating the structure and reducing the curvaturesymmetric
- If True, adds a mirrored copy of the step across the x-axis to the geometry and adjusts the width of the ports.layer
- layer spec to put polygon geometry on.based on phidl.geometry
Notes¶
Optimal structure from Clem & Berggren (2011) Clem, J., & Berggren, K. (2011). Geometry-dependent critical currents in superconducting nanocircuits. Physical Review B, 84(17), 1–27.
gdsfactory.components.coupler90bend¶
coupler90bend¶
@gf.cell
def coupler90bend(
radius: float = 10.0,
gap: float = 0.2,
bend: ComponentSpec = bend_euler,
cross_section_inner: CrossSectionSpec = "strip",
cross_section_outer: CrossSectionSpec = "strip") -> Component
Returns 2 coupled bends.
Arguments:
radius
- um.gap
- um.bend
- for bend.cross_section_inner
- spec inner bend.cross_section_outer
- spec outer bend... code::
r 3 4 | | | | / / | / / 2____/ / 1_____/
gdsfactory.components.awg¶
Sample AWG.
free_propagation_region¶
@gf.cell
def free_propagation_region(width1: float = 2.0,
width2: float = 20.0,
length: float = 20.0,
wg_width: float = 0.5,
inputs: int = 1,
outputs: int = 10,
cross_section: CrossSectionSpec = strip,
**kwargs) -> Component
Free propagation region.
Arguments:
width1
- width of the input region.width2
- width of the output region.length
- length of the free propagation region.wg_width
- waveguide width.inputs
- number of inputs.outputs
- number of outputs.cross_section
- cross_section function.**kwargs
- cross_section parameters... code::
length <--> /| / | width1| | width2 \ | |
awg¶
@gf.cell
def awg(arms: int = 10,
outputs: int = 3,
free_propagation_region_input_function=free_propagation_region_input,
free_propagation_region_output_function=free_propagation_region_output,
fpr_spacing: float = 50.0) -> Component
Returns a basic Arrayed Waveguide grating.
Arguments:
arms
- number of arms.outputs
- number of outputs.free_propagation_region_input_function
- for input.free_propagation_region_output_function
- for output.fpr_spacing
- x separation between input/output free propagation region.
gdsfactory.components.ring_crow¶
ring_crow¶
@gf.cell
def ring_crow(
gaps: list[float] = [0.2] * 4,
radius: list[float] = [10.0] * 3,
input_straight_cross_section: CrossSectionSpec = strip,
output_straight_cross_section: CrossSectionSpec = strip,
bends: list[ComponentSpec] = [bend_circular] * 3,
ring_cross_sections: list[CrossSectionSpec] = [strip] * 3
) -> Component
Coupled ring resonators.
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.length_x
- ring coupler length.length_y
- vertical straight length.coupler
- ring coupler spec.straight
- straight spec.bend
- bend spec.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
--==ct==-- gap[N-1] | | sl sr ring[N-1] | | --==cb==-- gap[N-2]
. . .
--==ct==-- | | sl sr lengths_y[1], ring[1] | | --==cb==-- gap[1]
--==ct==-- | | sl sr lengths_y[0], ring[0] | | --==cb==-- gap[0]
length_x
gdsfactory.components.coupler_asymmetric¶
coupler_asymmetric¶
@gf.cell
def coupler_asymmetric(bend: ComponentSpec = bend_s,
gap: float = 0.234,
dy: float = 5.0,
dx: float = 10.0,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Bend coupled to straight waveguide.
Arguments:
bend
- spec.gap
- um.dy
- port to port vertical spacing.dx
- bend length in x direction.cross_section
- spec.kwargs
- cross_section settings... code::
dx |-----| _____ o2 / | / | gap o1_______ | dy o3
gdsfactory.components.interdigital_capacitor_enclosed¶
interdigital_capacitor_enclosed¶
@gf.cell
def interdigital_capacitor_enclosed(
enclosure_box: Sequence[Sequence[float | int]] = [[-200, -200],
[200, 200]],
fingers: int = INTERDIGITAL_DEFAULTS["fingers"],
finger_length: float | int = INTERDIGITAL_DEFAULTS["finger_length"],
finger_gap: float | int = INTERDIGITAL_DEFAULTS["finger_gap"],
thickness: float | int = INTERDIGITAL_DEFAULTS["thickness"],
cpw_dimensions: tuple[float | int, float | int] = (10, 6),
gap_to_ground: float | int = 5,
metal_layer: LayerSpec = INTERDIGITAL_DEFAULTS["layer"],
gap_layer: LayerSpec = "DEEPTRENCH") -> Component
Generates an interdigital capacitor surrounded by a ground plane and coplanar waveguides with ports on both ends.
See for :func:~interdigital_capacitor
for details.
Notes:
finger_length=0
effectively provides a plate capacitor.
Arguments:
enclosure_box
- Bounding box dimensions for a ground metal enclosure.fingers
- total fingers of the capacitor.finger_length
- length of the probing fingers.finger_gap
- length of gap between the fingers.thickness
- Thickness of fingers and section before the fingers.gap_to_ground
- Size of gap from capacitor to ground metal.cpw_dimensions
- Dimensions for the trace width and gap width of connecting coplanar waveguides.metal_layer
- layer for metalization.gap_layer
- layer for trenching.
gdsfactory.components.version_stamp¶
qrcode¶
@gf.cell
def qrcode(data: str = "mask01",
psize: int = 1,
layer: LayerSpec = "WG") -> Component
Returns QRCode.
version_stamp¶
@gf.cell
def version_stamp(labels: tuple[str, ...] = ("demo_label", ),
with_qr_code: bool = False,
layer: LayerSpec = "WG",
pixel_size: int = 1,
version: str | None = None,
text_size: int = 10) -> Component
Component with module version and date.
Arguments:
labels
- Iterable of labels
gdsfactory.components.component_sequence¶
SequenceGenerator Objects¶
class SequenceGenerator()
__init__¶
def __init__(start_sequence: str = "IL",
repeated_sequence: str = "ASASBSBS",
end_sequence: str = "LO") -> None
Sequence generator.
Main use case: any type of cascade of components with repeating patterns such as serpentine, cutbacks etc... Component sequences have two ports by default. it adds aliases for the components forming the sequence. They use the component symbol with a suffix index starting from 1, so you may access the ports from any subcomponent.
Usually we can break these components in 3 parts:
- there is a starting pattern with input and possibly some special connections
- then a repeating pattern
- An ending pattern with an output
Example of symbol meaning
A: bend connected with input W0 B: bend connected with input N0 I: taper with input ‘1’ O: taper with input ‘2’ S: short straight waveguide L: long straight waveguide
parse_component_name¶
def parse_component_name(name: str) -> tuple[str, bool]
If the component name has more than one character and starts with “!”.
then we need to flip along the axis given by the input port angle.
component_sequence¶
@gf.cell
def component_sequence(sequence: str,
symbol_to_component: dict[str, tuple[ComponentSpec, str,
str]],
ports_map: dict[str, tuple[str, str]] | None = None,
port_name1: str = "o1",
port_name2: str = "o2",
start_orientation: float = 0.0) -> Component
Returns component from ASCII sequence.
if you prefix a symbol with ! it mirrors the component
Arguments:
sequence
- a string or a list of symbols.symbol_to_component
- maps symbols to (component, input, output).ports_map
- (optional) extra port mapping using the convention.{port_name
- (alias_name, port_name)}port_name1
- input port_name.port_name2
- output port_name.start_orientation
- in degrees.
Returns:
component
- containing the sequence of sub-components instantiated and connected together in the sequence order... plot:: :include-source:
import gdsfactory as gf
bend180 = gf.components.bend_circular180() wg_pin = gf.components.straight_pin(length=40) wg = gf.components.straight()
Define a map between symbols and (component, input port, output port)¶
symbol_to_component = {
"A"
- (bend180, ‘o1’, ‘o2’),"B"
- (bend180, ‘o2’, ‘o1’),"H"
- (wg_pin, ‘o1’, ‘o2’),"-"
- (wg, ‘o1’, ‘o2’), }Each character in the sequence represents a component¶
s = “AB-H-H-H-H-BA” c = gf.components.component_sequence(sequence=s, symbol_to_component=symbol_to_component) c.plot()
gdsfactory.components.text¶
text¶
@gf.cell
def text(text: str = "abcd",
size: float = 10.0,
position: Coordinate = (0, 0),
justify: str = "left",
layer: LayerSpec = "WG") -> Component
Text shapes.
Arguments:
text
- string.size
- in um.position
- x, y position.justify
- left, right, center.layer
- for the text.
text_lines¶
@gf.cell
def text_lines(text: tuple[str, ...] = ("Chip", "01"),
size: float = 0.4,
layer: LayerSpec = "WG") -> Component
Returns a Component from a text lines.
Arguments:
text
- list of strings.size
- text size.layer
- text layer.
gdsfactory.components.array_with_via¶
array_with_via¶
@cell
def array_with_via(component: ComponentSpec = pad,
columns: int = 3,
spacing: float = 150.0,
via_spacing: float = 10.0,
straight_length: float = 60.0,
cross_section: CrossSectionSpec | None = metal2,
via_stack: ComponentSpec = via_stack_factory,
via_stack_dy: float = 0,
port_orientation: float = 180,
port_offset: Float2 | None = None,
**kwargs) -> Component
Returns an array of vias in X axis with fanout waveguides facing west.
Arguments:
component
- to replicate in the array.columns
- number of components.spacing
- for the array in um.via_spacing
- for fanout in um.straight_length
- length of the straight at the end in um.waveguide
- waveguide definition.cross_section
- spec.via_stack
- spec.via_stack_dy
- via_stack offset in um.port_orientation
- 180: facing west.port_offset
- Optional port movement in um.kwargs
- cross_section settings.
array_with_via_2d¶
@cell
def array_with_via_2d(spacing: Float2 = (150.0, 150.0),
columns: int = 3,
rows: int = 2,
**kwargs) -> Component
Returns 2D array with fanout waveguides facing west.
Arguments:
spacing
- 2D spacing x,y in um.columns
- number of columns.rows
- number of rows.
Arguments:
component
- to replicatecolumns
- number of componentsspacing
- floatvia_spacing
- for fanoutstraight_length
- length of the straight at the end via_stack_port_name:
gdsfactory.components.L¶
L¶
@gf.cell
def L(width: int | float = 1,
size: tuple[int, int] = (10, 20),
layer: LayerSpec = "M3",
port_type: str = "electrical") -> Component
Generates an ‘L’ geometry with ports on both ends.
Based on phidl.
Arguments:
width
- of the line.size
- length and height of the base.layer
- spec.port_type
- for port.
gdsfactory.components.cdsem_straight¶
CD SEM structures.
cdsem_straight¶
@cell
def cdsem_straight(widths: tuple[float, ...] = (0.4, 0.45, 0.5, 0.6, 0.8, 1.0),
length: float = LINE_LENGTH,
cross_section: CrossSectionSpec = "strip",
text: ComponentSpec | None = text_rectangular_mini,
spacing: float = 5) -> Component
Returns straight waveguide lines width sweep.
Arguments:
widths
- for the sweep.length
- for the line.cross_section
- for the lines.text
- optional text for labels.spacing
- edge to edge spacing.
gdsfactory.components.die_bbox¶
based on phidl.geometry.
die_bbox¶
@gf.cell
def die_bbox(component: ComponentSpec = big_square,
street_width: float = 100.0,
street_length: float | None = None,
die_name: str | None = None,
text_size: float = 100.0,
text_anchor: Anchor = "sw",
layer: LayerSpec = "M3",
padding: float = 10.0) -> gf.Component
Returns component with boundary box frame around it.
Perfect for defining the boundary of the chip/die it can also add a label with the name of the die. similar to die and bbox.
Arguments:
component
- to frame.street_width
- Width of the boundary box.street_length
- length of the boundary box.die_name
- Label text.text_size
- Label text size.text_anchor
- {‘nw’, ‘nc’, ‘ne’, ‘sw’, ‘sc’, ‘se’} text location.layer
- Specific layer(s) to put polygon geometry on.padding
- adds padding.
gdsfactory.components.circle¶
circle¶
@gf.cell
def circle(radius: float = 10.0,
angle_resolution: float = 2.5,
layer: LayerSpec = "WG") -> Component
Generate a circle geometry.
Arguments:
radius
- of the circle.angle_resolution
- number of degrees per point.layer
- layer.
gdsfactory.components.interdigital_capacitor¶
interdigital_capacitor¶
@gf.cell
def interdigital_capacitor(fingers: int = 4,
finger_length: float | int = 20.0,
finger_gap: float | int = 2.0,
thickness: float | int = 5.0,
layer: LayerSpec = "WG") -> Component
Generates an interdigital capacitor with ports on both ends.
See for example Zhu et al., Accurate circuit model of interdigital capacitor and its application to design of new uasi-lumped miniaturized filters with suppression of harmonic resonance
, doi: 10.1109/22.826833.
Notes:
finger_length=0
effectively provides a plate capacitor.
Arguments:
fingers
- total fingers of the capacitor.finger_length
- length of the probing fingers.finger_gap
- length of gap between the fingers.thickness
- Thickness of fingers and section before the fingers.layer
- spec.
gdsfactory.components.bend_circular_heater¶
bend_circular_heater¶
@gf.cell
def bend_circular_heater(radius: float = 10,
angle: float = 90,
npoints: int | None = None,
heater_to_wg_distance: float = 1.2,
heater_width: float = 0.5,
layer_heater: LayerSpec = "HEATER",
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Creates an arc of arclength theta
starting at angle start_angle
.
Arguments:
radius
- in um.angle
- angle of arc (degrees).npoints
- Number of points used per 360 degrees.heater_to_wg_distance
- in um.heater_width
- in um.layer_heater
- for heater.with_bbox
- box in bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- specification (CrossSection, string, CrossSectionFactory dict).kwargs
- cross_section settings.
gdsfactory.components.straight¶
Straight waveguide.
straight¶
@gf.cell
def straight(length: float = 10.0,
npoints: int = 2,
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns a Straight waveguide.
Arguments:
length
- straight length (um).npoints
- number of points.with_bbox
- box in bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- specification (CrossSection, string, CrossSectionFactory dict).kwargs
- cross_section settings... code::
o1 -------------- o2 length
gdsfactory.components.seal_ring¶
seal_ring¶
@gf.cell_without_validator
def seal_ring(bbox: tuple[Coordinate, Coordinate] = ((-1.0, -1.0), (3.0, 4.0)),
seal: gf.typings.ComponentSpec = via_stack,
width: float = 10,
padding: float = 10.0,
with_north: bool = True,
with_south: bool = True,
with_east: bool = True,
with_west: bool = True) -> gf.Component
Returns a continuous seal ring boundary at the chip/die.
Prevents cracks from spreading and shields when connected to ground.
Arguments:
bbox
- to add seal ring around. You can pass Component.bbox.seal
- function for the seal.width
- of the seal.padding
- from component to seal.with_north
- includes seal.with_south
- includes seal.with_east
- includes seal.with_west
- includes seal.
gdsfactory.components.ellipse¶
ellipse¶
@gf.cell
def ellipse(radii: tuple[float, float] = (10.0, 5.0),
angle_resolution: float = 2.5,
layer: LayerSpec = "WG") -> Component
Returns ellipse component.
Arguments:
radii
- Semimajor and semiminor axis lengths of the ellipse.angle_resolution
- number of degrees per point.layer
- Specific layer(s) to put polygon geometry on.The orientation of the ellipse is determined by the order of the radii variables; if the first element is larger, the ellipse will be horizontal and if the second element is larger, the ellipse will be vertical.
gdsfactory.components.align¶
align_wafer¶
@cell
def align_wafer(width: float = 10.0,
spacing: float = 10.0,
cross_length: float = 80.0,
layer: LayerSpec = "WG",
layer_cladding: tuple[int, int] | None = None,
square_corner: str = "bottom_left") -> Component
Returns cross inside a frame to align wafer.
Arguments:
width
- in um.spacing
- in um.cross_length
- for the cross.layer
- for the cross.layer_cladding
- optional.square_corner
- bottom_left, bottom_right, top_right, top_left.
add_frame¶
@cell
def add_frame(component: ComponentSpec = rectangle,
width: float = 10.0,
spacing: float = 10.0,
layer: LayerSpec = "WG") -> Component
Returns component with a frame around it.
Arguments:
component
- Component to frame.width
- of the frame.spacing
- of component to frame.layer
- frame layer.
gdsfactory.components.dicing_lane¶
dicing_lane¶
@gf.cell
def dicing_lane(size: Float2 = (50, 300),
marker: ComponentSpec = triangle_metal,
layer_dicing: LayerSpec = "DICING") -> Component
Dicing lane with triangular markers on both sides.
Arguments:
size
- (tuple) Width and height of rectangle.marker
- function to generate the dicing lane markers.layer_dicing
- Specific layer to put polygon geometry on.
gdsfactory.components.mzit_lattice¶
mzit_lattice¶
@gf.cell
def mzit_lattice(coupler_lengths: tuple[float, ...] = (10.0, 20.0),
coupler_gaps: tuple[float, ...] = (0.2, 0.3),
delta_lengths: tuple[float, ...] = (10.0, ),
mzi: ComponentSpec = mzit) -> Component
Mzi fab tolerant lattice filter.
.. code::
cp1
W3 W1 __ __ E1___w0_t2 _w2___
\ / \
\ length1 / |
============== gap1 |
/ \ |
__/ \_____w0___t1 _w1 |
W2 W0 E0 \ | .
... | | .
W1 W1 | | .
__ __w0____t1____w1___/ |
\ / |
\ lengthN / |
============== gapN |
/ \ |
__/ \_ |
W0 W0 \ E0_w0__t2 __w1_____/
cpN
gdsfactory.components.delay_snake_sbend¶
delay_snake_sbend¶
@gf.cell
def delay_snake_sbend(length: float = 100.0,
length1: float = 0.0,
length4: float = 0.0,
radius: float = 5.0,
waveguide_spacing: float = 5.0,
bend: ComponentSpec = "bend_euler",
sbend: ComponentSpec = "bend_s",
sbend_xsize: float = 100.0,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns compact Snake with sbend in the middle.
Input port faces west and output port faces east.
Arguments:
length
- total length.length1
- first straight section length in um.length3
- third straight section length in um.radius
- u bend radius in um.waveguide_spacing
- waveguide pitch in um.bend
- bend spec.sbend
- sbend spec.sbend_size
- sbend size.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
length1 <---------------------------- length2 spacing | _______ | | \ | | \ | bend1 radius | \sbend | bend2| \ | | \ | | __| | ---------------------->-----------> length3 length4
We adjust length2 and length3
gdsfactory.components.mmi1x2_with_sbend¶
mmi1x2_with_sbend¶
@gf.cell
def mmi1x2_with_sbend(with_sbend: bool = True,
s_bend: ComponentSpec = bend_s,
cross_section: CrossSectionSpec = "strip") -> Component
Returns 1x2 splitter for Cband.
https://
Arguments:
with_sbend
- add sbend.s_bend
- S-bend spec.cross_section
- spec.
gdsfactory.components.straight_rib¶
Straight Doped PIN waveguide.
gdsfactory.components.ring_single_heater¶
ring_single_heater¶
@gf.cell
def ring_single_heater(
gap: float = 0.2,
radius: float = 10.0,
length_x: float = 4.0,
length_y: float = 0.6,
coupler_ring: ComponentSpec = _coupler_ring,
bend: ComponentSpec = bend_euler,
cross_section_waveguide_heater: CrossSectionSpec = "strip_heater_metal",
cross_section: CrossSectionSpec = "strip",
via_stack: ComponentSpec = via_stack_heater_mtop_mini,
port_orientation: float | None = None,
via_stack_offset: Float2 = (0, 0),
**kwargs) -> gf.Component
Returns a single ring with heater on top.
ring coupler (cb: bottom) connects to two vertical straights (sl: left, sr: right), two bends (bl, br) and horizontal straight (wg: top)
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.length_x
- ring coupler length.length_y
- vertical straight length.coupler_ring
- ring coupler function.bend
- 90 degrees bend function.cross_section_waveguide_heater
- for heater.cross_section
- for regular waveguide.via_stack
- for heater to routing metal.port_orientation
- for electrical ports to promote from via_stack.via_stack_offset
- x,y offset for via_stack.kwargs
- cross_section settings... code::
bl-st-br | | sl sr length_y | | --==cb==-- gap
length_x
gdsfactory.components.text_rectangular¶
text_rectangular¶
@gf.cell
def text_rectangular(text: str = "abcd",
size: float = 10.0,
position: tuple[float, float] = (0.0, 0.0),
justify: str = "left",
layer: LayerSpec = "WG",
font: Callable = rectangular_font) -> Component
Pixel based font, guaranteed to be manhattan, without acute angles.
Arguments:
text
- string.size
- pixel size.position
- coordinate.justify
- left, right or center.layer
- for text.font
- function that returns dictionary of characters.
text_rectangular_multi_layer¶
def text_rectangular_multi_layer(
text: str = "abcd",
layers: LayerSpecs = ("WG", "M1", "M2", "M3"),
text_factory: ComponentSpec = text_rectangular,
**kwargs) -> Component
Returns rectangular text in different layers.
Arguments:
text
- string of textlayers
- list of layers to replicate the texttext_factory
- function to create the text Components
Arguments:
size
- pixel sizeposition
- coordinatejustify
- left, right or centerfont
- function that returns dictionary of characters
gdsfactory.components.cavity¶
cavity¶
@cell
def cavity(component: ComponentSpec = dbr,
coupler: ComponentSpec = "coupler",
length: float = 0.1,
gap: float = 0.2,
**kwargs) -> Component
Returns cavity from a coupler and a mirror.
connects the W0 port of the mirror to E1 and W1 coupler ports creating a resonant cavity
Arguments:
component
- mirror.coupler
- coupler library.length
- coupler length.gap
- coupler gap.kwargs
- coupler_settings... code::
ml (mirror left) mr (mirror right) | | |o1 - o2__ __o3 - o1| | \ / | \ / ---=========--- o1 o1 length o4 o2
gdsfactory.components.pads_shorted¶
pads_shorted¶
@gf.cell
def pads_shorted(pad: ComponentSpec = pad_function,
columns: int = 8,
pad_spacing: float = 150.0,
layer_metal: LayerSpec = "M3",
metal_width: float = 10) -> Component
Returns a 1D array of shorted_pads.
Arguments:
pad
- pad spec.columns
- number of columns.pad_spacing
- in umlayer_metal
- for the short.metal_width
- for the short.
gdsfactory.components.grating_coupler_dual_pol¶
grating_coupler_dual_pol¶
@gf.cell
def grating_coupler_dual_pol(unit_cell: ComponentSpec = rectangle_unit_cell,
period_x: float = 0.58,
period_y: float = 0.58,
x_span: float = 11,
y_span: float = 11,
length_taper: float = 150.0,
width_taper: float = 10.0,
polarization: str = "dual",
wavelength: float = 1.55,
taper: ComponentSpec = taper_function,
base_layer: LayerSpec | None = "WG",
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
2 dimensional, dual polarization grating coupler.
Based on a photonic crystal with a unit cell that is usually an ellipse, a rectangle or a circle.
Arguments:
unit_cell
- component describing the unit cell of the photonic crystal.period_x
- spacing between unit cells in the x direction [um].period_y
- spacing between unit cells in the y direction [um].x_span
- full x span of the photonic crystal.y_span
- full y span of the photonic crystal.length_taper
- taper length [um].width_taper
- width of the taper at the grating coupler side [um].polarization
- polarization of the grating coupler.wavelength
- operation wavelength [um]taper
- function to generate the tapers.base_layer
- layer to draw over the whole photonic crystal (necessary if the unit cells are etched into a base layer).cross_section
- for the routing waveguides.kwargs
- cross_section settings... code::
side view fiber
/ / / / / / / /
|-||-||-|__ --> unit_cells base_layer | o1 ______________|
top view
// | o o o | o1 __ // | o o o | \ | o o o | \ | o o o |¶
\ // \ // | o2
gdsfactory.components.ring_single_pn¶
ring_single_pn¶
@gf.cell
def ring_single_pn(gap: float = 0.3,
radius: float = 5.0,
doping_angle: float = 250,
cross_section: CrossSection = partial(
gf.cross_section.strip,
sections=(Section(width=2 * 2.425,
layer="SLAB90",
name="slab"), ),
),
pn_cross_section: CrossSection = partial(
gf.cross_section.pn,
width_doping=2.425,
width_slab=2 * 2.425,
layer_via="VIAC",
width_via=0.5,
layer_metal="M1",
width_metal=0.5,
),
doped_heater: bool = True,
doped_heater_angle_buffer: float = 10,
doped_heater_layer: LayerSpec = "NPP",
doped_heater_width: float = 0.5,
doped_heater_waveguide_offset: float = 2.175,
heater_vias: ComponentSpec = partial(
via_stack,
size=(0.5, 0.5),
layers=("M1", "M2"),
vias=(
partial(
via,
layer="VIAC",
size=(0.1, 0.1),
spacing=(0.2, 0.2),
enclosure=0.1,
),
partial(
via,
layer="VIA1",
size=(0.1, 0.1),
spacing=(0.2, 0.2),
enclosure=0.1,
),
),
),
**kwargs) -> gf.Component
Returns single pn ring with optional doped heater.
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.doping_angle
- angle in degrees representing portion of ring that is doped.length_x
- ring coupler length.length_y
- vertical straight length.cross_section
- cross_section spec for non-PN doped rib waveguide sections.pn_cross_section
- cross section of pn junction.doped_heater
- boolean for if we include doped heater or not.doped_heater_angle_buffer
- angle in degrees buffering heater from pn junction.doped_heater_layer
- doping layer for heater.doped_heater_width
- width of doped heater.doped_heater_waveguide_offset
- distance from the center of the ring waveguide to the center of the doped heater.heater_vias
- components specifications for heater vias.kwargs
- cross_section settings.
gdsfactory.components.pack_doe¶
generate_doe¶
def generate_doe(
doe: ComponentSpec,
settings: dict[str, list[Any]],
do_permutations: bool = False,
function: CellSpec | None = None
) -> tuple[list[Component], list[dict]]
Generates a component DOE (Design of Experiment).
which can then be packed, or used elsewhere.
Arguments:
doe
- function to return Components.settings
- component settings.do_permutations
- for each setting.function
- for the component (add padding, grating couplers ...)
pack_doe¶
@cell
def pack_doe(doe: ComponentSpec = _doe,
settings: dict[str, list[Any]] = _settings,
do_permutations: bool = False,
function: CellSpec | None = None,
**kwargs) -> Component
Packs a component DOE (Design of Experiment) using pack.
Arguments:
doe
- function to return Components.settings
- component settings.do_permutations
- for each setting.function
- to apply (add padding, grating couplers).keyword Args:
spacing
- Minimum distance between adjacent shapes.aspect_ratio
- (width, height) ratio of the rectangular bin.max_size
- Limits the size into which the shapes will be packed.sort_by_area
- Pre-sorts the shapes by area.density
- Values closer to 1 pack tighter but require more computation.precision
- Desired precision for rounding vertex coordinates.text
- Optional function to add text labels.text_prefix
- for labels. For example. ‘A’ for ‘A1’, ‘A2’...text_offsets
- relative to component size info anchor. Defaults to center.text_anchors
- relative to component (ce cw nc ne nw sc se sw center cc).name_prefix
- for each packed component (avoids the Unnamed cells warning). Note that the suffix contains a uuid so the name will not be deterministic.rotation
- for each component in degrees.h_mirror
- horizontal mirror in y axis (x, 1) (1, 0). This is the most common.v_mirror
- vertical mirror using x axis (1, y) (0, y).
pack_doe_grid¶
@cell
def pack_doe_grid(doe: ComponentSpec = _doe,
settings: dict[str, list[Any]] = _settings,
do_permutations: bool = False,
function: CellSpec | None = None,
with_text: bool = False,
**kwargs) -> Component
Packs a component DOE (Design of Experiment) using grid.
Arguments:
component
- function to return Components.settings
- component settings.do_permutations
- for each setting.function
- to apply to component (add padding, grating couplers).with_text
- includes text label.keyword Args:
spacing
- between adjacent elements on the grid, can be a tuple for different distances in height and width.separation
- If True, guarantees elements are separated with fixed spacing if False, elements are spaced evenly along a grid.shape
- x, y shape of the grid (see np.reshape). If no shape and the list is 1D, if np.reshape were run with (1, -1).align_x
- {‘x’, ‘xmin’, ‘xmax’} for x (column) alignment along.align_y
- {‘y’, ‘ymin’, ‘ymax’} for y (row) alignment along.edge_x
- {‘x’, ‘xmin’, ‘xmax’} for x (column) (ignored if separation = True).edge_y
- {‘y’, ‘ymin’, ‘ymax’} for y (row) (ignored if separation = True).rotation
- for each component in degrees.h_mirror
- horizontal mirror y axis (x, 1) (1, 0). most common mirror.v_mirror
- vertical mirror using x axis (1, y) (0, y).
gdsfactory.components.litho_ruler¶
litho_ruler¶
@gf.cell
def litho_ruler(height: float = 2,
width: float = 0.5,
spacing: float = 2.0,
scale: tuple[float, ...] = (3, 1, 1, 1, 1, 2, 1, 1, 1, 1),
num_marks: int = 21,
layer: LayerSpec = "WG") -> gf.Component
Ruler structure for lithographic measurement.
Includes marks of varying scales to allow for easy reading by eye.
based on phidl.geometry
Arguments:
height
- Height of the ruling marks in um.width
- Width of the ruling marks in um.spacing
- Center-to-center spacing of the ruling marks in um.scale
- Height scale pattern of marks.num_marks
- Total number of marks to generate.layer
- Specific layer to put the ruler geometry on.
gdsfactory.components.straight_heater_meander¶
straight_heater_meander¶
@gf.cell
def straight_heater_meander(
length: float = 300.0,
spacing: float = 2.0,
cross_section: gf.typings.CrossSectionSpec = "strip",
heater_width: float = 2.5,
extension_length: float = 15.0,
layer_heater: LayerSpec = "HEATER",
radius: float = 5.0,
via_stack: ComponentSpec | None = "via_stack_heater_mtop",
port_orientation1: int | None = None,
port_orientation2: int | None = None,
heater_taper_length: float | None = 10.0,
straight_widths: Floats = (0.8, 0.9, 0.8),
taper_length: float = 10) -> Component
Returns a meander based heater.
based on SungWon Chung, Makoto Nakai, and Hossein Hashemi,
Low-power thermo-optic silicon modulator for large-scale photonic integrated systems
Opt. Express 27, 13430-13459 (2019)
https://
Arguments:
length
- total length of the optical path.spacing
- waveguide spacing (center to center).cross_section
- for waveguide.heater_width
- for heater.extension_length
- of input and output optical ports.layer_heater
- for top heater, if None, it does not add a heater.radius
- for the meander bends.via_stack
- for the heater to via_stack metal.port_orientation1
- in degrees. None adds all orientations.port_orientation2
- in degrees. None adds all orientations.heater_taper_length
- minimizes current concentrations from heater to via_stack.straight_width
- width of the straight section.taper_length
- from the cross_section.
gdsfactory.components.mmi_90degree_hybrid¶
mmi_90degree_hybrid¶
@gf.cell
def mmi_90degree_hybrid(
width: float = 0.5,
width_taper: float = 1.7,
length_taper: float = 40.0,
length_mmi: float = 175.0,
width_mmi: float = 10.0,
gap_mmi: float = 0.8,
taper: ComponentSpec = taper_function,
straight: ComponentSpec = straight_function,
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip") -> Component
90 degree hybrid based on a 4x4 MMI.
Default values from Watanabe et al., “Coherent few mode demultiplexer realized as a 2D grating coupler array in silicon”, Optics Express 28(24), 2020
It could be interesting to consider the design in Guan et al., “Compact and low loss 90° optical hybrid on a silicon-on-insulator platform”, Optics Express 25(23), 2017
Arguments:
width
- input and output straight 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
- (width_taper + gap between tapered wg)/2.taper
- taper function.straight
- straight function.with_bbox
- box in bbox_layers and bbox_offsets avoid DRC sharp edges.cross_section
- spec... code::
length_mmi <------>
| | / _ signal_in __ __ I_out1 \ / _ _ _ | | _ _ _ | gap_mmi | _ | __ Q_out1 | / | | | / _ LO_in __ __ Q_out2 \ / _ _ _ | | _ _ _ | gap_mmi | _ | __ I_out2 | / | ________|
<-> length_taper
gdsfactory.components.grating_coupler_loss¶
connect_loopback¶
def connect_loopback(port0: Port,
port1: Port,
a: float,
b: float,
y_bot_align_route: float,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> list[ComponentReference]
Connects loopback structure.
loss_deembedding_ch13_24¶
@cell
def loss_deembedding_ch13_24(
pitch: float = 127.0,
grating_coupler: ComponentSpec = grating_coupler_te,
input_port_indexes: tuple[int, ...] = (0, 1),
cross_section: CrossSectionSpec = "strip",
port_name: str = "o1",
get_input_label: Callable = get_input_label_function,
**kwargs) -> Component
Grating coupler test structure for fiber array.
Connects channel 1->3, 2->4
Arguments:
pitch
- um.grating_coupler
- spec.input_port_indexes
- adds test labels.cross_section
- spec.port_name
- for the grating_coupler port.kwargs
- cross_section settings.
loss_deembedding_ch12_34¶
@cell
def loss_deembedding_ch12_34(
pitch: float = 127.0,
grating_coupler: ComponentSpec = grating_coupler_te,
input_port_indexes: tuple[int, ...] = (0, 2),
port_name: str = "o1",
cross_section: CrossSectionSpec = "strip",
get_input_label: Callable = get_input_label_function,
**kwargs) -> Component
Grating coupler test structure for fiber array.
Connects channel 1->2, 3->4
Arguments:
pitch
- um.grating_coupler
- spec.input_port_indexes
- for grating couplers.port_name
- for the grating_coupler port.cross_section
- spec.
Arguments:
kwargs
- cross_section settings.
loss_deembedding_ch14_23¶
@cell
def loss_deembedding_ch14_23(
pitch: float = 127.0,
grating_coupler: ComponentSpec = grating_coupler_te,
input_port_indexes: tuple[int, ...] = (0, 1),
cross_section: CrossSectionSpec = "strip",
port_name: str = "o1",
get_input_label: Callable = get_input_label_function,
**kwargs) -> Component
Grating coupler test structure for fiber array.
Connects channel 1->4, 2->3
Arguments:
pitch
- um.grating_coupler
- spec.input_port_indexes
- for grating couplers.cross_section
- spec.port_name
- for the grating_coupler port.
Arguments:
kwargs
- cross_section settings.
grating_coupler_loss_fiber_array¶
@cell
def grating_coupler_loss_fiber_array(
pitch: float = 127.0,
grating_coupler: ComponentSpec = grating_coupler_te,
input_port_indexes: tuple[int, ...] = (0, 1),
port_name: str = "o1",
cross_section: CrossSectionSpec = "strip",
get_input_label: Callable = get_input_label_function,
**kwargs) -> Component
Returns Grating coupler fiber array loopback.
Arguments:
pitch
- spacing.grating_coupler
- spec for grating coupler.input_port_indexes
- for grating couplers.port_name
- for the grating_coupler port.cross_section
- spec.
Arguments:
kwargs
- cross_section settings.
grating_coupler_loss_fiber_array4¶
@cell
def grating_coupler_loss_fiber_array4(
pitch: float = 127.0,
grating_coupler: ComponentSpec = grating_coupler_te,
**kwargs) -> Component
Returns a grating coupler test structure for fiber array.
Measures all combinations for a 4 fiber fiber_array
Connects channel 1->3, 2->4 Connects channel 1->4, 2->3 Connects channel 1->2, 3->4
Arguments:
pitch
- grating_coupler_pitch.grating_coupler
- function.kwargs
- cross_section settings.
gdsfactory.components.ring_double_heater¶
ring_double_heater¶
@gf.cell
def ring_double_heater(
gap: float = 0.2,
radius: float = 10.0,
length_x: float = 0.01,
length_y: float = 0.01,
coupler_ring: ComponentSpec = coupler_ring,
coupler_ring_top: ComponentSpec | None = None,
straight: ComponentSpec = straight,
bend: ComponentSpec = bend_euler,
cross_section_heater: CrossSectionSpec = "heater_metal",
cross_section_waveguide_heater: CrossSectionSpec = "strip_heater_metal",
cross_section: CrossSectionSpec = "strip",
via_stack: ComponentSpec = via_stack_heater_m3_mini,
port_orientation: float | None = None,
via_stack_offset: Float2 = (0, 0),
**kwargs) -> Component
Returns a double bus ring with heater on top.
two couplers (ct: top, cb: bottom) connected with two vertical straights (sl: left, sr: right)
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.length_x
- ring coupler length.length_y
- vertical straight length.coupler_ring
- ring coupler spec.coupler_ring_top
- ring coupler spec for coupler away from vias (defaults to coupler_ring)straight
- straight spec.bend
- bend spec.cross_section_heater
- for heater.cross_section_waveguide_heater
- for waveguide with heater.cross_section
- for regular waveguide.via_stack
- for heater to routing metal.port_orientation
- for electrical ports to promote from via_stack.via_stack_offset
- x,y offset for via_stack.kwargs
- cross_section settings... code::
--==ct==-- | | sl sr length_y | | --==cb==-- gap
length_x
gdsfactory.components.ring_single¶
ring_single¶
@gf.cell
def ring_single(gap: float = 0.2,
radius: float = 10.0,
length_x: float = 4.0,
length_y: float = 0.6,
coupler_ring: ComponentSpec = coupler_ring_function,
bend: ComponentSpec = bend_euler,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> gf.Component
Returns a single ring.
ring coupler (cb: bottom) connects to two vertical straights (sl: left, sr: right), two bends (bl, br) and horizontal straight (wg: top)
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.length_x
- ring coupler length.length_y
- vertical straight length.coupler_ring
- ring coupler spec.bend
- 90 degrees bend spec.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
bl-st-br | | sl sr length_y | | --==cb==-- gap
length_x
gdsfactory.components.terminator¶
terminator¶
@gf.cell
def terminator(length: float | None = 50,
cross_section_input: CrossSectionSpec = "strip",
cross_section_tip: CrossSectionSpec | None = None,
tapered_width: float = 0.2,
doping_layers: LayerSpecs = ("NPP", ),
doping_offset: float = 1) -> gf.Component
Returns doped taper to terminate waveguides.
Arguments:
length
- distance between input and narrow tapered end.cross_section_input
- input cross-section.cross_section_tip
- cross-section at the end of the termination.tapered_width
- width of the default cross-section at the end of the termination. Only used if cross_section_tip is not None.doping_layers
- doping layers to superimpose on the taper. Default N++.doping_offset
- offset of the doping layer beyond the bbox
gdsfactory.components.cutback_splitter¶
cutback_splitter¶
@gf.cell
def cutback_splitter(component: ComponentSpec = mmi1x2,
cols: int = 4,
rows: int = 5,
port1: str = "o1",
port2: str = "o2",
port3: str = "o3",
bend180: ComponentSpec = bend_euler180,
mirror: bool = False,
straight_length: float | None = None,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns a daisy chain of splitters for measuring their loss.
Arguments:
component
- for cutback.cols
- number of columns.rows
- number of rows.port1
- name of first optical port.port2
- name of second optical port.bend180
- ubend.straight
- waveguide spec to connect both sides.mirror
- Flips component. Useful when ‘o2’ is the port that you want to route to.straight_length
- length of the straight section between cutbacks.cross_section
- specification (CrossSection, string or dict).kwargs
- cross_section settings.
gdsfactory.components¶
Each component factory component returns a component.
Make sure your components get imported here so the PDK registers them.
gdsfactory.components.verniers¶
gdsfactory.components.bend_circular¶
bend_circular¶
@gf.cell
def bend_circular(angle: float = 90.0,
npoints: int | None = None,
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns a radial arc.
Arguments:
angle
- angle of arc (degrees).npoints
- number of points.with_bbox
- box in bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- spec (CrossSection, string or dict).kwargs
- cross_section settings... code::
o2 | / / / o1_____/
gdsfactory.components.grating_coupler_elliptical_arbitrary¶
grating_coupler_elliptical_arbitrary¶
@gf.cell
def grating_coupler_elliptical_arbitrary(
gaps: Floats = _gaps,
widths: Floats = _widths,
taper_length: float = 16.6,
taper_angle: float = 60.0,
wavelength: float = 1.554,
fiber_angle: float = 15.0,
nclad: float = 1.443,
layer_slab: LayerSpec | None = "SLAB150",
layer_grating: LayerSpec | None = None,
taper_to_slab_offset: float = -3.0,
polarization: str = "te",
spiked: bool = True,
bias_gap: float = 0,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Grating coupler with parametrization based on Lumerical FDTD simulation.
The ellipticity is derived from Lumerical knowledge base it depends on fiber_angle (degrees), neff, and nclad
Arguments:
gaps
- list of gaps.widths
- list of widths.taper_length
- taper length from input.taper_angle
- grating flare angle.wavelength
- grating transmission central wavelength (um).fiber_angle
- fibre angle in degrees determines ellipticity.nclad
- cladding effective index to compute ellipticity.layer_slab
- Optional slab.layer_grating
- Optional layer for grating. by default None uses cross_section.layer. if different from cross_section.layer expands taper.taper_to_slab_offset
- 0 is where taper ends.polarization
- te or tm.spiked
- grating teeth have spikes to avoid drc errors.bias_gap
- etch gap (um). Positive bias increases gap and reduces width to keep period constant.cross_section
- cross_section spec for waveguide port.kwargs
- cross_section settings.https://
en .wikipedia .org /wiki /Ellipse c = (a1 ** 2 - b1 ** 2) ** 0.5 e = (1 - (b1 / a1) ** 2) ** 0.5 print(e) .. code::
fiber
/ / / / / / / /
|-||-||-|__ layer layer_slab | o1 ______________|
grating_coupler_elliptical_uniform¶
@gf.cell
def grating_coupler_elliptical_uniform(n_periods: int = 20,
period: float = 0.75,
fill_factor: float = 0.5,
**kwargs) -> Component
Grating coupler with parametrization based on Lumerical FDTD simulation.
The ellipticity is derived from Lumerical knowledge base it depends on fiber_angle (degrees), neff, and nclad
Arguments:
n_periods
- number of grating periods.period
- grating pitch in um.fill_factor
- ratio of grating width vs gap.
Arguments:
taper_length
- taper length from input.taper_angle
- grating flare angle.wavelength
- grating transmission central wavelength (um).fiber_angle
- fibre angle in degrees determines ellipticity.neff
- tooth effective index to compute ellipticity.nclad
- cladding effective index to compute ellipticity.layer_slab
- Optional slab.taper_to_slab_offset
- where 0 is at the start of the taper.polarization
- te or tm.spiked
- grating teeth have spikes to avoid drc errors..bias_gap
- etch gap (um). Positive bias increases gap and reduces width to keep period constant.cross_section
- cross_section spec for waveguide port.kwargs
- cross_section settings... code::
fiber
/ / / / / / / /
|-||-||-|__ layer layer_slab | o1 ______________|
gdsfactory.components.spiral_external_io¶
Bends with grating couplers inside the spiral.
maybe: need to add grating coupler loopback as well
get_bend_port_distances¶
def get_bend_port_distances(bend: Component) -> tuple[float64, float64]
Returns distance between bend ports.
spiral_external_io¶
@cell
def spiral_external_io(N: int = 6,
x_inner_length_cutback: float = 300.0,
x_inner_offset: float = 0.0,
y_straight_inner_top: float = 0.0,
xspacing: float = 3.0,
yspacing: float = 3.0,
bend: ComponentSpec = bend_euler,
length: float | None = None,
cross_section: CrossSectionSpec = "strip",
with_inner_ports: bool = False,
y_straight_outer_offset: float = 0.0,
inner_loop_spacing_offset: float = 0.0,
**kwargs) -> Component
Returns spiral with input and output ports outside the spiral.
Arguments:
N
- number of loops.x_inner_length_cutback
- x inner length.x_inner_offset
- x inner offset.y_straight_inner_top
- y straight inner top.xspacing
- center to center x-spacing.yspacing
- center to center y-spacing.bend
- function.length
- length in um, it is the approximates total length.cross_section
- spec.with_inner_ports
- if True, removes the internal S-bend and exposes new portsy_straight_outer_offset
- amount to add/remove to the last points at the outer output of the spiralinner_loop_spacing_offset
- extra difference between the inner portskwargs
- cross_section settings.
gdsfactory.components.crossing_waveguide¶
snap_to_grid¶
def snap_to_grid(p: float, grid_per_unit: int = 1000) -> float64
Round.
crossing_arm¶
@cell
def crossing_arm(r1: float = 3.0,
r2: float = 1.1,
w: float = 1.2,
L: float = 3.4,
layer_slab: LayerSpec = "SLAB150",
cross_section: CrossSectionSpec = "strip") -> Component
Returns crossing arm.
Arguments:
r1
- ellipse radius1.r2
- ellipse radius2.w
- width in um.L
- length in um.layer_slab
- for the shallow etch.cross_section
- spec.
crossing¶
@cell
def crossing(arm: ComponentSpec = crossing_arm,
cross_section: CrossSectionSpec = "strip") -> Component
Waveguide crossing.
Arguments:
arm
- arm spec.cross_section
- spec.
crossing_from_taper¶
@cell
def crossing_from_taper(taper=lambda: taper(width2=2.5, length=3.0)
) -> Component
Returns Crossing based on a taper.
The default is a dummy taper.
Arguments:
taper
- taper function.
crossing_etched¶
@cell
def crossing_etched(width: float = 0.5,
r1: float = 3.0,
r2: float = 1.1,
w: float = 1.2,
L: float = 3.4,
layer_wg: LayerSpec = "WG",
layer_slab: LayerSpec = "SLAB150") -> Component
Waveguide crossing.
Full crossing has to be on WG layer (to start with a 220nm slab). Then we etch the ellipses down to 150nm slabs and we keep linear taper at 220nm.
Arguments:
width
- input waveguides width.r1
- radii.r2
- radii.w
- wide width.L
- length.layer_wg
- waveguide layer.layer_slab
- shallow etch layer.
crossing45¶
@cell
def crossing45(
crossing: ComponentSpec = crossing,
port_spacing: float = 40.0,
dx: float | None = None,
alpha: float = 0.08,
npoints: int = 101,
cross_section: CrossSectionSpec = "strip",
cross_section_bends: CrossSectionSpec = "strip_no_pins") -> Component
Returns 45deg crossing with bends.
Arguments:
crossing
- crossing function.port_spacing
- target I/O port spacing.dx
- target length.alpha
- optimization parameter. diminish it for tight bends, increase it if raises assertion angle errorsnpoints
- number of points.The 45 Degree crossing CANNOT be kept as an SRef since we only allow for multiples of 90Deg rotations in SRef.
.. code::
\ / X / \
compensation_path¶
@cell
def compensation_path(crossing45: ComponentSpec = crossing45_pins,
crossing: ComponentSpec = crossing,
direction: str = "top",
cross_section: CrossSectionSpec = "strip") -> Component
Returns Component Path with same path length as the crossing.
with input and output ports having same y coordinates
Arguments:
crossing45
- component that we want to match in path length. needs to have .info[“components”] with bends and crossing.direction
- the direction in which the bend should go “top” / “bottom”... code::
\ / \ / \ / X /
/
/ \Compensation path:
.. code::
--+-- _/ _ --/ --
gdsfactory.components.dbr¶
DBR gratings.
wavelength = 2periodneff period = wavelength/2/neff
dbr default parameters are from Stephen Lin thesis
https://
Period: 318nm, width: 500nm, dw: 20 ~ 120 nm.
dbr_cell¶
@cell
def dbr_cell(w1: float = w1,
w2: float = w2,
l1: float = period / 2,
l2: float = period / 2,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Distributed Bragg Reflector unit cell.
Arguments:
w1
- thin width in um.l1
- thin length in um.w2
- thick width in um.l2
- thick length in um.n
- number of periods.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
l1 l2 <-----><-------->
_______|
w1 w2
|_________
dbr¶
@cell
def dbr(w1: float = w1,
w2: float = w2,
l1: float = period / 2,
l2: float = period / 2,
n: int = 10,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Distributed Bragg Reflector.
Arguments:
w1
- thin width in um.l1
- thin length in um.w2
- thick width in um.l2
- thick length in um.n
- number of periods.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
l1 l2 <-----><-------->
_______|
w1 w2 ... n times
|_________
gdsfactory.components.taper_parabolic¶
taper_parabolic¶
@gf.cell
def taper_parabolic(length: float = 20,
width1: float = 0.5,
width2: float = 5.0,
exp: float = 0.5,
npoints: int = 100,
layer: LayerSpec = "WG") -> gf.Component
Returns a parabolic_taper.
Arguments:
length
- in um.width1
- in um.width2
- in um.exp
- exponent.npoints
- number of points.layer
- layer spec.
gdsfactory.components.via_stack_slot¶
via_stack_slot¶
@gf.cell
def via_stack_slot(size=(11.0, 11.0),
layers: LayerSpecs = ("M1", "M2"),
layer_offsets: Floats | None = (0, 1.0),
layer_offsetsx: Floats | None = None,
layer_offsetsy: Floats | None = None,
layer_port: LayerSpec | None = None,
via: ComponentSpec = via1,
enclosure: float = 1.0,
ysize: float = 0.5,
yspacing: float = 2.0) -> Component
Rectangular via_stack with slotted via in X direction.
Arguments:
size
- of the layers.layers
- layers on which to draw rectangles.layer_offsets
- cladding_offset for each layer.layer_offsetsx
- optional xoffset for layers, defaults to layer_offsets.layer_offsetsy
- optional yoffset for layers, defaults to layer_offsets.layer_port
- if None assumes port is on the last layer.via
- via to use to fill the rectangles.enclosure
- of the via by rectangle.ysize
- via height in y.yspacing
- via spacing pitch in y... code::
| | | | | layer_offsetsy[1] | | |________ | | |<---> |<>| | |enclosure | layer_offsetsx[1] | | ______________________ | | | | | | | | | | | via | ysize| | | | || | | | | | | | | | | yspacing size[1]| | | | | | | | | | ______________________ | | | | | | | | | | | | | via | ysize| | | | | || | | | | | | | | | | | || | | size[0] | | | |______|
gdsfactory.components.cutback_bend¶
cutback_bend¶
@cell
def cutback_bend(bend90: ComponentSpec = bend_euler,
straight: ComponentSpec = straight,
straight_length: float = 5.0,
rows: int = 6,
columns: int = 5,
**kwargs) -> Component
Deprecated.
Use cutback_bend90 instead with smaller footprint.
Arguments:
bend90
- bend spec.straight
- straight spec.straight_length
- in um.rows
- number of rows.columns
- number of columns.kwargs
- cross_section settings... code::
this is a column _ _| _|
_ this is a row
cutback_bend90¶
@cell
def cutback_bend90(bend90: ComponentSpec = bend_euler,
straight: ComponentSpec = straight,
straight_length: float = 5.0,
rows: int = 6,
columns: int = 6,
spacing: int = 5,
**kwargs) -> Component
Returns bend90 cutback.
Arguments:
bend90
- bend spec.straight
- straight spec.straight_length
- in um.rows
- number of rows.columns
- number of columns.kwargs
- cross_section settings... code::
_ |_| |
staircase¶
@cell
def staircase(bend90: ComponentSpec = bend_euler,
straight: ComponentSpec = straight,
length_v: float = 5.0,
length_h: float = 5.0,
rows: int = 4,
**kwargs) -> Component
Returns staircase.
Arguments:
bend90
- bend spec.straight
- straight spec.length_v
- vertical length.length_h
- vertical length.rows
- number of rows.columns
- number of columns.kwargs
- cross_section settings.
cutback_bend180¶
@cell
def cutback_bend180(bend180: ComponentSpec = bend_euler180,
straight: ComponentSpec = straight,
straight_length: float = 5.0,
rows: int = 6,
columns: int = 6,
spacing: int = 3,
**kwargs) -> Component
Returns cutback to measure u bend loss.
Arguments:
bend180
- bend spec.straight
- straight spec.straight_length
- in um.rows
- number of rows.columns
- number of columns.spacing
- in um.kwargs
- cross_section settings... code::
_ | | this is a row
_ this is a column
gdsfactory.components.straight_pin_slot¶
Straight Doped PIN waveguide.
straight_pin_slot¶
@gf.cell
def straight_pin_slot(length: float = 500.0,
cross_section: CrossSectionSpec = pin,
via_stack: ComponentSpec | None = via_stack_m1_m3,
via_stack_width: float = 10.0,
via_stack_slab: ComponentSpec
| None = via_stack_slot_slab_m1,
via_stack_slab_top: ComponentSpec | None = None,
via_stack_slab_bot: ComponentSpec | None = None,
via_stack_slab_width: float | None = None,
via_stack_spacing: float = 3.0,
via_stack_slab_spacing: float = 2.0,
taper: ComponentSpec | None = taper_strip_to_ridge,
**kwargs) -> Component
Returns a PIN straight waveguide with slotted via.
500um length for PI phase shift
https://
to go beyond 2PI, you will need at least 1mm
https://
Arguments:
length
- of the waveguide.cross_section
- for the waveguide.via_stack
- for via_stacking the metal.via_stack_width
- in um.via_stack_slab
- function for the component via_stacking the slab.via_stack_slab_top
- Optional, defaults to via_stack_slab.via_stack_slab_bot
- Optional, defaults to via_stack_slab.via_stack_slab_width
- defaults to via_stack_width.via_stack_spacing
- spacing between via_stacks.via_stack_slab_spacing
- spacing between via_stacks slabs.taper
- optional taper.kwargs
- cross_section settings.
gdsfactory.components.grating_coupler_rectangular¶
grating_coupler_rectangular¶
@gf.cell
def grating_coupler_rectangular(n_periods: int = 20,
period: float = 0.75,
fill_factor: float = 0.5,
width_grating: float = 11.0,
length_taper: float = 150.0,
polarization: str = "te",
wavelength: float = 1.55,
taper: ComponentSpec = taper_function,
layer_slab: LayerSpec | None = "SLAB150",
fiber_angle: float = 15,
slab_xmin: float = -1.0,
slab_offset: float = 1.0,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Grating coupler with rectangular shapes (not elliptical).
Needs longer taper than elliptical. Grating teeth are straight. For a focusing grating take a look at grating_coupler_elliptical.
Arguments:
n_periods
- number of grating teeth.period
- grating pitch.fill_factor
- ratio of grating width vs gap.width_grating
- 11.length_taper
- 150.polarization
- ‘te’ or ‘tm’.wavelength
- in um.taper
- function.layer_slab
- layer that protects the slab under the grating.fiber_angle
- in degrees.slab_xmin
- where 0 is at the start of the taper.slab_offset
- from edge of grating to edge of the slab.cross_section
- for input waveguide port.kwargs
- cross_section settings... code::
side view fiber
/ / / / / / / /
|-||-||-|__ layer layer_slab | o1 ______________|
top view _________ /| | | | | / | | | | | /taper_angle /_ | | | | | wg_width | | | | | | \ | | | | | \ | | | | | \ | | | | | ||||_| <--> taper_length
gdsfactory.components.rectangle_with_slits¶
rectangle_with_slits¶
@cell
def rectangle_with_slits(size: tuple[float, float] = (100.0, 200.0),
layer: LayerSpec = "WG",
layer_slit: LayerSpec = "SLAB150",
centered: bool = False,
port_type: str | None = None,
slit_size: tuple[float, float] = (1.0, 1.0),
slit_spacing: Float2 = (20, 20),
slit_enclosure: float = 10) -> Component
Returns a rectangle with slits.
Metal slits reduce stress.
Arguments:
size
- (tuple) Width and height of rectangle.layer
- Specific layer to put polygon geometry on.layer_slit
- does a boolean NOT when None.centered
- True sets center to (0, 0), False sets south-west to (0, 0)port_type
- for the rectangle.slit_size
- x, y slit size.slit_spacing
- pitch_x, pitch_y for slits.slit_enclosure
- from slit to rectangle edge... code::
slit_enclosure
|<---> | | | | ______________________ | | | | | | | | slit_size[1] | || | | | | | | slit_spacing | | | | size[1] | | ______________________ | | | | | | | | | | | | | || | | <---------------------> | | slit_size[0] | |___________________________________| size[0]
gdsfactory.components.litho_calipers¶
litho_calipers¶
@cell
def litho_calipers(notch_size: tuple[float, float] = (2.0, 5.0),
notch_spacing: float = 2.0,
num_notches: int = 11,
offset_per_notch: float = 0.1,
row_spacing: float = 0.0,
layer1: LayerSpec = "WG",
layer2: LayerSpec = "SLAB150") -> Component
Vernier caliper structure to test lithography alignment.
Only the middle finger is aligned and the rest are offset.
based on phidl
Arguments:
notch_size
- [xwidth, yheight].notch_spacing
- in um.num_notches
- number of notches.offset_per_notch
- in um.row_spacing
- 0layer1
- layer.layer2
- layer.
gdsfactory.components.array_component¶
array¶
@cell
def array(component: ComponentSpec = "pad",
spacing: tuple[float, float] = (150.0, 150.0),
columns: int = 6,
rows: int = 1,
add_ports: bool = True,
size: Float2 | None = None) -> Component
Returns an array of components.
Arguments:
component
- to replicate.spacing
- x, y spacing.columns
- in x.rows
- in y.add_ports
- add ports from component into the array.size
- Optional x, y size. Overrides columns and rows.
Raises:
ValueError
- If columns > 1 and spacing[0] = 0.ValueError
- If rows > 1 and spacing[1] = 0... code::
2 rows x 4 columns
| | | | | | | | || || || ||
| | | | | | | | || || || ||
gdsfactory.components.mzit¶
mzit¶
@gf.cell
def mzit(w0: float = 0.5,
w1: float = 0.45,
w2: float = 0.55,
dy: float = 2.0,
delta_length: float = 10.0,
length: float = 1.0,
coupler_length1: float = 5.0,
coupler_length2: float = 10.0,
coupler_gap1: float = 0.2,
coupler_gap2: float = 0.3,
taper: ComponentSpec = taper_function,
taper_length: float = 5.0,
bend90: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
coupler1: ComponentSpec | None = coupler_function,
coupler2: ComponentSpec = coupler_function,
**kwargs) -> Component
Mzi tolerant to fabrication variations.
based on Yufei Xing thesis
http://
Arguments:
w1
- narrow waveguide width (um).w2
- wide waveguide width (um).dy
- port to port vertical spacing.delta_length
- length difference between arms (um).length
- shared length for w1 and w2.coupler_length1
- length of coupler1.coupler_length2
- length of coupler2.coupler_gap1
- coupler1.coupler_gap2
- coupler2.taper
- taper spec.taper_length
- from w0 to w1.bend90
- bend spec.straight
- spec.coupler1
- coupler1 spec (optional).coupler2
- coupler2 spec.kwargs
- cross_section settings... code::
cp1 4 2 __ __ 3___w0_t2 w2__ \ /
\ length1 / | ============== gap1 | / \ | __/ ___w0___t1 w1 | 3 1 4 \ | | | 2 2 | | __ w0____t1____w1/ | \ / | \ length2 / | ============== gap2 | / \ | | / \ E0_w0__t2 w1/ 1 1 cp2
gdsfactory.components.disk¶
disk¶
@gf.cell
def disk(radius: float = 10.0,
gap: float = 0.2,
wrap_angle_deg: float = 180.0,
parity: int = 1,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Disk Resonator.
Arguments:
radius
- disk resonator radius.gap
- Distance between the bus straight and resonator.wrap_angle_deg
- Angle in degrees between 0 and 180. determines how much the bus straight wraps along the resonator. 0 corresponds to a straight bus straight. 180 corresponds to a bus straight wrapped around half of the resonator.parity
1 or -1 - 1, resonator left from bus straight, -1 resonator to the right.cross_section
- cross_section spec.kwargs
- cross_section settings.
disk_heater¶
@gf.cell
def disk_heater(radius: float = 10.0,
gap: float = 0.2,
wrap_angle_deg: float = 180.0,
parity: int = 1,
cross_section: CrossSectionSpec = "strip",
heater_layer: LayerSpec = "HEATER",
via_stack: ComponentSpec = "via_stack_heater_mtop",
heater_width: float = 5.0,
heater_extent: float = 2.0,
via_width: float = 10.0,
port_orientation: float | None = 90,
**kwargs) -> Component
Disk Resonator with top metal heater.
Arguments:
radius
- disk resonator radius.gap
- Distance between the bus straight and resonator.wrap_angle_deg
- Angle in degrees between 0 and 180. determines how much the bus straight wraps along the resonator. 0 corresponds to a straight bus straight. 180 corresponds to a bus straight wrapped around half of the resonator.parity
1 or -1 - 1, resonator left from bus straight, -1 resonator to the right.cross_section
- cross_section spec.heater_layer
- layer of the heater.heater_width
- width of the heater.heater_extent
- length of heater beyond disk.via_width
- size of the square via at the end of the heater.port_orientation
- in degrees.kwargs
- cross_section settings.
gdsfactory.components.grating_coupler_elliptical¶
ellipse_arc¶
def ellipse_arc(a: float,
b: float,
x0: float,
theta_min: float,
theta_max: float,
angle_step: float = 0.5) -> ndarray
Returns an elliptical arc.
b = a *sqrt(1-e**2)
An ellipse with a = b has zero eccentricity (is a circle)
Arguments:
a
- ellipse semi-major axis.b
- semi-minor axis.x0
- in um.theta_min
- in rad.theta_max
- in rad.angle_step
- in rad.
grating_coupler_elliptical¶
@gf.cell
def grating_coupler_elliptical(polarization: str = "te",
taper_length: float = 16.6,
taper_angle: float = 40.0,
wavelength: float = 1.554,
fiber_angle: float = 15.0,
grating_line_width: float = 0.343,
neff: float = 2.638,
nclad: float = 1.443,
n_periods: int = 30,
big_last_tooth: bool = False,
layer_slab: LayerSpec | None = "SLAB150",
slab_xmin: float = -1.0,
slab_offset: float = 2.0,
spiked: bool = True,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Grating coupler with parametrization based on Lumerical FDTD simulation.
Arguments:
polarization
- te or tm.taper_length
- taper length from input.taper_angle
- grating flare angle.wavelength
- grating transmission central wavelength (um).fiber_angle
- fibre angle in degrees determines ellipticity.grating_line_width
- in um.neff
- tooth effective index.nclad
- cladding effective index.n_periods
- number of periods.big_last_tooth
- adds a big_last_tooth.layer_slab
- layer that protects the slab under the grating.slab_xmin
- where 0 is at the start of the taper.slab_offset
- in um.spiked
- grating teeth have sharp spikes to avoid non-manhattan drc errors.cross_section
- specification (CrossSection, string or dict).kwargs
- cross_section settings... code::
fiber
/ / / / / / / /
|-||-||-|__ layer layer_slab | o1 ______________|
gdsfactory.components.greek_cross¶
Greek cross test structure.
greek_cross¶
@gf.cell
def greek_cross(length: float = 30,
layers: LayerSpecs = (
"WG",
"N",
),
widths: Floats = (2.0, 3.0),
offsets: Floats | None = None,
via_stack: ComponentSpec = via_stack_npp_m1) -> gf.Component
Simple greek cross with via stacks at the endpoints.
Process control monitor for dopant sheet resistivity and linewidth variation.
Arguments:
length
- length of cross arms.layers
- list of layers.widths
- list of widths (same order as layers).offsets
- how much to extend each layer beyond the cross length negative shorter, positive longer.via
- via component to attach to the cross... code::
via_stack <-------> _________ length ________ | |<-------------------->| 2x | | | ↓ |<-->| | |======== width =======| |_______|<--> | ↑ |<-->|________ offset offset
References:
- Walton, Anthony J.. “MICROELECTRONIC TEST STRUCTURES.” (1999).
- W. Versnel, Analysis of the Greek cross, a Van der Pauw structure with finite contacts, Solid-State Electronics, Volume 22, Issue 11, 1979, Pages 911-914, ISSN 0038-1101, Versnel (1979).
- S. Enderling et al., “Sheet resistance measurement of non-standard cleanroom materials using suspended Greek cross test structures,” IEEE Transactions on Semiconductor Manufacturing, vol. 19, no. 1, pp. 2-9, Feb. 2006,
doi
- 10.1109/TSM.2005.863248.
greek_cross_with_pads¶
@gf.cell
def greek_cross_with_pads(pad: ComponentSpec = pad,
pad_spacing: float = 150.0,
greek_cross_component: ComponentSpec = greek_cross,
pad_via: ComponentSpec = via_stack_m1_m3,
xs_metal: CrossSectionSpec = metal1) -> gf.Component
Greek cross under 4 DC pads, ready to test.
Arguments:
pad
- component to use for probe padspad_spacing
- spacing between padsgreek_cross_component
- component to use for greek crosspad_via
- via to add to the padxs_metal
- cross-section for cross via to pad via wiring
greek_cross_offset_pads¶
@gf.cell
def greek_cross_offset_pads(cross_struct_length: float = 30.0,
cross_struct_width: float = 1.0,
cross_struct_layers: LayerSpecs = ("WG", ),
cross_implant_length: float = 30.0,
cross_implant_width: float = 2.0,
cross_implant_layers: LayerSpecs = ("N", ),
contact_layers: LayerSpecs = ("WG", "NPP"),
contact_offset: float = 10,
contact_buffer: float = 10,
pad_width: float = 50) -> gf.Component
Greek cross, with silicon islands on each side of the cross to place larger contacting regions.
Arguments:
cross_struct_length
- length of structural part of cross e.g. silicon core.cross_struct_width
- width of structural part of cross e.g. silicon core.cross_struct_layers
- layers to be considered “structural”.cross_implant_length
- length of implantation part of cross.cross_implant_width
- width of implantation part of cross.cross_implant_layers
- layers to be considered “implants”.contact_layers
- layers to include under and around the pad.contact_offset
- fudge factor to move pad relative to cross.contact_buffer
- amount of dopants around pad in contact.pad_width
- pad size... code::
pad_width <-------> _________ cross_implant_length, cross_struct_length | |<-------> 4x | | ↓ | |======== cross_implant_width, cross_struct_width |_______| ↑ <--------------> contact_offset (fudge)
References:
- Walton, Anthony J.. “MICROELECTRONIC TEST STRUCTURES.” (1999).
- W. Versnel, Analysis of the Greek cross, a Van der Pauw structure with finite contacts, Solid-State Electronics, Volume 22, Issue 11, 1979, Pages 911-914, ISSN 0038-1101, Versnel (1979).
- S. Enderling et al., “Sheet resistance measurement of non-standard cleanroom materials using suspended Greek cross test structures,” IEEE Transactions on Semiconductor Manufacturing, vol. 19, no. 1, pp. 2-9, Feb. 2006,
doi
- 10.1109/TSM.2005.863248.
gdsfactory.components.splitter_tree¶
splitter_tree¶
@gf.cell
def splitter_tree(coupler: ComponentSpec = mmi1x2,
noutputs: int = 4,
spacing: Float2 = (90.0, 50.0),
bend_s: ComponentSpec | None = bend_s_function,
bend_s_xsize: float | None = None,
cross_section: CrossSectionSpec = "strip") -> gf.Component
Tree of power splitters.
Arguments:
coupler
- coupler factory.noutputs
- number of outputs.spacing
- x, y spacing between couplers.bend_s
- Sbend function for termination.bend_s_xsize
- xsize for the sbend.cross_section
- cross_section... code::
| | | | | |_ dy
dx
gdsfactory.components.regular_polygon¶
regular_polygon¶
@cell
def regular_polygon(sides: int = 6,
side_length: float = 10,
layer: LayerSpec = "WG",
port_type: str | None = "placement") -> Component
Returns a regular N-sided polygon, with ports on each edge.
Arguments:
sides
- number of sides for the polygon.side_length
- of the edges.layer
- Specific layer to put polygon geometry on.port_type
- optical, electrical.
gdsfactory.components.component_lattice_generic¶
In a multiple-topology Clements Scheme we can implement any universal photonic function.
component_lattice_generic¶
@cell
def component_lattice_generic(network: list[list] | None = None) -> Component
The shape of the network
matrix determines the physical interconnection.
Note that there should be at least S+1=N modes
based on this formalism of interconnection,
and the position of the component implements a connectivity in between the modes,
and assumes a 2x2 network encoding.
One nice functionality by this component is that it can generate a
component lattice for generic variable components with different x and y pitches.
Initially this will maximise the surface area required
but different placement algorithms can compact the size.
Arguments:
network
- A list of lists of components that are to be placed in the lattice.
Returns:
Component
- A component lattice that implements the physical network.The placement matrix is in this form: .. math::
M = X & 0 & X 0 & P & 0 X & 0 & X
:include-source: import gdsfactory as gf from gdsfactory.components.mzi import mzi2x2_2x2
example_component_lattice = [ [mzi2x2_2x2(), 0, mzi2x2_2x2()], [0, mzi2x2_2x2(delta_length=30.0), 0], [mzi2x2_2x2(), 0, mzi2x2_2x2()], ] c = gf.components.component_lattice_generic(example_component_lattice)
Another example that demonstrates the generic-nature of this component lattice algorithm can be with an mixed set of actively driven and passiver interferometers. The placement matrix is in this form:
.. math::
M = Y & 0 & A 0 & B & 0 C & 0 & Y
:include-source: import gdsfactory as gf from gdsfactory.components import mzi2x2_2x2_phase_shifter, mzi2x2_2x2
example_mixed_component_lattice = [ [mzi2x2_2x2_phase_shifter(), 0, mzi2x2_2x2(delta_length=20.0)], [0, mzi2x2_2x2(delta_length=30.0), 0], [mzi2x2_2x2(delta_length=15.0), 0, mzi2x2_2x2_phase_shifter()], ] c = gf.components.component_lattice_generic( network=example_mixed_component_lattice )
TODO implement balanced waveguide paths function per stage¶
TODO automatic electrical fanout?¶
TODO multiple placement optimization algorithms.¶
gdsfactory.components.bbox¶
bbox¶
@gf.cell_without_validator
def bbox(bbox: tuple[Coordinate, Coordinate] = ((-1.0, -1.0), (3.0, 4.0)),
layer: tuple[int, int] = (1, 0),
top: float = 0,
bottom: float = 0,
left: float = 0,
right: float = 0) -> gf.Component
Returns bounding box rectangle from coordinates.
Arguments:
bbox
- Coordinates of the box [(x1, y1), (x2, y2)].layer
- for bbox.top
- north offset.bottom
- south offset.left
- west offset.right
- east offset.
gdsfactory.components.wafer¶
wafer¶
@gf.cell
def wafer(reticle: ComponentFactory = die,
cols: tuple[int, ...] = _cols_200mm_wafer,
xspacing: float | None = None,
yspacing: float | None = None,
die_name_col_row: bool = False) -> Component
Returns complete wafer. Useful for mask aligner steps.
Arguments:
reticle
- spec for each wafer reticle.cols
- how many columns per row.xspacing
- optional spacing, defaults to reticle.xsize.yspacing
- optional spacing, defaults to reticle.ysize.die_name_col_row
- if True, die name is row_col, otherwise is a number
gdsfactory.components.hline¶
hline¶
@gf.cell
def hline(length: float = 10.0,
width: float = 0.5,
layer: LayerSpec = "WG",
port_type: str = "optical") -> Component
Horizontal line straight, with ports on east and west sides.
gdsfactory.components.via_stack¶
via_stack¶
@gf.cell
def via_stack(size=(11.0, 11.0),
layers: LayerSpecs = ("M1", "M2", "M3"),
layer_offsets: Floats | None = None,
vias: tuple[ComponentSpec | None, ...] | None = (via1, via2,
None),
layer_port: LayerSpec | None = None,
correct_size: bool = True) -> Component
Rectangular via array stack.
You can use it to connect different metal layers or metals to silicon. You can use the naming convention via_stack_layerSource_layerDestination contains 4 ports (e1, e2, e3, e4)
also know as Via array
http://
spacing = via.info[‘spacing’] enclosure = via.info[‘enclosure’]
Arguments:
size
- of the layers.layers
- layers on which to draw rectangles.layer_offsets
- Optional offsets for each layer with respect to size. positive grows, negative shrinks the size.vias
- vias to use to fill the rectangles.layer_port
- if None assumes port is on the last layer.correct_size
- if True, if the specified dimensions are too small it increases them to the minimum possible to fit a via.
via_stack_circular¶
@gf.cell
def via_stack_circular(radius: float = 10.0,
angular_extent: float = 45,
center_angle: float = 0,
width: float = 5.0,
layers: LayerSpecs = ("M1", "M2", "M3"),
vias: tuple[ComponentSpec | None, ...] = (via1, via2),
layer_port: LayerSpec | None = None) -> Component
Circular via array stack.
FIXME! does not work.
Constructs a circular via array stack. It does so by stacking rectangular via stacks offset by a small amount along the specified circumference.
Arguments:
radius
- of the via stack (center).angular_extent
- of the via stack.center_angle
- of the via stack.width
- of the via stack.layers
- layers to drawvias
- vias to use to fill the rectangles.layer_port
- if None assumes port is on the last layer.
via_stack_from_rules¶
@gf.cell
def via_stack_from_rules(size: Float2 = (1.2, 1.2),
layers: LayerSpecs = ("M1", "M2", "M3"),
layer_offsets: tuple[float, ...] | None = None,
vias: tuple[ComponentSpec | None, ...]
| None = (via1, via2),
via_min_size: tuple[Float2,
...] = ((0.2, 0.2), (0.2, 0.2)),
via_min_gap: tuple[Float2,
...] = ((0.1, 0.1), (0.1, 0.1)),
via_min_enclosure: Float2 = (0.15, 0.25),
layer_port: LayerSpec | None = None) -> Component
Rectangular via array stack, with optimized dimension for vias.
Uses inclusion, minimum width, and minimum spacing rules to place the maximum number of individual vias, each with maximum via area.
Arguments:
size
- of the layers, len(size).layers
- layers on which to draw rectangles.layer_offsets
- Optional offsets for each layer with respect to size. positive grows, negative shrinks the size.vias
- list of base via components to modify.via_min_size
- via minimum x, y dimensions.via_min_gap
- via minimum x, y distances.via_min_enclosure
- via minimum inclusion into connecting layers.layer_port
- if None assumes port is on the last layer.
optimized_via¶
def optimized_via(base_via: ComponentSpec = "VIAC",
size: tuple[float, float] = (11.0, 11.0),
min_via_size: tuple[float, float] = (0.3, 0.3),
min_via_gap: tuple[float, float] = (0.1, 0.1),
min_via_enclosure: float = 0.2) -> Component
Given a target total inclusion size, returns an optimized dimension for the via.
Uses inclusion, minimum width, and minimum spacing rules to place the maximum number of individual vias, with maximum via area.
Arguments:
base_via
- to modify.size
- of the target enclosing medium.min_via_size
- minimum size the vias can take.min_via_gap
- minimum distance between vias.min_via_enclosure
- minimum distance between edge of enclosing medium and nearest via edge.
gdsfactory.components.resistance_meander¶
resistance_meander¶
@cell
def resistance_meander(pad_size: tuple[float, float] = (50.0, 50.0),
num_squares: int = 1000,
width: float = 1.0,
res_layer: LayerSpec = "MTOP",
pad_layer: LayerSpec = "MTOP",
gnd_layer: LayerSpec = "MTOP") -> Component
Return meander to test resistance.
based on phidl.geometry
Arguments:
pad_size
- Size of the two matched impedance pads (microns).num_squares
- Number of squares comprising the resonator wire.width
- The width of the squares (microns).res_layer
- resistance layer.pad_layer
- pad layer.gnd_layer
- ground layer.
gdsfactory.components.taper_cross_section¶
taper_cross_section¶
@cell
def taper_cross_section(cross_section1: CrossSectionSpec = strip_rib_tip,
cross_section2: CrossSectionSpec = rib_conformal,
length: float = 10,
npoints: int = 100,
linear: bool = False,
width_type: str = "sine",
**kwargs) -> Component
Returns taper transition between cross_section1 and cross_section2.
Arguments:
cross_section1
- start cross_section factory.cross_section2
- end cross_section factory.length
- transition length.npoints
- number of points.linear
- shape of the transition, sine when False.width_type
- shape of the transition ONLY IF linear is Falsekwargs
- cross_section settings for section2... code::
/ /_______________ / cross_section1 | cross_section2 _________________
_____________________
gdsfactory.components.mmi2x2_with_sbend¶
mmi2x2_with_sbend¶
@gf.cell
def mmi2x2_with_sbend(with_sbend: bool = True,
s_bend: ComponentSpec = bend_s,
cross_section: CrossSectionSpec = "strip") -> Component
Returns mmi2x2 for Cband.
C_band 2x2MMI in 220nm thick silicon
https://
Arguments:
with_sbend
- add sbend.s_bend
- S-bend spec.cross_section
- spec.
gdsfactory.components.mmi2x2¶
mmi2x2¶
@gf.cell
def mmi2x2(width: float | None = None,
width_taper: float = 1.0,
length_taper: float = 10.0,
length_mmi: float = 5.5,
width_mmi: float = 2.5,
gap_mmi: float = 0.25,
taper: ComponentFactory = taper_function,
straight: ComponentFactory = straight_function,
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip") -> Component
Mmi 2x2.
Arguments:
width
- input and output straight 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
- (width_taper + gap between tapered wg)/2.taper
- taper function.straight
- straight function.with_bbox
- box in bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- spec... code::
length_mmi <------>
| | / _ o2 __ __ o3 \ / _ _ _ | | _ _ _ _| gap_mmi / _ o1 __ __ o4 \ / |_______|
<-> length_taper
gdsfactory.components.spiral_double¶
spiral_double¶
@gf.cell
def spiral_double(
min_bend_radius: float = 10.0,
separation: float = 2.0,
number_of_loops: float = 3,
npoints: int = 1000,
cross_section: gf.typings.CrossSectionSpec = "strip",
bend: gf.typings.ComponentSpec = bend_circular) -> gf.Component
Returns a spiral double (spiral in, and then out).
Arguments:
min_bend_radius
- inner radius of the spiral.separation
- separation between the loops.number_of_loops
- number of loops per spiral.npoints
- points for the spiral.cross_section
- cross-section to extrude the structure with.bend
- factory for the bends in the middle of the double spiral.
gdsfactory.components.fiber_array¶
fiber_array¶
@gf.cell
def fiber_array(n: int = 8,
pitch: float = 127.0,
core_diameter: float = 10,
cladding_diameter: float = 125,
layer_core: LayerSpec = "WG",
layer_cladding: LayerSpec = "WGCLAD") -> Component
Returns a fiber array.
Arguments:
n
- number of fibers.pitch
- spacing.core_diameter
- 10um.cladding_diameter
- in um.layer_core
- layer spec for fiber core.layer_cladding
- layer spec for fiber cladding... code::
pitch <->
| | lid | o o o o | | | base |_________| length
gdsfactory.components.via_corner¶
via_corner¶
@gf.cell
def via_corner(cross_section: MultiCrossSectionAngleSpec = (
(metal2, (0, 180)),
(metal3, (90, 270)),
),
vias: tuple[ComponentSpec] = (via1, ),
layers_labels: tuple[str, ...] = ("m2", "m3"),
**kwargs) -> gf.Component
Returns Corner via.
Use in place of wire_corner to route between two layers.
Arguments:
cross_section
- list of cross_section, orientation pairs.vias
- vias to use to fill the rectangles.layers_labels
- Labels to use for each layer.kwargs
- cross_section settings.
gdsfactory.components.pad¶
pad¶
@cell
def pad(size: str | Float2 = (100.0, 100.0),
layer: LayerSpec = "MTOP",
bbox_layers: tuple[LayerSpec, ...] | None = None,
bbox_offsets: tuple[float, ...] | None = None,
port_inclusion: float = 0,
port_orientation: float | None = None) -> Component
Returns rectangular pad with ports.
Arguments:
size
- x, y size.layer
- pad layer.bbox_layers
- list of layers.bbox_offsets
- Optional offsets for each layer with respect to size. positive grows, negative shrinks the size.port_inclusion
- from edge.port_orientation
- in degrees.
pad_array¶
@cell
def pad_array(pad: ComponentSpec = "pad",
spacing: tuple[float, float] = (150.0, 150.0),
columns: int = 6,
rows: int = 1,
orientation: float | None = 270) -> Component
Returns 2D array of pads.
Arguments:
pad
- pad element.spacing
- x, y pitch.columns
- number of columns.rows
- number of rows.orientation
- port orientation in deg. None for low speed DC ports.
gdsfactory.components.ge_detector_straight_si_contacts¶
Straight Ge photodetector.
ge_detector_straight_si_contacts¶
@gf.cell
def ge_detector_straight_si_contacts(
length: float = 80.0,
cross_section: CrossSectionSpec = pn_ge_detector_si_contacts,
via_stack: ComponentSpec
| tuple[ComponentSpec, ComponentSpec] = via_stack_slab_m3,
via_stack_width: float = 10.0,
via_stack_spacing: float = 5.0,
via_stack_offset: float = 0.0,
taper: ComponentSpec | None = default_taper,
**kwargs) -> Component
Returns a straight Ge on Si detector with silicon contacts.
There are no contacts on the Ge. These detectors could have lower dark current and sensitivity compared to those with contacts in the Ge. See Chen et al., “High-Responsivity Low-Voltage 28-Gb/s Ge p-i-n Photodetector With Silicon Contacts”, Journal of Lightwave Technology 33(4), 2015.
Arguments:
length
- total length of the waveguide including the tapers.cross_section
- for the waveguide.via_stack
- for the via_stacks. First elementvia_stack_width
- width of the via_stack.via_stack_spacing
- spacing between via_stacks.via_stack_offset
- with respect to the detectortaper
- optional taper to transition from the input waveguide into the absorption region.kwargs
- cross_section settings.
gdsfactory.components.mzi¶
mzi¶
@cell
def mzi(delta_length: float = 10.0,
length_y: float = 2.0,
length_x: float | None = 0.1,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
straight_y: ComponentSpec | None = None,
straight_x_top: ComponentSpec | None = None,
straight_x_bot: ComponentSpec | None = None,
splitter: ComponentSpec = "mmi1x2",
combiner: ComponentSpec | None = None,
with_splitter: bool = True,
port_e1_splitter: str = "o2",
port_e0_splitter: str = "o3",
port_e1_combiner: str = "o2",
port_e0_combiner: str = "o3",
nbends: int = 2,
cross_section: CrossSectionSpec = "strip",
cross_section_x_top: CrossSectionSpec | None = None,
cross_section_x_bot: CrossSectionSpec | None = None,
mirror_bot: bool = False,
add_optical_ports_arms: bool = False) -> Component
Mzi.
Arguments:
delta_length
- bottom arm vertical extra length.length_y
- vertical length for both and top arms.length_x
- horizontal length. None uses to the straight_x_bot/top defaults.bend
- 90 degrees bend library.straight
- straight function.straight_y
- straight for length_y and delta_length.straight_x_top
- top straight for length_x.straight_x_bot
- bottom straight for length_x.splitter
- splitter function.combiner
- combiner function.with_splitter
- if False removes splitter.port_e1_splitter
- east top splitter port.port_e0_splitter
- east bot splitter port.port_e1_combiner
- east top combiner port.port_e0_combiner
- east bot combiner port.nbends
- from straight top/bot to combiner (at least 2).cross_section
- for routing (sxtop/sxbot to combiner).cross_section_x_top
- optional top cross_section (defaults to cross_section).cross_section_x_bot
- optional bottom cross_section (defaults to cross_section).mirror_bot
- if true, mirrors the bottom arm.add_optical_ports_arms
- add all other optical ports in the arms with top_ and bot_ prefix... code::
b2______b3 | sxtop | straight_y | | | b1 b4 splitter==| |==combiner b5 b8 | | straight_y | | | delta_length/2 | | | b6__sxbot__b7 Lx
gdsfactory.components.optimal_90deg¶
optimal_90deg¶
@cell
def optimal_90deg(
width: float = 100,
num_pts: int = 15,
length_adjust: float = 1,
layer: LayerSpec = (1, 0)) -> Component
Returns optimally-rounded 90 degree bend that is sharp on the outer corner.
Arguments:
width
- Width of the ports on either side of the bend.num_pts
- The number of points comprising the curved section of the bend.length_adjust
- Adjusts the length of the non-curved portion of the bend.layer
- Specific layer(s) to put polygon geometry on.
Notes:
Optimal structure from Clem & Berggren (2011) Clem, J., & Berggren, K. (2011). Geometry-dependent critical currents in superconducting nanocircuits. Physical Review B, 84(17), 1–27.
gdsfactory.components.switch_tree¶
Returns a switch_tree.
__
_| |_
__ | | |_ _ | || || | | |_ |dy || | __ | || | | | |_ - ||
|<-dx->|
gdsfactory.components.bend_euler¶
bend_euler¶
@gf.cell
def bend_euler(angle: float = 90.0,
p: float = 0.5,
with_arc_floorplan: bool = True,
npoints: int | None = None,
direction: str = "ccw",
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Euler bend with changing bend radius.
By default, radius
corresponds to the minimum radius of curvature of the bend.
However, if with_arc_floorplan
is True, radius
corresponds to the effective
radius of curvature (making the curve a drop-in replacement for an arc). If
p < 1.0, will create a “partial euler” curve as described in Vogelbacher et.
al. Vogelbacher et al. (2019)
default p = 0.5 based on this paper
https://
Arguments:
angle
- total angle of the curve.p
- Proportion of the curve that is an Euler curve.with_arc_floorplan
- If False:radius
is the minimum radius of curvature If True: The curve scales such that the endpoints match a bend_circular with parametersradius
andangle
.npoints
- Number of points used per 360 degrees.direction
- cw (clock-wise) or ccw (counter clock-wise).with_bbox
- add bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- specification (CrossSection, string, CrossSectionFactory dict).kwargs
- cross_section settings... code::
o2 | / / / o1_____/
bend_euler_s¶
@gf.cell
def bend_euler_s(**kwargs) -> Component
Sbend made of 2 euler bends.
Arguments:
angle
- total angle of the curve.p
- Proportion of the curve that is an Euler curve.with_arc_floorplan
- If False:radius
is the minimum radius of curvature If True: The curve scales such that the endpoints match a bend_circular with parametersradius
andangle
.npoints
- Number of points used per 360 degrees.direction
- cw (clock-wise) or ccw (counter clock-wise).with_bbox
- add bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- specification (CrossSection, string, CrossSectionFactory dict).kwargs
- cross_section settings... code::
_____ o2 / / / / | / / / o1_____/
bend_straight_bend¶
@gf.cell
def bend_straight_bend(straight_length: float = 10.0,
angle: float = 90,
p: float = 0.5,
with_arc_floorplan: bool = True,
npoints: int = 720,
direction: str = "ccw",
cross_section: CrossSectionSpec = strip,
**kwargs) -> Component
Sbend made of 2 euler bends and straight section in between.
Arguments:
straight_length
- in um.angle
- total angle of the curve.p
- Proportion of the curve that is an Euler curve.with_arc_floorplan
- If False:radius
is the minimum radius of curvature If True: The curve scales such that the endpoints match a bend_circular with parametersradius
andangle
.npoints
- Number of points used per 360 degrees.direction
- cw (clock-wise) or ccw (counter clock-wise).cross_section
- specification (CrossSection, string, CrossSectionFactory dict).kwargs
- cross_section settings.
gdsfactory.components.polarization_splitter_rotator¶
polarization_splitter_rotator¶
@gf.cell
def polarization_splitter_rotator(width_taper_in: Float3 = (0.54, 0.69, 0.83),
length_taper_in: Float2 | Float3 = (4.0,
44.0),
width_coupler: Float2 = (0.9, 0.405),
length_coupler: float = 7.0,
gap: float = 0.15,
width_out: float = 0.54,
length_out: float = 14.33,
dy: float = 5.0,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns polarization splitter rotator
“Novel concept for ultracompact polarization splitter-rotator based on silicon nanowires.” By D. Dai, and J. E. Bowers (Optics express vol 19, no. 11 pp. 10940-10949 (2011)).
Arguments:
width_taper_in
- Three west widths of the input tapers in um.length_taper_in
- Two or three length of the bend regions in um.width_coupler
- Top and bottom widths of the coupling region in um.length_coupler
- Length of the coupling region in um.gap
- Distance between the coupler in um.width_out
- Width of the splitter region in um.length_out
- Length of the splitter region in um.dy
- Port-to-port distance between the splitter region in um.cross_section
- cross-section spec.
Arguments:
cross_section kwargs.
Notes:
The length of third input taper is automatically determined if only two lengths are in arguments.
gdsfactory.components.die_bbox_frame¶
die_bbox_frame¶
@gf.cell_without_validator
def die_bbox_frame(bbox: tuple[Coordinate,
Coordinate] = ((-1.0, -1.0), (3.0, 4.0)),
street_width: float = 100.0,
street_length: float = 1000.0,
die_name: str | None = None,
text_size: float = 100.0,
text_anchor: Anchor = "sw",
layer: LayerSpec = "M3",
padding: float = 10.0) -> gf.Component
Return boundary box frame.
The chip/die boundary can include a label with the name of the die.
Arguments:
bbox
- bounding box to frame.street_width
- Width of the boundary box.street_length
- length of the boundary box.die_name
- Label text.text_size
- Label text size.text_anchor
- {‘nw’, ‘nc’, ‘ne’, ‘sw’, ‘sc’, ‘se’} text location.layer
- Specific layer(s) to put polygon geometry on.padding
- adds padding.
gdsfactory.components.delay_snake¶
delay_snake¶
@gf.cell
def delay_snake(length: float = 1600.0,
L0: float = 5.0,
n: int = 2,
bend: ComponentSpec = "bend_euler",
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns Snake with a starting straight and 90 bends.
Input faces west output faces east.
Arguments:
length
- delay length in um.L0
- initial xoffset in um.n
- number of loops.bend
- bend spec.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
| L0 | L2 |
->-------------|
pi * radius -------------------> | DL |
gdsfactory.components.coh_tx_single_pol¶
coh_tx_single_pol¶
@cell
def coh_tx_single_pol(balanced_phase_shifters: bool = False,
mzm_y_spacing: float = 50.0,
phase_shifter: ComponentSpec = "straight_pin",
phase_shifter_length: float = 100.0,
mzm_ps_spacing: float = 40.0,
splitter: ComponentSpec = "mmi1x2",
combiner: ComponentSpec | None = None,
mzm: ComponentSpec = default_mzm,
mzm_length: float = 200.0,
with_pads: bool = False,
xspacing: float = 40.0,
input_coupler: ComponentSpec | None = None,
output_coupler: ComponentSpec | None = None,
pad_array: ComponentSpec = "pad_array",
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
MZM-based single polarization coherent transmitter.
Arguments:
balanced_phase_shifters
- True adds phase sifters after the MZM at both the I and Q arms. False, only adds Q arm has a phase shifter.mzm_y_spacing
- vertical spacing between the bottom of the I MZM and the top of the Q MZM.phase_shifter
- phase_shifter spec.phase_shifter_length
- length of the phase shifter.mzm_ps_spacing
- spacing between the end of the mzm and the phase shifter.splitter
- splitter spec.combiner
- combiner spec.mzm
- Mach-Zehnder modulator spec.mzm_length
- length of the MZMs.xspacing
- horizontal spacing between the splitter and combiner and the mzm.input_coupler
- Optional coupler to add before the splitter.output_coupler
- Optional coupler to add after the combiner.pad_array
- array of pads spec.cross_section
- for routing (splitter to mzms and mzms to combiners).kwargs
- cross_section settings... code::
___ mzm_i __ ps_i__ | | | | | | (in_coupler)---splitter==| |==combiner---(out_coupler) | | | | |___ mzm_q __ ps_q_|
gdsfactory.components.grating_coupler_loss_fiber_single¶
grating_coupler_loss_fiber_single¶
@cell
def grating_coupler_loss_fiber_single(
grating_coupler: ComponentSpec = grating_coupler_te,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns grating coupler test structure.
for testing with single fiber input/output
Arguments:
grating_coupler
- function.cross_section
- spec.
Arguments:
layer_label
- for test and measurement label.min_input_to_output_spacing
- spacing from input to output fiber.max_y0_optical
- None.get_input_labels_function
- function to get input labels for grating couplers.optical_routing_type
- None: autoselection, 0: no extension.get_input_label_text_function
- for the grating couplers input label.get_input_label_text_loopback_function
- for the loopbacks input label.
gdsfactory.components.litho_steps¶
litho_steps¶
@gf.cell
def litho_steps(line_widths: tuple[float, ...] = (1.0, 2.0, 4.0, 8.0, 16.0),
line_spacing: float = 10.0,
height: float = 100.0,
layer: LayerSpec = "WG") -> Component
Positive + negative tone linewidth test.
used for lithography resolution test patterning based on phidl
Arguments:
line_widths
- in um.line_spacing
- in um.height
- in um.layer
- Specific layer to put the ruler geometry on.
gdsfactory.components.rectangle¶
rectangle¶
@cell
def rectangle(
size=(4.0, 2.0),
layer: LayerSpec = "WG",
centered: bool = False,
port_type: str | None = "electrical",
port_orientations: Ints | None = (180, 90, 0, -90)
) -> Component
Returns a rectangle.
Arguments:
size
- (tuple) Width and height of rectangle.layer
- Specific layer to put polygon geometry on.centered
- True sets center to (0, 0), False sets south-west to (0, 0).port_type
- optical, electrical.port_orientations
- list of port_orientations to add.
rectangles¶
@cell
def rectangles(size=(4.0, 2.0),
offsets=(0, 1),
layers=("WG", "SLAB150"),
centered: bool = True,
**kwargs) -> Component
Returns overimposed rectangles.
Arguments:
size
- (tuple) Width and height of rectangle.layers
- Specific layer to put polygon geometry on.offsets
- list of offsets.centered
- True sets center to (0, 0), False sets south-west of first rectangle to (0, 0).
Arguments:
port_type
- optical, electrical.port_orientations
- list of port_orientations to add... code::
┌──────────────┐ │ │ │ ┌──────┐ │ │ │ │ │ │ │ ├───► │ │ │offset │ └──────┘ │ │ │ └──────────────┘
gdsfactory.components.straight_heater_doped_rib¶
straight_heater_doped_rib¶
@gf.cell
def straight_heater_doped_rib(
length: float = 320.0,
nsections: int = 3,
cross_section: CrossSectionSpec = strip_rib_tip,
cross_section_heater: CrossSectionSpec = rib_heater_doped,
via_stack: ComponentSpec | None = via_stack_slab_npp_m3,
via_stack_metal: ComponentSpec | None = via_stack_metal_function,
via_stack_metal_size: tuple[float, float] = (10.0, 10.0),
via_stack_size: tuple[float, float] = (10.0, 10.0),
taper: ComponentSpec | None = taper_cross_section,
with_taper1: bool = True,
with_taper2: bool = True,
heater_width: float = 2.0,
heater_gap: float = 0.8,
via_stack_gap: float = 0.0,
width: float = 0.5,
xoffset_tip1: float = 0.2,
xoffset_tip2: float = 0.4,
**kwargs) -> Component
Returns a doped thermal phase shifter.
dimensions from Jacques et al. (2019)
Arguments:
length
- of the waveguide in um.nsections
- between via_stacks.cross_section
- for the input/output ports.cross_section_heater
- for the heater.via_stack
- optional function to connect the heater strip.via_stack_metal
- function to connect the metal area.via_stack_metal_size
- x, y size in um.via_stack_size
- x, y size in um.taper
- optional taper spec.heater_width
- in um.heater_gap
- in um.via_stack_gap
- from edge of via_stack to waveguide.width
- waveguide width on the ridge.xoffset_tip1
- distance in um from input taper to via_stack.xoffset_tip2
- distance in um from output taper to via_stack.kwargs
- cross_section settings... code::
length |<--------------------------------------------->| | length_section | | <---------------------------> | | length_via_stack | | <-------> taper| | __________ _________ | | | | | | | | | via_stack|| | | | | size | heater width | | | | /||||\ | | / | heater_gap | \ | |/ |________________| \ | \ |width| / \ | | / |heater_gap |/ | | | | | |heater_width| | | | | | || ||
taper cross_section_heater
|<------width------>| ____________________ heater_gap slab_gap top_via_stack | |<---------->| bot_via_stack <--> ___ | || | | | undoped Si | | | | |layer_heater| intrinsic region |layer_heater | | |||______________||| <------------> heater_width <------------------------------------------------------------------------------> slab_width
gdsfactory.components.mmi1x2¶
mmi1x2¶
@gf.cell
def mmi1x2(width: float | None = None,
width_taper: float = 1.0,
length_taper: float = 10.0,
length_mmi: float = 5.5,
width_mmi: float = 2.5,
gap_mmi: float = 0.25,
taper: ComponentFactory = taper_function,
straight: ComponentFactory = straight_function,
with_bbox: bool = True,
cross_section: CrossSectionSpec = "strip") -> Component
1x2 MultiMode Interferometer (MMI).
Arguments:
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.with_bbox
- add rectangular box in cross_section bbox_layers and bbox_offsets to avoid DRC sharp edges.cross_section
- specification (CrossSection, string or dict)... code::
length_mmi <------>
| | | __ | __ o2 / / _ _ _ o1 __ | _ _ _ | gap_mmi \ _ | __ o3 | / |_______|
<-> length_taper
gdsfactory.components.rectangular_ring¶
rectangular_ring¶
@gf.cell
def rectangular_ring(enclosed_size=(4.0, 2.0),
width: float = 0.5,
layer: LayerSpec = "WG",
centered: bool = False) -> Component
Returns a Rectangular Ring
Arguments:
enclosed_size
- (width, height) of the enclosed area.width
- width of the ring.layer
- Specific layer to put polygon geometry on.centered
- True sets center to (0,0), False sets south-west to (0,0).
gdsfactory.components.pad_gsg¶
High speed GSG pads.
pad_gsg_short¶
@gf.cell
def pad_gsg_short(via_stack: ComponentSpec = rectangle_m3,
size: Float2 = (22, 7),
layer_metal: LayerSpec = "M3",
metal_spacing: float = 5.0,
short: bool = True,
pad: ComponentSpec = pad_function,
pad_spacing: float = 150) -> gf.Component
Returns high speed GSG pads for calibrating the RF probes.
Arguments:
via_stack
- where the RF pads connect to.size
- for the via_stack.layer_metal
- for the short.metal_spacing
- in um.short
- if False returns an open.pad
- function for pad.pad_spacing
- in um.
gdsfactory.components.cutback_component¶
cutback_component¶
@gf.cell
def cutback_component(component: ComponentSpec = taper_0p5_to_3_l36,
cols: int = 4,
rows: int = 5,
port1: str = "o1",
port2: str = "o2",
bend180: ComponentSpec = bend_euler180,
mirror: bool = False,
mirror1: bool = False,
mirror2: bool = False,
straight_length: float | None = None,
straight_length_pair: float | None = None,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns a daisy chain of components for measuring their loss.
Works only for components with 2 ports (input, output).
Arguments:
component
- for cutback.cols
- number of columns.rows
- number of rows.port1
- name of first optical port.port2
- name of second optical port.bend180
- ubend.mirror
- Flips component. Useful when ‘o2’ is the port that you want to route to.mirror1
- mirrors first component.mirror2
- mirrors second component.straight_length
- length of the straight section between cutbacks.straight_length_pair
- length of the straight section between each component pair.cross_section
- specification (CrossSection, string or dict).kwargs
- component settings.
gdsfactory.components.mzi_phase_shifter¶
gdsfactory.components.fiducial_squares¶
fiducial_squares¶
@gf.cell
def fiducial_squares(layers: Layers = ((1, 0), ),
size: Float2 = (5, 5),
offset: float = 0.14) -> gf.Component
Returns fiducials with two squares.
Arguments:
layers
- list of layers.size
- in um.offset
- in um.
gdsfactory.components.coh_rx_single_pol¶
coh_rx_single_pol¶
@cell
def coh_rx_single_pol(
bend: ComponentSpec = "bend_euler",
cross_section: CrossSectionSpec = "strip",
hybrid_90deg: ComponentSpec = mmi_90degree_hybrid,
detector: ComponentSpec = ge_detector_straight_si_contacts,
det_spacing: tuple[float, float] = (60.0, 50.0),
with_pads: bool = True,
pad_det_spacing: float = 80.0,
in_wg_length: float = 20.0,
lo_input_coupler: ComponentSpec | None = None,
signal_input_coupler: ComponentSpec | None = None) -> Component
Single polarization coherent receiver.
Arguments:
bend
- 90 degrees bend library.cross_section
- for routing.hybrid_90deg
- generates the 90 degree hybrid.detector
- generates the detector.det_spacing
- spacing between 90 degree hybrid and detector and vertical spacing between detectors.with_pads
- if True, it draws pads for the balanced detectors.pad_det_spacing
- spacing between the pads and the detectors (if with_pads=True).in_wg_length
- length of the straight waveguides at the input of the 90 deg hybrid.lo_input_coupler
- Optional coupler for the LO.signal_input_coupler
- Optional coupler for the signal... code::
(lo_in_coupler)---| |--- detI1 \ __ i signal | 90 deg |--- detI2 // (signal_in_coupler)---| hybrid |--- detQ1 \ __ q signal |__________|--- detQ2 //
gdsfactory.components.ring_double_bend_coupler¶
ring_double_bend_coupler¶
@gf.cell
def ring_double_bend_coupler(radius: float = 5.0,
gap: float = 0.2,
coupling_angle_coverage: float = 70.0,
bend: ComponentSpec = bend_circular,
length_x: float = 0.6,
length_y: float = 0.6,
cross_section_inner: CrossSectionSpec = "strip",
cross_section_outer: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns ring with double curved couplers.
TODO: enable euler bends.
Arguments:
radius
- um.gap
- um.angle_inner
- of the inner bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.angle_outer
- of the outer bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.bend
- for bend.length_y
- vertical straight length.cross_section_inner
- spec inner bend.cross_section_outer
- spec outer bend.kwargs
- cross_section settings.
gdsfactory.components.mode_converter¶
mode_converter¶
@gf.cell
def mode_converter(gap: float = 0.3,
length: float = 10,
coupler_straight_asymmetric:
ComponentSpec = coupler_straight_asymmetric_function,
bend: ComponentSpec = partial(bend_euler_s, angle=45),
taper: ComponentSpec = taper_function,
mm_width: float = 1.2,
mc_mm_width: float = 1,
sm_width: float = 0.5,
taper_length: float = 25,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns Mode converter from TE0 to TE1.
By matching the effective indices of two waveguides with different widths, light can couple from different transverse modes e.g. TE0 <-> TE1. Shu et al. (2019)
Arguments:
gap
- directional coupler gap.length
- coupler length interaction.coupler_straight_asymmetric
- spec.mm_width
- input/output multimode waveguide width.mc_mm_width
- mode converter multimode waveguide widthsm_width
- single mode waveguide width.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
o2 --- --- o4 \ / \ /¶
o1 -----=======----- o3 |-----| length
= : multimode width
- : singlemode width
gdsfactory.components.coupler_full¶
coupler_full¶
@gf.cell
def coupler_full(coupling_length: float = 40.0,
dx: float = 10.0,
dy: float = 5.0,
gap: float = 0.5,
dw: float = 0.1,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Adiabatic Full coupler.
Design based on asymmetric adiabatic full coupler designs, such as the one reported in ‘Integrated Optic Adiabatic Devices on Silicon’ by Y. Shani, et al (IEEE Journal of Quantum Electronics, Vol. 27, No. 3 March 1991).
- is the first half of the input S-bend straight where the input straights widths taper by +dw and -dw,
- is the second half of the S-bend straight with constant, unbalanced widths,
- is the coupling region where the straights from unbalanced widths to balanced widths to reverse polarity unbalanced widths,
- is the fixed width straight that curves away from the coupling region, 5.is the final curve where the straights taper back to the regular width specified in the straight template.
Arguments:
coupling_length
- Length of the coupling region in um.dx
- Length of the bend regions in um.dy
- Port-to-port distance between the bend regions in um.gap
- Distance between the two straights in um.dw
- delta width. Top arm tapers to width - dw, bottom to width + dw in um.cross_section
- cross-section spec.
Arguments:
cross_section kwargs.
gdsfactory.components.edge_coupler_array¶
edge_coupler_array¶
@gf.cell
def edge_coupler_array(edge_coupler: ComponentSpec = edge_coupler_silicon,
n: int = 5,
pitch: float = 127.0,
x_reflection: bool = False,
text: ComponentSpec | None = text_rectangular,
text_offset: Float2 = (10, 20),
text_rotation: float = 0) -> Component
Fiber array edge coupler based on an inverse taper.
Each edge coupler adds a ruler for polishing.
Arguments:
edge_coupler
- edge coupler spec.n
- number of channels.pitch
- Fiber pitch.x_reflection
- horizontal mirror.text
- text spec.text_offset
- from edge coupler.text_rotation
- text rotation in degrees.
edge_coupler_array_with_loopback¶
@gf.cell
def edge_coupler_array_with_loopback(
edge_coupler: ComponentSpec = edge_coupler_silicon,
cross_section: CrossSectionSpec = "strip",
radius: float = 30,
n: int = 8,
pitch: float = 127.0,
extension_length: float = 1.0,
right_loopback: bool = True,
x_reflection: bool = False,
text: ComponentSpec | None = text_rectangular,
text_offset: Float2 = (0, 0),
text_rotation: float = 0) -> Component
Fiber array edge coupler.
Arguments:
edge_coupler
- edge coupler.cross_section
- spec.radius
- bend radius loopback (um).n
- number of channels.pitch
- Fiber pitch (um).extension_length
- in um.right_loopback
- adds right loopback.x_reflection
- horizontal mirror.text
- Optional text spec.text_offset
- x, y.text_rotation
- text rotation in degrees.
gdsfactory.components.spiral_inner_io¶
Spiral with grating couplers inside to save space.
spiral_inner_io¶
@gf.cell
def spiral_inner_io(N: int = 6,
x_straight_inner_right: float = 150.0,
x_straight_inner_left: float = 50.0,
y_straight_inner_top: float = 50.0,
y_straight_inner_bottom: float = 10.0,
grating_spacing: float = 127.0,
waveguide_spacing: float = 3.0,
bend90: ComponentSpec = bend_euler,
bend180: ComponentSpec = bend_euler180,
straight: ComponentSpec = straight_function,
length: float | None = None,
cross_section: CrossSectionSpec = "strip",
cross_section_bend: CrossSectionSpec | None = None,
cross_section_bend180: CrossSectionSpec | None = None,
asymmetric_cross_section: bool = False,
**kwargs) -> Component
Returns Spiral with ports inside the spiral loop.
You can add grating couplers inside.
Arguments:
N
- number of loops.x_straight_inner_right
- xlength.x_straight_inner_left
- x length left.y_straight_inner_top
- x inner top.y_straight_inner_bottom
- y length.grating_spacing
- defaults to 127 for fiber array.waveguide_spacing
- center to center spacing.bend90
- bend90 spec.bend180
- bend180 spec.straight
- straight spec.length
- spiral target length (um), overrides x_straight_inner_left. to match the length by a simple 1D interpolation.cross_section
- spec.cross_section_bend
- for the bends.cross_section_bend180
- for 180 bend.asymmetric_cross_section
- if the cross_section is asymmetric, it needs to be mirrored at the halfway pointkwargs
- cross_section settings.
spiral_inner_io_fiber_single¶
@gf.cell
def spiral_inner_io_fiber_single(cross_section: CrossSectionSpec = "strip",
cross_section_bend: CrossSectionSpec
| None = None,
cross_section_ports: CrossSectionSpec
| None = None,
x_straight_inner_right: float = 40.0,
x_straight_inner_left: float = 75.0,
y_straight_inner_top: float = 10.0,
y_straight_inner_bottom: float = 0.0,
grating_spacing: float = 200.0,
**kwargs) -> Component
Returns Spiral with 90 and 270 degree ports.
You can add single fiber north and south grating couplers inside the spiral to save space
Arguments:
cross_section
- for the straight sections in the spiral.cross_section_bend
- for the bends in the spiral.cross_section_ports
- for input/output ports.x_straight_inner_right
- in um.x_straight_inner_left
- in um.y_straight_inner_top
- in um.y_straight_inner_bottom
- in um.grating_spacing
- in um.
Arguments:
N
- number of loops.waveguide_spacing
- center to center spacing.bend90
- bend90 spec.bend180
- bend180 spec.straight
- straight spec.length
- computes spiral length from simple interpolation.kwargs
- cross_section settings.
get_straight_length¶
def get_straight_length(length: float, spiral_function: ComponentSpec,
**kwargs) -> float
Returns y_spiral to achieve a particular spiral length.
gdsfactory.components.taper_adiabatic¶
taper_adiabatic¶
@gf.cell
def taper_adiabatic(width1: float = 0.5,
width2: float = 5.0,
length: float = 0,
neff_w: Callable = lambda w: np.poly1d(
adiabatic_polyfit_TE1550SOI_220nm)(w),
alpha: float = 1,
wavelength: float = 1.55,
npoints: int = 200,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> gf.Component
Returns a straight adiabatic_taper from an effective index callable.
Arguments:
width1
- initial width.width2
- final width.length
- 0 uses the optimized length, and otherwise the optimal shape is compressed/stretched to the specified length.neff_y
- a callable that returns the effective index as a function of width- By default, will use a compact model of neff(y) for fundamental 1550 nm TE mode of 220nm-thick core with 3.45 index, fully clad with 1.44 index. Many coefficients are needed to capture the behaviour.
alpha
- parameter that scales the rate of width change.- closer to 0 means longer and more adiabatic;
- 1 is the intuitive limit beyond which higher order modes are excited;
- [2] reports good performance up to 1.4 for fundamental TE in SOI (for multiple core thicknesses)
References:
[1] Burns, W. K., et al. “Optical waveguide parabolic coupling horns.” Appl. Phys. Lett., vol. 30, no. 1, 1 Jan. 1977, pp. 28-30, doi:10.1063/1.89199. [2] Fu, Yunfei, et al. “Efficient adiabatic silicon-on-insulator waveguide taper.” Photonics Res., vol. 2, no. 3, 1 June 2014, pp. A41-A44, doi:10.1364/PRJ.2.000A41.
npoints
- number of points for sampling
gdsfactory.components.coupler¶
coupler¶
@gf.cell
def coupler(gap: float = 0.236,
length: float = 20.0,
coupler_symmetric: ComponentSpec = coupler_symmetric_function,
coupler_straight: ComponentSpec = coupler_straight_function,
dy: float = 4.0,
dx: float = 10.0,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Symmetric coupler.
Arguments:
gap
- between straights in um.length
- of coupling region in um.coupler_symmetric
- spec for bend coupler.coupler_straight
- spec for straight coupler.dy
- port to port vertical spacing in um.dx
- length of bend in x direction in um.cross_section
- spec (CrossSection, string or dict).kwargs
- cross_section settings... code::
dx dx |------| |------| o2 ________ ______o3 \ / | \ length / | ======================= gap | dy / \ | __/ _ | o1 o4
coupler_straight coupler_symmetric
gdsfactory.components.via_stack_with_offset¶
via_stack_with_offset¶
@gf.cell
def via_stack_with_offset(
layers: LayerSpecs = ("PPP", "M1"),
size: Float2 = (10, 10),
sizes: tuple[Float2, ...] | None = None,
layer_offsets: Floats | None = None,
vias: tuple[ComponentSpec | None, ...] = (None, viac),
offsets: tuple[float, ...] | None = None) -> Component
Rectangular layer transition with offset between layers.
Arguments:
layers
- layer specs between vias.size
- for all vias array.sizes
- Optional size for each via array. Overrides size.layer_offsets
- Optional offsets for each layer with respect to size. positive grows, negative shrinks the size.vias
- via spec for previous layer. None for no via.offsets
- optional offset for each layer relatively to the previous one. By default it only offsets by size[1] if there is a via... code::
side view
| | | | layers[2] || vias[2] = None | | | layer_offsets[1]+size | layers[1] || | | vias[1] || | | | sizes[0] | layers[0] |____________|
vias[0] = None
gdsfactory.components.dbr_tapered¶
dbr_tapered¶
@gf.cell
def dbr_tapered(length: float = 10.0,
period: float = 0.85,
dc: float = 0.5,
w1: float = 0.4,
w2: float = 1.0,
taper_length: float = 20.0,
fins: bool = False,
fin_size: tuple[float, float] = (0.2, 0.05),
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Distributed Bragg Reflector Cell class.
Tapers the input straight to a periodic straight structure with varying width (1-D photonic crystal).
Arguments:
length
- Length of the DBR region.period
- Period of the repeated unit.dc
- Duty cycle of the repeated unit (must be a float between 0 and 1.0).w1
- thin section width. w1 = 0 corresponds to disconnected periodic blocks.w2
- wide section width.taper_length
- between the input/output straight and the DBR region.fins
- IfTrue
, adds fins to the input/output straights.fin_size
- Specifies the x- and y-size of thefins
. Defaults to 200 nm x 50 nmcross_section
- cross_section spec.
Arguments:
cross_section kwargs.
.. code::
period <-----><-------->
_______|
w1 w2 ... n times
|_________
gdsfactory.components.cdsem_straight_density¶
CD SEM structures.
cdsem_straight_density¶
@cell
def cdsem_straight_density(
widths: Floats = widths,
gaps: Floats = gaps,
length: float = 420.0,
label: str = "",
cross_section: CrossSectionSpec = "strip",
text: ComponentSpec | None = text_rectangular_mini) -> Component
Returns sweep of dense straight lines.
Arguments:
widths
- list of widths.gaps
- list of gaps.length
- of the lines.label
- defaults to widths[0] gaps[0].cross_section
- spec.text
- optional function for text.
gdsfactory.components.add_trenches¶
add_trenches¶
@gf.cell
def add_trenches(component: ComponentSpec = coupler,
cross_section: CrossSectionSpec = "rib_with_trenches",
top: bool = True,
bot: bool = True,
right: bool = False,
left: bool = False,
**kwargs) -> gf.Component
Return component with trenches.
Arguments:
component
- component to add to the trenches.cross_section
- spec (CrossSection, string or dict).top
- add top trenches.bot
- add bot trenches.right
- add right trenches.left
- add left trenches.kwargs
- component settings.
gdsfactory.components.wire_sbend¶
wire_sbend¶
@gf.cell
def wire_sbend(dx: float = 20.0, dy: float = 10.0, **kwargs) -> Component
Sbend corner with manhattan wires.
Arguments:
dx
- xsize.dy
- ysize.kwargs
- cross_section settings.
gdsfactory.components.coupler_symmetric¶
coupler_symmetric¶
@gf.cell
def coupler_symmetric(bend: ComponentSpec = bend_s,
gap: float = 0.234,
dy: float = 5.0,
dx: float = 10.0,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Two coupled straights with bends.
Arguments:
bend
- bend spec.gap
- in um.dy
- port to port vertical spacing.dx
- bend length in x direction.cross_section
- section.**kwargs
- cross_section settings... code::
dx |-----| ___ E1 / | ___/ | gap _____ | dy \ | _ | E0
gdsfactory.components.mzm¶
mzm¶
@cell
def mzm(phase_shifter: ComponentSpec = straight_pin,
length_x: float = 500,
length_y: float = 2.0,
delta_length: float = 0.0,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
splitter: ComponentSpec = "mmi1x2",
combiner: ComponentSpec | None = "mmi1x2",
with_splitter: bool = True,
port_e1_splitter: str = "o2",
port_e0_splitter: str = "o3",
port_e1_combiner: str = "o2",
port_e0_combiner: str = "o3",
nbends: int = 2,
cross_section: CrossSectionSpec = "strip",
mirror_bot: bool = False) -> Component
Mzm modulator.
Arguments:
phase_shifter
- for bottom and top arms.length_x
- horizontal length. None uses to the straight_x_bot/top defaults.length_y
- vertical length for both and top arms.delta_length
- bottom arm vertical extra length.bend
- 90 degrees bend spec.straight
- straight function for vertical.splitter
- splitter function.combiner
- combiner function. Optional adds ports.with_splitter
- if False removes splitter.port_e1_splitter
- east top splitter port.port_e0_splitter
- east bot splitter port.port_e1_combiner
- east top combiner port.port_e0_combiner
- east bot combiner port.nbends
- from straight top/bot to combiner (at least 2).cross_section
- for routing (sxtop/sxbot to combiner).mirror_bot
- mirrors bottom arm... code::
b2______b3 | sxtop | straight_y | | | b1 b4 splitter==| |==combiner b5 b8 | | straight_y | | | delta_length/2 | | | b6__sxbot__b7 Lx
gdsfactory.components.die¶
based on phidl.geometry.
die¶
@gf.cell
def die(size: tuple[float, float] = (10000.0, 10000.0),
street_width: float = 100.0,
street_length: float = 1000.0,
die_name: str | None = "chip99",
text_size: float = 100.0,
text_location: str | Float2 = "SW",
layer: LayerSpec | None = "FLOORPLAN",
bbox_layer: LayerSpec | None = "FLOORPLAN",
text: ComponentFactory = text,
draw_corners: bool = False) -> gf.Component
Returns die with optional markers marking the boundary of the die.
Arguments:
size
- x, y dimensions of the die.street_width
- Width of the corner marks for die-sawing.street_length
- Length of the corner marks for die-sawing.die_name
- Label text. If None, no label is added.text_size
- Label text size.text_location
- {‘NW’, ‘N’, ‘NE’, ‘SW’, ‘S’, ‘SE’} or (x, y) coordinate.layer
- For street widths. None to not draw the street widths.bbox_layer
- optional bbox layer drawn bounding box around the die.text
- function use for generating text. Needs to accept text, size, layer.draw_corners
- True draws only corners. False draws a square die.
gdsfactory.components.array_with_fanout¶
array_with_fanout¶
@cell
def array_with_fanout(component: ComponentSpec = "pad",
columns: int = 3,
pitch: float = 150.0,
waveguide_pitch: float = 10.0,
start_straight_length: float = 5.0,
end_straight_length: float = 40.0,
radius: float = 5.0,
component_port_name: str = "e4",
bend: ComponentSpec = "bend_euler",
bend_port_name1: str | None = None,
bend_port_name2: str | None = None,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns component array in X axis with west facing waveguides.
Arguments:
component
- to replicate.columns
- number of components.pitch
- for waveguides.waveguide_pitch
- for output waveguides.start_straight_length
- length of the start of the straight.end_straight_length
- length of the straight at the end.radius
- bend radius.component_port_name
- for fanout.bend
- spec.bend_port_name1
- optional port name.bend_port_name2
- optional port name.cross_section
- cross_section spec.kwargs
- cross_section settings.
array_with_fanout_2d¶
@cell
def array_with_fanout_2d(pitch: float = 150.0,
pitch_x: float | None = None,
pitch_y: float | None = None,
columns: int = 3,
rows: int = 2,
**kwargs) -> Component
Returns 2D array with fanout waveguides facing west.
Arguments:
pitch
- 2D pitch.pitch_x
- defaults to pitch.pitch_y
- defaults to pitch.columns
- number of columns.rows
- number of rows.keyword args:
component
- to replicate.pitch
- in um.waveguide_pitch
- for fanout in um.start_straight_length
- length of the start of the straight in um.end_straight_length
- length of the straight at the end in um.radius
- bend radius in um.cross_section
- cross_section factory. component_port_name: bend_port_name1: bend_port_name2:
gdsfactory.components.grating_coupler_rectangular_arbitrary¶
grating_coupler_rectangular_arbitrary¶
@gf.cell
def grating_coupler_rectangular_arbitrary(
gaps: Floats = _gaps,
widths: Floats = _widths,
width_grating: float = 11.0,
length_taper: float = 150.0,
polarization: str = "te",
wavelength: float = 1.55,
taper: ComponentSpec | None = taper_function,
layer_grating: LayerSpec | None = None,
layer_slab: LayerSpec = "SLAB150",
slab_xmin: float = -1.0,
slab_offset: float = 1.0,
fiber_angle: float = 15,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Grating coupler uniform with rectangular shape (not elliptical). Therefore it needs a longer taper. Grating teeth are straight instead of elliptical.
Arguments:
gaps
- list of gaps between grating teeth.widths
- list of grating widths.width_grating
- grating teeth width.length_taper
- taper length (um).polarization
- ‘te’ or ‘tm’.wavelength
- in um.taper
- function.layer_grating
- Optional layer for grating. by default None uses cross_section.layer. if different from cross_section.layer expands taper.layer_slab
- layer that protects the slab under the grating.slab_xmin
- where 0 is at the start of the taper.slab_offset
- from edge of grating to edge of the slab.fiber_angle
- in degrees.cross_section
- for input waveguide port.kwargs
- cross_section settings... code::
fiber
/ / / / / / / /
|-||-||-|__ layer layer_slab | o1 ______________|
top view _________ /| | | | | / | | | | | /taper_angle /_ | | | | | wg_width | | | | | | \ | | | | | \ | | | | | \ | | | | | ||||_| <--> taper_length
gdsfactory.components.C¶
C¶
@gf.cell
def C(width: float = 1.0,
size: tuple[float, float] = (10.0, 20.0),
layer: LayerSpec = "WG") -> Component
C geometry with ports on both ends.
based on phidl.
Arguments:
width
- of the line.size
- length and height of the base.layer
- layer spec... code::
| o1 | ___ | | | |___ ||<---> size[0] |______ o2
gdsfactory.components.coupler_straight¶
coupler_straight¶
@gf.cell
def coupler_straight(length: float = 10.0,
gap: float = 0.27,
**kwargs) -> Component
Coupler_straight with two parallel straights.
Arguments:
length
- of straight.gap
- between straights.kwargs
- cross_section settings.
gdsfactory.components.coupler_adiabatic¶
coupler_adiabatic¶
@gf.cell
def coupler_adiabatic(length1: float = 20.0,
length2: float = 50.0,
length3: float = 30.0,
wg_sep: float = 1.0,
input_wg_sep: float = 3.0,
output_wg_sep: float = 3.0,
dw: float = 0.1,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns 50/50 adiabatic coupler.
Design based on asymmetric adiabatic 3dB coupler designs, such as those.
input Bezier curves, with poles set to half of the x-length of the S-bend.
- is the first half of input S-bend where input widths taper by +dw and -dw
- is the second half of the S-bend straight with constant, unbalanced widths
- is the region where the two asymmetric straights gradually come together
- straights taper back to the original width at a fixed distance from one another
- is the output S-bend straight.
Arguments:
length1
- region that gradually brings the two asymmetric straights together. In this region the straight widths gradually change to be different bydw
.length2
- coupling region, where asymmetric straights gradually become the same width.length3
- output region where the two straights separate.wg_sep
- Distance between center-to-center in the coupling region (Region 2).input_wg_sep
- Separation of the two straights at the input, center-to-center.output_wg_sep
- Separation of the two straights at the output, center-to-center.dw
- Change in straight width. In Region 1, top arm tapers to width+dw/2.0, bottom taper to width-dw/2.0.cross_section
- cross_section spec.
Arguments:
cross_section kwargs.
gdsfactory.components.cross¶
cross¶
@gf.cell
def cross(length: float = 10.0,
width: float = 3.0,
layer: LayerSpec = "WG",
port_type: str | None = None) -> Component
Returns a cross from two rectangles of length and width.
Arguments:
length
- float Length of the cross from one end to the other.width
- float Width of the arms of the cross.layer
- layer for geometry.port_type
- None, optical, electrical.
gdsfactory.components.cdsem_bend180¶
CD SEM structures.
cdsem_bend180¶
@cell
def cdsem_bend180(width: float = 0.5,
radius: float = 10.0,
wg_length: float = LINE_LENGTH,
straight: ComponentSpec = "straight",
bend90: ComponentSpec = "bend_circular",
cross_section: CrossSectionSpec = "strip",
text: ComponentSpec = text_rectangular_mini) -> Component
Returns CDSEM structures.
Arguments:
width
- of the line.radius
- um.wg_length
- in um.straight
- spec.bend90
- spec.cross_section
- spec.text
- spec.
gdsfactory.components.copy_layers¶
copy_layers¶
@cell
def copy_layers(factory: ComponentSpec = cross,
layers: LayerSpecs = ((1, 0), (2, 0)),
**kwargs) -> Component
Returns a component with the geometry copied in different layers.
Arguments:
factory
- component spec.layers
- iterable of layers.kwargs
- keyword arguments.
gdsfactory.components.grating_coupler_elliptical_lumerical¶
grating_coupler_elliptical_lumerical¶
@cell
def grating_coupler_elliptical_lumerical(parameters: Floats = parameters,
layer: LayerSpec = "WG",
layer_slab: LayerSpec
| None = "SLAB150",
taper_angle: float = 55,
taper_length: float = 12.24 + 0.36,
fiber_angle: float = 5,
info: dict[str, Any] | None = None,
bias_gap: float = 0,
**kwargs) -> Component
Returns a grating coupler from lumerical inverse design 3D optimization.
this is a wrapper of components.grating_coupler_elliptical_arbitrary
https://
Here are the simulation settings used in lumerical
n_bg=1.44401 # Refractive index of the background material (cladding) wg=3.47668 # Refractive index of the waveguide material (core) lambda0=1550e-9 bandwidth = 0e-9 polarization = ‘TE’ wg_width=500e-9 # Waveguide width wg_height=220e-9 # Waveguide height etch_depth=80e-9 # etch depth theta_fib_mat = 5 # Angle of the fiber mode in material theta_taper=30 efficiency=0.55 # 5.2 dB
Arguments:
parameters
- xinput, gap1, width1, gap2, width2 ...layer
- for waveguide.layer_slab
- for slab.taper_angle
- in deg.taper_length
- in um.fiber_angle
- used to compute ellipticity.info
- optional simulation settings.bias_gap
- gap/trenches bias (um) to compensate for etching bias.keyword Args:
taper_length
- taper length from input in um.taper_angle
- grating flare angle in degrees.wavelength
- grating transmission central wavelength (um).fiber_angle
- fibre angle in degrees determines ellipticity.neff
- tooth effective index.nclad
- cladding effective index.polarization
- te or tm.spiked
- grating teeth include sharp spikes to avoid non-manhattan drc errors.cross_section
- cross_section spec for waveguide port.
gdsfactory.components.bend_port¶
bend_port¶
@gf.cell
def bend_port(component: ComponentSpec = straight_heater_metal,
port_name: str = "l_e1",
port_name2: str = "r_e1",
port_name1_bend: str | None = None,
port_name2_bend: str | None = None,
cross_section: CrossSectionSpec = "metal3_with_bend",
bend: ComponentSpec = bend_circular,
angle: float = 180,
extension_length: float | None = None,
**kwargs) -> gf.Component
Returns a component with a bend and a straight extension.
Arguments:
component
- to bend.port_name
- of the component port origin.port_name2
- of the component port destination.port_name1_bend
- for bend port.port_name2_bend
- for bend port.cross_section
- for the bend.bend
- factory for the bend.angle
- for the bend.extension_length
- for the straight after the bend.kwargs
- cross_section settings.
gdsfactory.components.straight_heater_meander_doped¶
straight_heater_meander_doped¶
@gf.cell
def straight_heater_meander_doped(
length: float = 300.0,
spacing: float = 2.0,
cross_section: gf.typings.CrossSectionSpec = "strip",
heater_width: float = 1.5,
extension_length: float = 15.0,
layers_doping: LayerSpecs = ("P", "PP", "PPP"),
radius: float = 5.0,
via_stack: ComponentSpec | None = via_stack,
port_orientation1: int | None = None,
port_orientation2: int | None = None,
straight_widths: Floats = (0.8, 0.9, 0.8),
taper_length: float = 10) -> Component
Returns a meander based heater.
based on SungWon Chung, Makoto Nakai, and Hossein Hashemi,
Low-power thermo-optic silicon modulator for large-scale photonic integrated systems
Opt. Express 27, 13430-13459 (2019)
https://
Arguments:
length
- total length of the optical path.spacing
- waveguide spacing (center to center).cross_section
- for waveguide.heater_width
- for heater.extension_length
- of input and output optical ports.layers_doping
- doping layers to be used for heater.radius
- for the meander bends.via_stack
- for the heater to via_stack metal.port_orientation1
- in degrees. None adds all orientations.port_orientation2
- in degrees. None adds all orientations.straight_width
- width of the straight section.taper_length
- from the cross_section.
gdsfactory.components.ring_crow_couplers¶
ring_crow_couplers¶
@gf.cell
def ring_crow_couplers(
radius: list[float] = [10.0] * 3,
bends: list[ComponentSpec] = [bend_circular] * 3,
ring_cross_sections: list[CrossSectionSpec] = [strip] * 3,
couplers: list[ComponentSpec] = [coupler_full] * 4) -> Component
Coupled ring resonators with coupler components between gaps.
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.length_x
- ring coupler length.length_y
- vertical straight length.coupler
- ring coupler spec.straight
- straight spec.bend
- bend spec.cross_section
- cross_section spec.couplers
- coupling component between rings and bus... code::
--==ct==-- gap[N-1] <------- couplers[N-1] | | sl sr ring[N-1] | | --==cb==-- gap[N-2] <------- couplers[N-2]
. . .
--==ct==-- | | sl sr lengths_y[1], ring[1] | | --==cb==-- gap[1] <------- couplers[1] --==ct==-- | | sl sr lengths_y[0], ring[0] | | --==cb==-- gap[0] <------- couplers[0]
length_x
gdsfactory.components.mzi_pads_center¶
mzi_pads_center¶
@gf.cell
def mzi_pads_center(ps_top: ComponentSpec = straight_heater_metal,
ps_bot: ComponentSpec = straight_heater_metal,
mzi: ComponentSpec = mzi_function,
pad: ComponentSpec = pad_small,
length_x: float = 500,
length_y: float = 40,
mzi_sig_top: str = "top_r_e2",
mzi_gnd_top: str = "top_l_e2",
mzi_sig_bot: str = "bot_l_e2",
mzi_gnd_bot: str = "bot_r_e2",
pad_sig_bot: str = "e1_1_1",
pad_sig_top: str = "e3_1_3",
pad_gnd_bot: str = "e4_1_2",
pad_gnd_top: str = "e2_1_2",
delta_length: float = 40.0,
cross_section: CrossSectionSpec = "strip",
cross_section_metal: CrossSectionSpec = "metal_routing",
pad_spacing: float | str = "pad_spacing",
**kwargs) -> gf.Component
Return Mzi phase shifter with pads in the middle.
GND is the middle pad and is shared between top and bottom phase shifters.
Arguments:
ps_top
- phase shifter top.ps_bot
- phase shifter bottom.mzi
- interferometer.pad
- pad function.length_x
- horizontal length.length_y
- vertical length.mzi_sig_top
- port name for top phase shifter signal.mzi_gnd_top
- port name for top phase shifter GND.mzi_sig_bot
- port name for top phase shifter signal.mzi_gnd_bot
- port name for top phase shifter GND.pad_sig_bot
- port name for top pad.pad_sig_top
- port name for top pad.pad_gnd_bot
- port name for top pad.pad_gnd_top
- port name for top pad.delta_length
- mzi length imbalance.cross_section
- for the mzi.cross_section_metal
- for routing metal.pad_spacing
- pad pitch in um.kwargs
- routing settings.
gdsfactory.components.optimal_hairpin¶
optimal_hairpin¶
@cell
def optimal_hairpin(width: float = 0.2,
pitch: float = 0.6,
length: float = 10,
turn_ratio: float = 4,
num_pts: int = 50,
layer: LayerSpec = (1, 0)) -> Component
Returns an optimally-rounded hairpin geometry, with a 180 degree turn on the right end of the polygon connected to two prongs extending towards ports on the left end.
based on phidl.geometry
Arguments:
width : int or float Width of the hairpin leads. pitch : int or float Distance between the two hairpin leads. Must be greater than width. length : int or float Length of the hairpin from the connectors to the opposite end of the curve.
turn_ratio
- int or float Specifies how much of the hairpin is dedicated to the 180 degree turn. A turn_ratio of 10 will result in 20% of the hairpin being comprised of the turn. num_pts : int Number of points constituting the 180 degree turn. layer : int, array-like[2], or set Specific layer(s) to put polygon geometry on.
Notes:
Hairpin pitch must be greater than width.
Optimal structure from Clem & Berggren (2011) Clem, J., & Berggren, K. (2011). Geometry-dependent critical currents in superconducting nanocircuits. Physical Review B, 84(17), 1–27.
gdsfactory.components.coh_tx_dual_pol¶
coh_tx_dual_pol¶
@cell
def coh_tx_dual_pol(splitter: ComponentSpec = "mmi1x2",
combiner: ComponentSpec | None = None,
spol_coh_tx: ComponentSpec = "coh_tx_single_pol",
yspacing: float = 10.0,
xspacing: float = 40.0,
input_coupler: ComponentSpec | None = None,
output_coupler: ComponentSpec | None = None,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Dual polarization coherent transmitter.
Arguments:
splitter
- splitter function.combiner
- combiner function.spol_coh_tx
- function generating a coherent tx for a single polarization.yspacing
- vertical spacing between each single polarization coherent tx.xspacing
- horizontal spacing between splitter and combiner.input_coupler
- Optional coupler to add before the splitter.output_coupler
- Optional coupler to add after the combiner.cross_section
- for routing (splitter to mzms and mzms to combiners).kwargs
- cross_section settings... code::
___ single_pol_tx__ | | | | | | (in_coupler)---splitter==| |==combiner---(out_coupler) | | | | |___ single_pol_tx_|
gdsfactory.components.ring_single_dut¶
ring_single_dut¶
@gf.cell
def ring_single_dut(component: ComponentSpec = taper2,
gap: float = 0.2,
length_x: float = 4,
length_y: float = 0,
radius: float = 5.0,
coupler: ComponentSpec = coupler_ring,
bend: ComponentSpec = bend_euler,
with_component: bool = True,
port_name: str = "o1",
**kwargs) -> Component
Single bus ring made of two couplers (ct: top, cb: bottom) connected.
with two vertical straights (wyl: left, wyr: right) (Component Under Test) in the middle to extract loss from quality factor.
Arguments:
component
- device under test.gap
- in um.length
- in um.length_y
- in um.radius
- in um.coupler
- coupler function.bend
- bend function.with_component
- True adds component. False adds waveguide.port_name
- for component input.kwargs
- cross_section settings.
Arguments:
with_component
- if False changes component for just a straight... code::
bl-wt-br | | length_y wl component | | --==cb==-- gap
length_x
gdsfactory.components.ring_single_array¶
ring_single_array¶
@gf.cell
def ring_single_array(ring: ComponentFactory = ring_single,
spacing: float = 5.0,
list_of_dicts: tuple[dict[str, float], ...]
| None = None,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Ring of single bus connected with straights.
Arguments:
ring
- ring function.spacing
- between rings.list_of_dicts
- settings for each ring.cross_section
- spec.kwargs
- cross_section settings... code::
| | | | | | length_y | | | | | | --======-- spacing ----==gap==--
length_x
gdsfactory.components.add_grating_couplers¶
Add grating_couplers to a component.
add_grating_couplers¶
@cell
def add_grating_couplers(
component: ComponentSpec = straight,
grating_coupler: ComponentSpec = grating_coupler_te,
layer_label: tuple[int, int] = (200, 0),
gc_port_name: str = "o1",
get_input_labels_function: LabelListFactory | None = get_input_labels,
select_ports: Callable[..., PortsDict] = select_ports_optical,
component_name: str | None = None) -> Component
Returns new component with grating couplers and labels.
Arguments:
component
- to add grating_couplers.grating_coupler
- grating_coupler spec.layer_label
- for label.gc_port_name
- where to add label.get_input_labels_function
- function to get label.select_ports
- for selecting optical_ports.component_name
- optional component name.
add_grating_couplers_with_loopback_fiber_single¶
@cell
def add_grating_couplers_with_loopback_fiber_single(
component: ComponentSpec = spiral_inner_io_fiber_single,
grating_coupler: ComponentSpec = grating_coupler_te,
layer_label: tuple[int, int] | None = (200, 0),
gc_port_name: str = "o1",
get_input_labels_function: LabelListFactory | None = get_input_labels,
get_input_label_text_loopback_function:
Callable = get_input_label_text_loopback,
select_ports: Callable[..., PortsDict] = select_ports_optical,
with_loopback: bool = True,
cross_section: CrossSectionSpec = strip,
component_name: str | None = None,
loopback_xspacing: float = 5.0,
rotation: int = 90) -> Component
Returns new component with all ports terminated with grating couplers.
Arguments:
component
- to add grating_couplers.grating_coupler
- grating_coupler spec function, string or dict.layer_label
- optional layer_label for the ports.gc_port_name
- grating_coupler port name.get_input_labels_function
- function to get grating_coupler labels. get_input_label_text_loopback_function:select_ports
- function to select ports.with_loopback
- adds a reference loopback.cross_section
- for routing.component_name
- optional component name.loopback_xspacing
- in um.rotation
- in degrees, 90 for North South devices, 0 for East-West.
add_grating_couplers_with_loopback_fiber_array¶
@cell
def add_grating_couplers_with_loopback_fiber_array(
component: ComponentSpec = spiral_inner_io,
grating_coupler: ComponentSpec = grating_coupler_te,
excluded_ports: list[str] | None = None,
grating_separation: float = 127.0,
bend_radius_loopback: float | None = None,
gc_port_name: str = "o1",
gc_rotation: int = -90,
straight_separation: float = 5.0,
bend: ComponentSpec = bend_euler,
layer_label: tuple[int, int] = (200, 0),
layer_label_loopback: tuple[int, int] | None = None,
component_name: str | None = None,
with_loopback: bool = False,
nlabels_loopback: int = 2,
get_input_labels_function: LabelListFactory | None = get_input_labels,
cross_section: CrossSectionSpec = strip,
select_ports: Callable = select_ports_optical,
loopback_yspacing: float = 4.0,
**kwargs) -> Component
Returns a component with grating_couplers and loopback.
Arguments:
component
- to add grating_couplers.grating_coupler
- grating_coupler.excluded_ports
- list of ports to exclude.grating_separation
- in um.bend_radius_loopback
- um.gc_port_name
- optional grating coupler name.gc_rotation
- grating coupler rotation in degrees.straight_separation
- in um.bend
- bend spec.layer_label
- for testing label.layer_label_loopback
- for testing label alignment loopback.component_name
- optional component name.with_loopback
- If True, add compact loopback alignment ports.nlabels_loopback
- number of ports to label(0
- no labels, 1: first port, 2: both ports).get_input_labels_function
- for getting test labels.cross_section
- CrossSectionSpec.select_ports
- function to select ports.loopback_yspacing
- in um.kwargs
- cross_section settings.
gdsfactory.components.extend_ports_list¶
extend_ports_list¶
@cell
def extend_ports_list(ports: list[Port],
extension: ComponentSpec,
extension_port_name: str | None = None,
ignore_ports: Strs | None = None) -> Component
Returns a component with the extensions for a list of ports.
Arguments:
ports
- list of ports.extension
- function for extension.extension_port_name
- to connect extension.ignore_ports
- list of port names to ignore.
gdsfactory.components.coupler_straight_asymmetric¶
coupler_straight_asymmetric¶
@gf.cell
def coupler_straight_asymmetric(length: float = 10.0,
gap: float = 0.27,
width_top: float = 0.5,
width_bot: float = 1,
**kwargs) -> Component
Coupler with two parallel straights of different widths.
Arguments:
length
- of straight.gap
- between straights.width_top
- of top straight.width_bot
- of bottom straight.kwargs
- cross_section settings.
gdsfactory.components.ring_single_bend_coupler¶
coupler_bend¶
@gf.cell
def coupler_bend(radius: float = 10.0,
coupler_gap: float = 0.2,
coupling_angle_coverage: float = 120.0,
cross_section_inner: CrossSectionSpec = "strip",
cross_section_outer: CrossSectionSpec = "strip",
bend: ComponentSpec = bend_circular) -> Component
Compact curved coupler with bezier escape.
TODO: fix for euler bends.
Arguments:
radius
- um.gap
- um.angle_inner
- of the inner bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.angle_outer
- of the outer bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.bend
- for bend.cross_section_inner
- spec inner bend.cross_section_outer
- spec outer bend... code::
r 4 | | | / 3 | / / 2_/ / 1_____/
coupler_ring_bend¶
@gf.cell
def coupler_ring_bend(radius: float = 10.0,
coupler_gap: float = 0.2,
coupling_angle_coverage: float = 90.0,
length_x: float = 0.0,
cross_section_inner: CrossSectionSpec = "strip",
cross_section_outer: CrossSectionSpec = "strip",
bend: ComponentSpec = bend_circular) -> Component
Two back-to-back coupler_bend.
Arguments:
radius
- um.gap
- um.angle_inner
- of the inner bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.angle_outer
- of the outer bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.bend
- for bend.length_x
- horizontal straight length.cross_section_inner
- spec inner bend.cross_section_outer
- spec outer bend. kwargs:
ring_single_bend_coupler¶
@gf.cell
def ring_single_bend_coupler(radius: float = 5.0,
gap: float = 0.2,
coupling_angle_coverage: float = 180.0,
bend: ComponentSpec = bend_circular,
length_x: float = 0.6,
length_y: float = 0.6,
cross_section_inner: CrossSectionSpec = "strip",
cross_section_outer: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns ring with curved coupler.
TODO: enable euler bends.
Arguments:
radius
- um.gap
- um.angle_inner
- of the inner bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.angle_outer
- of the outer bend, from beginning to end. Depending on the bend chosen, gap may not be preserved.bend
- for bend.length_x
- horizontal straight length.length_y
- vertical straight length.cross_section_inner
- spec inner bend.cross_section_outer
- spec outer bend.kwargs
- cross_section settings.
gdsfactory.components.compass¶
compass¶
@cell
def compass(
size=(4.0, 2.0),
layer: LayerSpec = "WG",
port_type: str | None = "electrical",
port_inclusion: float = 0.0,
port_orientations: Ints | None = (180, 90, 0, -90)
) -> Component
Rectangle with ports on each edge (north, south, east, and west).
Arguments:
size
- rectangle size.layer
- tuple (int, int).port_type
- optical, electrical.port_inclusion
- from edge.port_orientations
- list of port_orientations to add. None add one port only.
gdsfactory.components.via_cutback¶
Via cutback.
via_cutback¶
@gf.cell
def via_cutback(num_vias: float = 100.0,
wire_width: float = 10.0,
via_width: float = 5.0,
via_spacing: float = 40.0,
min_pad_spacing: float = 0.0,
pad: ComponentSpec = via_stack_heater_m3,
pad_size: Float2 = (150, 150),
layer1: LayerSpec = "HEATER",
layer2: LayerSpec = "M1",
via_layer: LayerSpec = "VIAC",
wire_pad_inclusion: float = 12.0) -> Component
Via cutback to extract via resistance.
based on phidl.geometry
Arguments:
num_vias
- total requested vias needs to be even.wire_width
- width of wire.via_width
- width of via.via_spacing
- via_spacing.pad_size
- (width, height). min_pad_spacing. pad_layer.layer1
- top wiring.layer2
- bottom wiring.via_layer
- via.wire_pad_inclusion
- in um.
gdsfactory.components.spiral_heater¶
spiral_racetrack¶
@gf.cell
def spiral_racetrack(min_radius: float = 5,
straight_length: float = 10.0,
spacings: Floats = (2, 2, 3, 3, 2, 2),
straight_factory: ComponentFactory = straight,
bend_factory: ComponentFactory = bend_euler,
bend_s_factory: ComponentFactory = bend_s,
cross_section: CrossSectionSpec = "strip",
cross_section_s: CrossSectionSpec | None = None,
n_bend_points: int | None = None,
with_inner_ports: bool = False,
extra_90_deg_bend: bool = False) -> Component
Returns Racetrack-Spiral.
Arguments:
min_radius
- smallest radius in um.straight_length
- length of the straight segments in um.spacings
- space between the center of neighboring waveguides in um.straight_factory
- factory to generate the straight segments.bend_factory
- factory to generate the bend segments.bend_s_factory
- factory to generate the s-bend segments.cross_section
- cross-section of the waveguides.n_bend_points
- optional bend points.with_inner_ports
- if True, will build the spiral, but expose the inner ports where the S-bend would be.extra_90_deg_bend
- if True, we add an additional straight + 90 degree bent at the output, so the output port is looking down.
spiral_racetrack_fixed_length¶
@gf.cell
def spiral_racetrack_fixed_length(
length: float = 1000,
in_out_port_spacing: float = 150,
n_straight_sections: int = 8,
min_radius: float = 5,
min_spacing: float = 5.0,
straight_factory: ComponentFactory = straight,
bend_factory: ComponentFactory = bend_euler,
bend_s_factory: ComponentFactory = bend_s,
cross_section: CrossSectionSpec = "strip",
cross_section_s: CrossSectionSpec | None = None,
n_bend_points: int | None = None,
with_inner_ports: bool = False) -> Component
Returns Racetrack-Spiral with a specified total length.
The input and output ports are aligned in y. This class is meant to be used for generating interferometers with long waveguide lengths, where the most important parameter is the length difference between the arms.
Arguments:
length
- total length of the spiral from input to output ports in um.in_out_port_spacing
- spacing between input and output ports of the spiral in um.n_straight_sections
- total number of straight sections for the racetrack spiral. Has to be even.min_radius
- smallest radius in um.min_spacing
- minimum center-center spacing between adjacent waveguides.straight_factory
- factory to generate the straight segments.bend_factory
- factory to generate the bend segments.bend_s_factory
- factory to generate the s-bend segments.cross_section
- cross-section of the waveguides.cross_section_s
- cross-section of the s bend waveguide (optional).n_bend_points
- optional bend points.with_inner_ports
- if True, will build the spiral, but expose the inner ports where the S-bend would be.
spiral_racetrack_heater_metal¶
@gf.cell
def spiral_racetrack_heater_metal(
min_radius: float | None = None,
straight_length: float = 30,
spacing: float = 2,
num: int = 8,
straight_factory: ComponentFactory = straight,
bend_factory: ComponentFactory = bend_euler,
bend_s_factory: ComponentFactory = bend_s,
waveguide_cross_section: CrossSectionSpec = "strip",
heater_cross_section: CrossSectionSpec = "heater_metal") -> Component
Returns spiral racetrack with a heater above.
based on Qiu et al. (2020) .
Arguments:
min_radius
- smallest radius.straight_length
- length of the straight segments.spacing
- space between the center of neighboring waveguides.num
- number.straight_factory
- factory to generate the straight segments.bend_factory
- factory to generate the bend segments.bend_s_factory
- factory to generate the s-bend segments.waveguide_cross_section
- cross-section of the waveguides.heater_cross_section
- cross-section of the heater.
spiral_racetrack_heater_doped¶
@gf.cell
def spiral_racetrack_heater_doped(
min_radius: float | None = None,
straight_length: float = 30,
spacing: float = 2,
num: int = 8,
straight_factory: ComponentFactory = straight,
bend_factory: ComponentFactory = bend_euler,
bend_s_factory: ComponentFactory = bend_s,
waveguide_cross_section: CrossSectionSpec = "strip",
heater_cross_section: CrossSectionSpec = "npp") -> Component
Returns spiral racetrack with a heater between the loops.
based on Qiu et al. (2020) but with the heater between the loops.
Arguments:
min_radius
- smallest radius in um.straight_length
- length of the straight segments in um.spacing
- space between the center of neighboring waveguides in um.num
- number.straight_factory
- factory to generate the straight segments.bend_factory
- factory to generate the bend segments.bend_s_factory
- factory to generate the s-bend segments.waveguide_cross_section
- cross-section of the waveguides.heater_cross_section
- cross-section of the heater.
gdsfactory.components.ramp¶
ramp¶
@gf.cell
def ramp(length: float = 10.0,
width1: float = 5.0,
width2: float | None = 8.0,
layer: LayerSpec = "WG") -> Component
Return a ramp component.
Based on phidl.
Arguments:
length
- Length of the ramp section.width1
- Width of the start of the ramp section.width2
- Width of the end of the ramp section (defaults to width1).layer
- Specific layer to put polygon geometry on.
gdsfactory.components.via¶
via¶
@gf.cell
def via(size: tuple[float, float] = (0.7, 0.7),
spacing: tuple[float, float] | None = (2.0, 2.0),
gap: tuple[float, float] | None = None,
enclosure: float = 1.0,
layer: LayerSpec = "VIAC",
bbox_layers: tuple[tuple[int, int], ...] | None = None,
bbox_offset: float = 0) -> Component
Rectangular via.
Defaults to a square via.
Arguments:
size
- in x, y direction.spacing
- pitch_x, pitch_y.gap
- edge to edge via gap in x, y.enclosure
- inclusion of via.layer
- via layer.bbox_layers
- layers for the bounding box.bbox_offset
- in um... code::
enclosure
|<---> | | gap[0] size[0] | | <------> <-----> | | ______ ______ | | | | | | | | | | | | size[1] | | || || | | <-------------> | | spacing[0] | |_______________________________________|
gdsfactory.components.delay_snake3¶
delay_snake3¶
@gf.cell
def delay_snake3(length: float = 1600.0,
length0: float = 0.0,
length2: float = 0.0,
n: int = 2,
bend180: ComponentSpec = bend_euler180,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns Snake with a starting bend and 180 bends.
Arguments:
length
- total length.length0
- start length.length2
- end length.n
- number of loops.bend180
- ubend spec.cross_section
- cross_section spec.kwargs
- cross_section settings... code::
| length0 |
---------
\bend180.info[‘length’] / |-------------------/ | |------------------->------->| length2 | delta_length | |
gdsfactory.components.coupler90¶
coupler90¶
@gf.cell
def coupler90(gap: float = 0.2,
radius: float = 10.0,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight,
cross_section: CrossSectionSpec = "strip",
bend_cross_section: CrossSectionSpec | None = None,
**kwargs) -> Component
Straight coupled to a bend.
Arguments:
gap
- um.radius
- um.straight
- for straight.bend
- bend spec.cross_section
- cross_section spec.bend_cross_section
- optional bend cross_section spec.kwargs
- cross_section settings... code::
3 | / / 2_/ 1____4
gdsfactory.components.wire¶
Wires for electrical manhattan routes.
wire_corner¶
@gf.cell
def wire_corner(cross_section: CrossSectionSpec = "metal_routing",
with_bbox: bool = False,
**kwargs) -> Component
Returns 45 degrees electrical corner wire.
Arguments:
cross_section
- spec.with_bbox
- if True, includes the bbox layer and bbox offsets of the cross_sectionkwargs
- cross_section settings.
wire_corner45¶
@gf.cell
def wire_corner45(cross_section: CrossSectionSpec = "metal_routing",
radius: float = 10,
with_bbox: bool = False,
**kwargs) -> Component
Returns 90 degrees electrical corner wire.
Arguments:
cross_section
- spec.with_bbox
- if True, includes the bbox layer and bbox offsets of the cross_sectionkwargs
- cross_section settings.
wire_corner_sections¶
@gf.cell
def wire_corner_sections(cross_section: CrossSectionSpec = "metal_routing",
with_bbox: bool = False,
**kwargs) -> Component
Returns 90 degrees electrical corner wire, where all cross_section sections properly represented.
Works well with symmetric cross_sections, not quite ready for asymmetric.
Arguments:
cross_section
- spec.with_bbox
- if True, includes the bbox layer and bbox offsets of the cross_sectionkwargs
- cross_section settings.
gdsfactory.components.component_lattice¶
get_sequence_cross¶
def get_sequence_cross(straights_start,
straights_end,
iter_max: int = 100,
symbols=("X", "-"))
Returns sequence of crossings to achieve the permutations between two columns of I/O.
Arguments:
straights_start
- list of the input port indices.straights_end
- list of the output port indices.iter_max
- maximum iterations.symbols
- [X
,S
].
Notes:
symbols to be used in the returned sequence:
X
:represents the crossing symbol: two Xs next to each-other means that the two modes have to be swappedS
:Straight straight, or compensation path typically
component_sequence_to_str¶
def component_sequence_to_str(sequence)
Transform a sequence of components (such as the one obtained from.
get_sequence_cross_str) into an ASCII block which can be used either as a cartoon or as an input for component_lattice(lattice = ...)
component_lattice¶
@gf.cell
def component_lattice(lattice: str = """
C-X
CXX
CXX
C-X
""",
symbol_to_component: dict[str, Component] | None = None,
grid_per_unit: int = 1000) -> Component
Return a lattice Component of N inputs and outputs Columns must have.
components with the same x spacing between input/output ports Lines must have components with the same y spacing between input/output ports.
Arguments:
lattice
- ASCII map with character.symbol_to_component
- dict of ASCII character to component.grid_per_unit
- int.Lattice example:
.. code::
X-X XCX XCX X-X
.. plot:: :include-source:
import gdsfactory as gf from gdsfactory.components.crossing_waveguide import crossing45 from gdsfactory.components.crossing_waveguide import compensation_path
symbol_to_component = {
"C"
- gf.routing.fanout2x2(component=gf.components.coupler(), port_spacing=40.0),"X"
- crossing45(port_spacing=40.0),"-"
- compensation_path(crossing45=crossing45(port_spacing=40.0)), } c = gf.components.component_lattice(symbol_to_component=symbol_to_component) c.plot()
parse_lattice¶
def parse_lattice(
lattice: str, symbol_to_component: dict[str, Component]
) -> tuple[dict[int, list[str]], dict[int, float64]]
Extract each column.
Arguments:
lattice
- string describing lattice.symbol_to_component
- dict of ASCII character to component.
gdsfactory.components.taper_from_csv¶
Adiabatic tapers from CSV files.
taper_from_csv¶
@gf.cell
def taper_from_csv(filepath: Path = data / "taper_strip_0p5_3_36.csv",
cross_section: CrossSectionSpec = "strip") -> Component
Returns taper from CSV file.
Arguments:
filepath
- for CSV file.cross_section
- specification (CrossSection, string, CrossSectionFactory dict).
gdsfactory.components.coupler_broadband¶
coupler_broadband¶
@gf.cell
def coupler_broadband(w_sc: float = 0.5,
gap_sc: float = 0.2,
w_top: float = 0.6,
gap_pc: float = 0.3,
legnth_taper: float = 1.0,
bend: ComponentFactory = bend_euler,
coupler_straight: ComponentFactory = coupler_straight,
length_coupler_straight: float = 12.4,
lenght_coupler_big_gap: float = 4.7,
cross_section: CrossSectionSpec = "strip",
radius: float = 10.0) -> Component
Returns broadband coupler component.
https://
Arguments:
w_sc
- width of waveguides in the symmetric coupler section.gap_sc
- gap size between the waveguides in the symmetric coupler section.w_top
- width of the top waveguide in the phase control section.gap_pc
- gap size in the phase control section.legnth_taper
- length of the tapers.bend
- bend factory.coupler_straight
- coupler_straight factory.length_coupler_straight
- optimal L_1 from the 3d fdtd analysis.lenght_coupler_big_gap
- optimal L_2 from the 3d fdtd analysis.cross_section
- cross_section of the waveguides.radius
- bend radius.
gdsfactory.components.ring_section_based¶
Generates a ring resonator based on a series of given cross sections.
This is useful to generate interleaved junction rings or rings with relatively complex junction profiles
ring_section_based¶
@cell_without_validator
def ring_section_based(gap: float | Floats = 0.3,
radius: float = 5.0,
add_drop: bool = False,
cross_sections: dict[str, str] = def_dict,
cross_sections_sequence: str | list[str]
| tuple[str, ...] = "AB",
cross_sections_angles: dict[str, float]
| None = def_ang_dict,
start_cross_section: CrossSectionSpec | None = None,
start_angle: float | None = 10.0,
drop_cross_section: CrossSectionSpec | None = None,
bus_cross_section: CrossSectionSpec = "strip",
ang_res: float | None = 0.1) -> gf.Component
Returns a ring made of the specified cross sections.
We start with start_cross section if indicated, then repeat the sequence in cross_section_sequence until the whole ring is filled.
Arguments:
gap
- bus waveguide - ring gap.radius
- ring radius.add_drop
- if True, we draw an add-drop ringcross_sections
- dictionary of cross sections to add consecutively to the ring until the ring is filled. Keys should be single character.cross_sections_sequence
- sequence to follow filling the ring.Ex
- “AB” means we will put first section A, then section B, then section A again... until the ring is filled If we have a drop, then this can be a list of two strings, where the first sequence is for one side of the ring and the second for the other side of the ringcross_sections_angles
- angular extent of each cross section in the cross_sections dictionary (deg). If not indicated, then we assume that the sequence is only repeated once and calculate the necessary angular lengthstart_cross_section
- it is likely that the cross section at the ring-bus junction is different than the sequence we want to repeat. If that’s the case, then here you indicate the initial cross section.start_angle
- angular extent of the initial cross section (deg)drop_cross_section
- cross section for the drop port. If not indicated, we assume it is the same as init_cross_section.bus_cross_section
- cross section for the bus waveguide.ang_res
- angular resolution to draw the bends for each section.
gdsfactory.components.add_fiducials¶
add_fiducials¶
@cell
def add_fiducials(component: ComponentSpec = pad_array,
gap: float = 50,
left: ComponentSpec | None = "cross",
right: ComponentSpec | None = "cross",
top: ComponentSpec | None = None,
bottom: ComponentSpec | None = None,
offset: Float2 = (0, 0),
**kwargs) -> Component
Return component with fiducials.
Arguments:
component
- component to add to the new component.gap
- from component to fiducial edge.left
- optional left fiducial.right
- optional right fiducial.top
- optional top fiducial.bottom
- optional bottom fiducial.offset
- component offset coordinate (x, y).kwargs
- fiducial settings.
add_fiducials_offsets¶
@cell
def add_fiducials_offsets(
component: ComponentSpec = pad_array,
fiducial: ComponentSpec = "cross",
offsets: Coordinates = ((0, 100), (0, -100))
) -> Component
Returns new component with fiducials from a list of offsets.
Arguments:
component
- add reference to component to the new Component.fiducial
- function to return fiducial.offsets
- list of offsets.
gdsfactory.components.ring¶
ring¶
@gf.cell
def ring(radius: float = 10.0,
width: float = 0.5,
angle_resolution: float = 2.5,
layer: LayerSpec = "WG",
angle: float | None = 360) -> Component
Returns a ring.
Arguments:
radius
- ring radius.width
- of the ring.angle_resolution
- number of points per degree.layer
- layer.angle
- angular coverage of the ring
gdsfactory.components.straight_heater_metal¶
straight_heater_metal_undercut¶
@cell
def straight_heater_metal_undercut(
length: float = 320.0,
length_undercut_spacing: float = 6.0,
length_undercut: float = 30.0,
length_straight_input: float = 15.0,
heater_width: float = 2.5,
cross_section_heater: CrossSectionSpec = "heater_metal",
cross_section_waveguide_heater: CrossSectionSpec = "strip_heater_metal",
cross_section_heater_undercut:
CrossSectionSpec = "strip_heater_metal_undercut",
with_undercut: bool = True,
via_stack: ComponentSpec | None = "via_stack_heater_mtop",
port_orientation1: int | None = None,
port_orientation2: int | None = None,
heater_taper_length: float | None = 5.0,
ohms_per_square: float | None = None,
**kwargs) -> Component
Returns a thermal phase shifter.
dimensions from Jacques et al. (2019)
Arguments:
length
- of the waveguide.length_undercut_spacing
- from undercut regions.length_undercut
- length of each undercut section.length_straight_input
- from input port to where trenches start.heater_width
- in um.cross_section_heater
- for heated sections. heater metal only.cross_section_waveguide_heater
- for heated sections.cross_section_heater_undercut
- for heated sections with undercut.with_undercut
- isolation trenches for higher efficiency.via_stack
- via stack.port_orientation1
- left via stack port orientation.port_orientation2
- right via stack port orientation.heater_taper_length
- minimizes current concentrations from heater to via_stack.ohms_per_square
- to calculate resistance.cross_section
- for waveguide ports.kwargs
- cross_section common settings.
straight_heater_metal_simple¶
@cell
def straight_heater_metal_simple(
length: float = 320.0,
length_straight_input: float = 15.0,
heater_width: float = 2.5,
cross_section_heater: CrossSectionSpec = "heater_metal",
cross_section_waveguide_heater: CrossSectionSpec = "strip_heater_metal",
via_stack: ComponentSpec | None = "via_stack_heater_mtop",
port_orientation1: int | None = None,
port_orientation2: int | None = None,
heater_taper_length: float | None = 5.0,
ohms_per_square: float | None = None,
**kwargs) -> Component
Returns a thermal phase shifter that has properly fixed electrical connectivity to extract a suitable electrical netlist and models. dimensions from Jacques et al. (2019)
Arguments:
length
- of the waveguide.length_undercut_spacing
- from undercut regions.length_undercut
- length of each undercut section.length_straight_input
- from input port to where trenches start.heater_width
- in um.cross_section_heater
- for heated sections. heater metal only.cross_section_waveguide_heater
- for heated sections.cross_section_heater_undercut
- for heated sections with undercut.with_undercut
- isolation trenches for higher efficiency.via_stack
- via stack.port_orientation1
- left via stack port orientation.port_orientation2
- right via stack port orientation.heater_taper_length
- minimizes current concentrations from heater to via_stack.ohms_per_square
- to calculate resistance.cross_section
- for waveguide ports.kwargs
- cross_section common settings.
gdsfactory.components.mzi_arm¶
mzi_arm¶
@cell
def mzi_arm(length_y_left: float = 0.8,
length_y_right: float = 0.8,
length_x: float = 0.1,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
straight_x: ComponentSpec | None = None,
straight_y: ComponentSpec | None = None,
**kwargs) -> Component
Mzi.
Arguments:
length_y_left
- vertical length.length_y_right
- vertical length.length_x
- horizontal length.bend
- 90 degrees bend library.straight
- straight function.straight_x
- straight for length_x.straight_y
- straight for length_y.kwargs
- cross_section settings... code::
B__Lx__B | | Ly Lyr | | B B
gdsfactory.components.straight_array¶
straight_array¶
@gf.cell
def straight_array(n: int = 4,
spacing: float = 4.0,
straight: ComponentSpec = straight_function,
**kwargs) -> Component
Array of straights connected with grating couplers.
useful to align the 4 corners of the chip
Arguments:
n
- number of straights.spacing
- edge to edge straight spacing.straight
- straight straight Component or library.kwargs
- straight settings.
gdsfactory.components.splitter_chain¶
splitter_chain¶
@gf.cell
def splitter_chain(splitter: ComponentSpec = mmi1x2,
columns: int = 3,
bend: ComponentSpec = bend_s) -> Component
Chain of splitters.
Arguments:
splitter
- splitter to chain.columns
- number of splitters to chain.bend
- bend to connect splitters... code::
__o5 __| __| |__o4 o1 _| |__o3 |__o2
__o2 o1 _| |__o3
gdsfactory.components.straight_pin¶
Straight Doped PIN waveguide.
straight_pin¶
@gf.cell
def straight_pin(length: float = 500.0,
cross_section: CrossSectionSpec = pin,
via_stack: ComponentSpec = via_stack_slab_m3,
via_stack_width: float = 10.0,
via_stack_spacing: float = 2,
taper: ComponentSpec | None = taper_strip_to_ridge,
**kwargs) -> Component
Returns rib waveguide with doping and via_stacks used for PN and PIN modulators.
For PIN: Fatemi et al. (2018)
500um length for PI phase shift
https://
to go beyond 2PI, you will need at least 1mm
https://
For PN:
Typical lengths in practice are 2-5mm depending on doping,engineering and application:
https://
Arguments:
length
- of the waveguide.cross_section
- for the waveguide.via_stack
- for the via_stacks.via_stack_width
- width of the via_stack.via_stack_spacing
- spacing between via_stacks.taper
- optional taper.kwargs
- cross_section settings.
gdsfactory.components.straight_heater_doped_strip¶
Top view.
.. code::
length
<-|--------|--------------------------------->
| | length_section
|<--------------------------->
length_via_stack
|<------>|
|________|_______________________________
/| |____________________| |
/ |viastack| |via_stack |
\ | size |____________________| |
\|________|____________________|__________|
| |
cross_section_heater| |
| |
| |
|__________|
cross_section
.. code::
|<------width------>|
____________ ___________________ ______________
| | | undoped Si | | |
|layer_heater| | intrinsic region |<----------->| layer_heater |
|____________| |___________________| |______________|
<------------>
heater_gap heater_width
gdsfactory.components.cdc¶
cdc¶
@gf.cell
def cdc(length: float = 30.0,
gap: float = 0.5,
period: float = 0.220,
dc: float = 0.5,
dx: float = 10.0,
dy: float = 5.0,
width_top: float = 2.0,
width_bot: float = 0.75,
fins: bool = False,
fin_size: tuple[float, float] = (0.2, 0.05),
cross_section: CrossSectionSpec = strip,
**kwargs) -> Component
Grating-Assisted Contra-Directional Coupler.
Arguments:
length : Length of the coupling region.
gap
- Distance between the two straights.period
- Period of the grating.dc
- Duty cycle of the grating. Must be between 0 and 1.width_top
- Width of the top straight in the coupling region.width_bot
- Width of the bottom straight in the coupling region.dx
- size of bends in x-direction.dy
- size of bends in y-direction.fins
- IfTrue
, adds fins to the input/output straights. In this case a different template for the component must be specified. This feature is useful when performing electron-beam lithography and using different beam currents for fine features (helps to reduce stitching errors).fin_size
- Specifies the x- and y-size of thefins
. Defaults to 200 nm x 50 nm.cross_section
- CrossSection spec.kwargs: cross_section kwargs.
gdsfactory.components.mzi_lattice¶
mzi_lattice¶
@cell
def mzi_lattice(coupler_lengths: tuple[float, ...] = (10.0, 20.0),
coupler_gaps: tuple[float, ...] = (0.2, 0.3),
delta_lengths: tuple[float, ...] = (10.0, ),
mzi: ComponentSpec = mzi_coupler,
splitter: ComponentSpec = coupler_function,
**kwargs) -> Component
Mzi lattice filter.
Arguments:
coupler_lengths
- list of length for each coupler.coupler_gaps
- list of coupler gaps.delta_lengths
- list of length differences.mzi
- function for the mzi.splitter
- splitter function.keyword Args:
length_y
- vertical length for both and top arms.length_x
- horizontal length.bend
- 90 degrees bend library.straight
- straight function.straight_y
- straight for length_y and delta_length.straight_x_top
- top straight for length_x.straight_x_bot
- bottom straight for length_x.cross_section
- for routing (sxtop/sxbot to combiner)... code::
| | | | | | | | cp1==| |===cp2=====| |=== .... ===cp_last=== | | | | | | | | DL1 | DL2 | | | | | || | | ||
mzi_lattice_mmi¶
@cell
def mzi_lattice_mmi(coupler_widths=(None, None),
coupler_widths_tapers: tuple[float, ...] = (
1.0,
1.0,
),
coupler_lengths_tapers: tuple[float, ...] = (
10.0,
10.0,
),
coupler_lengths_mmis: tuple[float, ...] = (
5.5,
5.5,
),
coupler_widths_mmis: tuple[float, ...] = (
2.5,
2.5,
),
coupler_gaps_mmis: tuple[float, ...] = (
0.25,
0.25,
),
taper_functions_mmis=(
taper_function,
taper_function,
),
straight_functions_mmis=(straight_function,
straight_function),
cross_sections_mmis=("strip", "strip"),
delta_lengths: tuple[float, ...] = (10.0, ),
mzi=mmi_coupler_function,
splitter=mmi_splitter_function,
**kwargs) -> Component
Mzi lattice filter, with MMI couplers.
Arguments:
coupler_widths
- (for each MMI coupler, list of) input and output straight width.coupler_widths_tapers
- (for each MMI coupler, list of) interface between input straights and mmi region.coupler_lengths_tapers
- (for each MMI coupler, list of) into the mmi region.coupler_lengths_mmis
- (for each MMI coupler, list of) in x direction.coupler_widths_mmis
- (for each MMI coupler, list of) in y direction.coupler_gaps_mmis
- (for each MMI coupler, list of) (width_taper + gap between tapered wg)/2.taper_functions_mmis
- (for each MMI coupler, list of) taper function.straight_functions_mmis
- (for each MMI coupler, list of) straight function.cross_sections_mmis
- (for each MMI coupler, list of) spec.delta_lengths
- list of length differences.mzi
- function for the mzi.splitter
- splitter function.keyword Args:
length_y
- vertical length for both and top arms.length_x
- horizontal length.bend
- 90 degrees bend library.straight
- straight function.straight_y
- straight for length_y and delta_length.straight_x_top
- top straight for length_x.straight_x_bot
- bottom straight for length_x.cross_section
- for routing (sxtop/sxbot to combiner)... code::
| | | | | | | | cp1==| |===cp2=====| |=== .... ===cp_last=== | | | | | | | | DL1 | DL2 | | | | | || | | ||
gdsfactory.components.cdsem_coupler¶
CD SEM structures.
cdsem_coupler¶
@cell
def cdsem_coupler(width: float = 0.45,
length: float = 420.0,
gaps: tuple[float, ...] = (0.15, 0.2, 0.25),
cross_section: CrossSectionSpec = "strip",
text: ComponentSpec | None = text_rectangular_mini,
spacing: float = 3) -> Component
Returns 2 coupled waveguides gap sweep.
Arguments:
width
- for the waveguide.length
- for the line.gaps
- list of gaps for the sweep.cross_section
- for the lines.text
- optional text for labels.spacing
- edge to edge spacing.
gdsfactory.components.ring_double_pn¶
ring_double_pn¶
@gf.cell
def ring_double_pn(add_gap: float = 0.3,
drop_gap: float = 0.3,
radius: float = 5.0,
doping_angle: float = 85,
cross_section: CrossSectionFactory = cross_section_rib,
pn_cross_section: CrossSectionFactory = cross_section_pn,
doped_heater: bool = True,
doped_heater_angle_buffer: float = 10,
doped_heater_layer: LayerSpec = "NPP",
doped_heater_width: float = 0.5,
doped_heater_waveguide_offset: float = 2.175,
heater_vias: ComponentSpec = heater_vias,
**kwargs) -> gf.Component
Returns add-drop pn ring with optional doped heater.
Arguments:
add_gap
- gap to add waveguide.drop_gap
- gap to drop waveguide.radius
- for the bend and coupler.doping_angle
- angle in degrees representing portion of ring that is doped.length_x
- ring coupler length.length_y
- vertical straight length.cross_section
- cross_section spec for non-PN doped rib waveguide sections.pn_cross_section
- cross section of pn junction.doped_heater
- boolean for if we include doped heater or not.doped_heater_angle_buffer
- angle in degrees buffering heater from pn junction.doped_heater_layer
- doping layer for heater.doped_heater_width
- width of doped heater.doped_heater_waveguide_offset
- distance from the center of the ring waveguide to the center of the doped heater.heater_vias
- components specifications for heater viaskwargs
- cross_section settings.
gdsfactory.components.logo¶
logo¶
@cell
def logo(text: str = "GDSFACTORY") -> Component
Returns GDSfactory logo.
gdsfactory.components.triangles¶
triangle¶
@cell
def triangle(x: float = 10,
xtop: float = 0,
y: float = 20,
ybot: float = 0,
layer: LayerSpec = "WG") -> Component
Return triangle.
Arguments:
x
- base xsize.xtop
- top xsize.y
- ysize.ybot
- bottom ysize.layer
- layer... code::
xtop _ |
|
|
y|
|
|
|______|ybot x
triangle2¶
@cell
def triangle2(spacing: float = 3, **kwargs)
Return 2 triangles (bot, top).
Arguments:
spacing
- between top and bottom.
Arguments:
x
- base xsize.xtop
- top xsize.y
- ysize.ybot
- bottom ysize.layer
- layer... code:: _ |
|
|
|
|
|
|
| | spacing | / | / | / | / | / |_/
triangle4¶
@cell
def triangle4(**kwargs)
Return 4 triangles.
Arguments:
x
- base xsize.xtop
- top xsize.y
- ysize.ybot
- bottom ysize.layer
- layer... code::
/ |
/ |
/ |
/ |
/ |
/ |
/ |
| | | \ | / \ | / \ | / \ | / \ | / \ |_/
gdsfactory.components.loop_mirror¶
Sagnac loop_mirror.
loop_mirror¶
@gf.cell
def loop_mirror(component: ComponentSpec = mmi1x2,
bend90: ComponentSpec = "bend_euler") -> Component
Returns Sagnac loop_mirror.
Arguments:
component
- 1x2 splitter.bend90
- 90 deg bend.
loop_mirror_with_delay¶
@gf.cell
def loop_mirror_with_delay(
loop_mirror: ComponentSpec = loop_mirror,
spiral: ComponentSpec = spiral_external_io) -> Component
Returns loop_mirror with spiral for delay.
Arguments:
loop_mirror
- loop_mirror spec.spiral
- for delay.
Notes:
Delay = 13e-12.
delay = length/speed¶
length=delay*speed¶
13e-123e8/4.21e6
gdsfactory.components.grating_coupler_rectangular_arbitrary_slab¶
grating_coupler_rectangular_arbitrary_slab¶
@gf.cell
def grating_coupler_rectangular_arbitrary_slab(
gaps: Floats = _gaps,
widths: Floats = _widths,
width_grating: float = 11.0,
length_taper: float = 150.0,
polarization: str = "te",
wavelength: float = 1.55,
taper: ComponentSpec = taper_strip_to_slab150,
layer_slab: LayerSpec | None = "SLAB150",
slab_offset: float = 2.0,
fiber_angle: float = 15,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Grating coupler uniform (grating with rectangular shape not elliptical). Therefore it needs a longer taper. Grating teeth are straight instead of elliptical.
Arguments:
gaps
- list of gaps.widths
- list of widths.width_grating
- um.length_taper
- um.polarization
- ‘te’ or ‘tm’.wavelength
- in um.taper
- function.layer_slab
- for pedestal.slab_offset
- from edge.fiber_angle
- in degrees.cross_section
- for input waveguide port.kwargs
- cross_section settings... code::
side view fiber
/ / / / / / / /
|-||-||-|__ layer layer_slab | o1 ______________|
top view _________ /| | | | | / | | | | | /taper_angle /_ | | | | | wg_width | | | | | | \ | | | | | \ | | | | | \ | | | | | ||||_| <--> taper_length
gdsfactory.labels.write_labels¶
Find GDS labels and write them to a CSV file.
find_labels¶
def find_labels(gdspath: PathType,
layer_label: LayerSpec = "LABEL",
prefix: str = "opt_") -> Iterator[tuple[str, float, float]]
Return text label and locations iterator from a GDS file.
Klayout does not support label rotations.
Arguments:
gdspath
- for the gds.layer_label
- for the labels.prefix
- for the labels to select.Returns
string
- for the label.x
- x position (um).y
- y position (um).angle
- in degrees.
write_labels_klayout¶
def write_labels_klayout(gdspath: PathType,
layer_label: LayerSpec = "LABEL",
filepath: PathType | None = None,
prefix: str = "opt_") -> Path
Load GDS and extracts labels in KLayout text and coordinates.
Returns CSV filepath with each row:
- Text
- x
- y
- rotation (degrees)
Arguments:
gdspath
- for the mask.layer_label
- for labels to write.filepath
- for CSV file. Defaults to gdspath with CSV suffix.prefix
- for the labels to write.
write_labels_gdstk¶
def write_labels_gdstk(gdspath: Path,
prefixes: list[str] = ("opt", "elec"),
layer_label: LayerSpec = "LABEL",
filepath: PathType | None = None,
debug: bool = False) -> Path
Load GDS and extracts label text and coordinates.
Returns CSV filepath with each row:
- Text
- x
- y
- rotation (degrees)
Arguments:
gdspath
- for the mask.prefix
- for the labels to write.layer_label
- for labels to write.filepath
- for CSV file. Defaults to gdspath with CSV suffix.debug
- prints the label.
gdsfactory.labels.add_label_yaml¶
Add label YAML.
add_label_yaml¶
@pydantic.validate_call
def add_label_yaml(
component: gf.Component,
port_prefixes: list[str] = ("opt_", "_elec"),
layer: LayerSpec = "LABEL",
metadata_ignore: list[str] | None = ignore,
metadata_include_parent: list[str] | None = None,
metadata_include_child: list[str] | None = None) -> gf.Component
Returns Component with measurement label.
Arguments:
component
- to add labels to.port_types
- list of port types to label.layer
- text label layer.metadata_ignore
- list of settings keys to ignore. Works with flatdict setting:subsetting.metadata_include_parent
- parent metadata keys to include. Works with flatdict setting:subsetting.metadata_include_child
- child metadata keys to include.
gdsfactory.labels¶
Design For Testing module includes test protocols.
gdsfactory.labels.merge_test_metadata¶
Merge mask metadata with test labels to return test_metadata.
parse_csv_data¶
def parse_csv_data(csv_labels_path: Path,
ignore_prefix: str = "METR_") -> list[list[str]]
Returns CSV labels as a list of strings.
get_cell_from_label_brackets¶
def get_cell_from_label_brackets(label: str) -> str
Get cell name from the label (cell_name is in parenthesis).
component_name_from_string_with_dashes¶
def component_name_from_string_with_dashes(label: str) -> str
Returns cell_name assuming opt-GratingName-ComponentName-PortName
merge_test_metadata¶
def merge_test_metadata(labels_path: PathType,
mask_metadata: dict[str, Any],
component_name_from_string:
Callable = component_name_from_string_with_dashes,
filepath: PathType | None = None) -> DictConfig
Returns a test metadata dict config of labeled cells by merging GDS labels in CSV and YAML mask metadata.
Arguments:
labels_path
- for test labels in CSV.mask_metadata
- dict with test metadata.component_name_from_string
- returns label string.filepath
- Optional path to write test metadata... code::
CSV labels ------- |--> merge_test_metadata dict | YAML metadata ----
gdsfactory.labels.ehva¶
add_label_ehva¶
@pydantic.validate_call
def add_label_ehva(
component: gf.Component,
die: str = "demo",
prefix_to_type: dict[str, str] = prefix_to_type_default,
layer: Layer = (66, 0),
metadata_ignore: list[str] | None = None,
metadata_include_parent: list[str] | None = None,
metadata_include_child: list[str] | None = None) -> gf.Component
Returns Component with measurement labels.
Arguments:
component
- to add labels to.die
- string.port_types
- list of port types to label.layer
- text label layer.metadata_ignore
- list of settings keys to ignore. Works with flatdict setting:subsetting.metadata_include_parent
- includes parent metadata. Works with flatdict setting:subsetting.
gdsfactory.labels.siepic¶
SiEPIC labels one grating coupler from the fiber array using a GDS label.
get_input_label_text¶
def get_input_label_text(port: Port,
gc: ComponentReference,
gc_index: int | None = None,
component_name: str | None = None,
username: str = "YourUserName") -> str
Return label for port and a grating coupler.
Arguments:
port
- component port.gc
- grating coupler reference.gc_index
- grating coupler index.component_name
- optional component name.username
- for the label.
get_input_labels¶
def get_input_labels(
io_gratings: list[ComponentReference],
ordered_ports: list[Port],
component_name: str,
layer_label: tuple[int, int] = (10, 0),
gc_port_name: str = "o1",
port_index: int = 1,
get_input_label_text_function: Callable = get_input_label_text
) -> list[Label]
Return list of labels for all component ports.
Arguments:
io_gratings
- list of grating_coupler references.ordered_ports
- list of ports.component_name
- name.layer_label
- for the label.gc_port_name
- grating_coupler port.port_index
- index of the port.get_input_label_text_function
- function.
add_fiber_array_siepic¶
@cell
def add_fiber_array_siepic(
component: ComponentSpec = straight,
component_name: str | None = None,
gc_port_name: str = "o1",
get_input_labels_function: Callable = get_input_labels,
with_loopback: bool = False,
optical_routing_type: int = 0,
fanout_length: float = 0.0,
grating_coupler: ComponentSpec = grating_coupler_te,
cross_section: CrossSectionSpec = "strip",
layer_label: LayerSpec = (10, 0),
**kwargs) -> Component
Returns component with grating couplers and labels on each port.
Routes all component ports south. Can add align_ports loopback reference structure on the edges.
Arguments:
component
- to connect.component_name
- for the label.gc_port_name
- grating coupler input port name ‘o1’.get_input_labels_function
- function to get input labels for grating couplers.with_loopback
- True, adds loopback structures.optical_routing_type
- None: autoselection, 0: no extension.fanout_length
- None # if None, automatic calculation of fanout length.grating_coupler
- grating coupler instance, function or list of functions.cross_section
- spec.layer_label
- for label.
gdsfactory.routing.sort_ports¶
sort_ports¶
def sort_ports(ports1: list[Port], ports2: list[Port],
enforce_port_ordering: bool) -> tuple[list[Port], list[Port]]
Returns two lists of sorted ports.
Arguments:
ports1
- the starting portsports2
- the ending portsenforce_port_ordering
- if True, only ports2 will be sorted in accordance with ports1. If False, the two lists will be sorted independently.
gdsfactory.routing.get_bundle¶
Routes bundles of ports (river routing).
get bundle is the generic river routing function get_bundle calls different function depending on the port orientation.
- get_bundle_same_axis: ports facing each other with arbitrary pitch on each side
- get_bundle_corner: 90Deg / 270Deg between ports with arbitrary pitch
- get_bundle_udirect: ports with direct U-turns
- get_bundle_uindirect: ports with indirect U-turns
get_bundle¶
def get_bundle(ports1: list[Port],
ports2: list[Port],
separation: float | None = None,
extension_length: float = 0.0,
straight: ComponentSpec = straight_function,
bend: ComponentSpec = bend_euler,
with_sbend: bool = False,
sort_ports: bool = True,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = "strip",
start_straight_length: float | None = None,
end_straight_length: float | None = None,
path_length_match_loops: int | None = None,
path_length_match_extra_length: float = 0.0,
path_length_match_modify_segment_i: int = -2,
enforce_port_ordering: bool = True,
**kwargs) -> list[Route]
Returns list of routes to connect two groups of ports.
Routes connect a bundle of ports with a river router. Chooses the correct routing function depending on port angles.
Arguments:
ports1
- list of starting ports.ports2
- list of end ports.separation
- bundle separation (center to center). Defaults to cross_section.width + cross_section.gapextension_length
- adds straight extension.bend
- function for the bend. Defaults to euler.with_sbend
- use s_bend routing when there is no space for manhattan routing.sort_ports
- sort port coordinates.cross_section
- CrossSection or function that returns a cross_section.start_straight_length
- straight length at the beginning of the route. If None, uses default value for the routing CrossSection.end_straight_length
- end length at the beginning of the route. If None, uses default value for the routing CrossSection.path_length_match_loops
- Integer number of loops to add to bundle for path length matching. Path-length matching won’t be attempted if this is set to None.path_length_match_extra_length
- Extra length to add to path length matching loops (requires path_length_match_loops != None).path_length_match_modify_segment_i
- Index of straight segment to add path length matching loops to (requires path_length_match_loops != None).enforce_port_ordering
- If True, enforce that the ports are connected in the specific order.
Arguments:
width
- main layer waveguide width (um).layer
- main layer for waveguide.width_wide
- wide waveguides width (um) for low loss routing.auto_widen
- taper to wide waveguides for low loss routing.auto_widen_minimum_length
- minimum straight length for auto_widen.taper_length
- taper_length for auto_widen.bbox_layers
- list of layers for rectangular bounding box.bbox_offsets
- list of bounding box offsets.cladding_layers
- list of layers to extrude.cladding_offsets
- list of offset from main Section edge.radius
- bend radius (um).sections
- list of Sections(width, offset, layer, ports).port_names
- for input and output (‘o1’, ‘o2’).port_types
- for input and output: electrical, optical, vertical_te ...min_length
- defaults to 1nm = 10e-3um for routing.snap_to_grid
- can snap points to grid when extruding the path.steps
- specify waypoint steps to route using get_bundle_from_steps.waypoints
- specify waypoints to route using get_bundle_from_steps... plot:: :include-source:
import gdsfactory as gf
gf.cell def test_north_to_south(): dy = 200.0 xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650]
pitch = 10.0 N = len(xs1) xs2 = [-20 + i * pitch for i in range(N // 2)] xs2 += [400 + i * pitch for i in range(N // 2)]
a1 = 90 a2 = a1 + 180
ports1 = [gf.Port(f"top_{i}“, center=(xs1[i], +0), width=0.5, orientation=a1, layer=(1,0)) for i in range(N)] ports2 = [gf.Port(f"bot_{i}”, center=(xs2[i], dy), width=0.5, orientation=a2, layer=(1,0)) for i in range(N)]
c = gf.Component() routes = gf.routing.get_bundle(ports1, ports2) for route in routes: c.add(route.references)
return c
gf.config.set_plot_options(show_subports=False) c = test_north_to_south() c.plot()
get_bundle_same_axis¶
def get_bundle_same_axis(ports1: list[Port],
ports2: list[Port],
separation: float = 5.0,
end_straight_length: float = 0.0,
start_straight_length: float = 0.0,
bend: ComponentSpec = bend_euler,
sort_ports: bool = True,
path_length_match_loops: int | None = None,
path_length_match_extra_length: float = 0.0,
path_length_match_modify_segment_i: int = -2,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = "strip",
enforce_port_ordering: bool = True,
**kwargs) -> list[Route]
Semi auto-routing for two lists of ports.
Arguments:
ports1
- first list of ports.ports2
- second list of ports.separation
- minimum separation between two straights.end_straight_length
- offset to add at the end of each straight.start_straight_length
- in um.bend
- spec.sort_ports
- sort the ports according to the axis.path_length_match_loops
- Integer number of loops to add to bundle for path length matching (won’t try to match if None).path_length_match_extra_length
- Extra length to add to path length matching loops (requires path_length_match_loops != None).path_length_match_modify_segment_i
- Index of straight segment to add path length matching loops to (requires path_length_match_loops != None).cross_section
- CrossSection or function that returns a cross_section.enforce_port_ordering
- If True, will enforce that the ports are conneceted as ordered.kwargs
- cross_section settings.
Returns:
[route_filter(r) for r in routes]
list of lists of coordinates
e.g with default get_route_from_waypoints
,
returns a list of elements which can be added to a component
The routing assumes manhattan routing between the different ports.
The strategy is to modify start_straight
and end_straight
for each
straight such that straights do not collide.
.. code::
1 X X X X X X |-----------| | | | | |-----------------------| | |-----| | | |---------------| | | | || |------| | | 2 X X X X X X
ports1
- at the topports2
- at the bottomThe general strategy is: Group tracks which would collide together and apply the following method on each group:
if x2 >= x1, increase
end_straight
(as seen on the right 3 ports) otherwise, decreaseend_straight
(as seen on the first 2 ports)We deal with negative end_straight by doing at the end end_straights = end_straights - min(end_straights)
This method deals with different metal track/wg/wire widths too.
get_min_spacing¶
def get_min_spacing(ports1: list[Port],
ports2: list[Port],
sep: float = 5.0,
radius: float = 5.0,
sort_ports: bool = True) -> float
Returns the minimum amount of spacing in um required to create a fanout.
get_bundle_same_axis_no_grouping¶
def get_bundle_same_axis_no_grouping(ports1: list[Port],
ports2: list[Port],
sep: float = 5.0,
route_filter: Callable = get_route,
start_straight_length: float
| None = None,
end_straight_length: float | None = None,
sort_ports: bool = True,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> list[Route]
Returns a list of route elements.
Compared to get_bundle_same_axis, this function does not do any grouping. It is not as smart for the routing, but it can fall back on arclinarc connection if needed. We can also specify longer start_straight and end_straight
Semi auto routing for optical ports
The routing assumes manhattan routing between the different ports.
The strategy is to modify start_straight
and end_straight
for each
straight such that straights do not collide.
We want to connect something like this:
::
2 X X X X X X |-----------| | | | | |-----------------------| | |-----| | | |---------------| | | | || |------| | | 1 X X X X X X
start
is at the bottom
end
is at the top
The general strategy is:
if x2 < x1, decrease start straight
, and increase end_straight
(as seen on left two ports)
otherwise, decrease start_straight
, and increase end_straight
(as seen on the last 3 right ports)
Arguments:
ports1
- first list of optical ports.ports2
- second list of optical ports.axis
- specifies “X” or “Y” direction along which the port is going.route_filter
- ManhattanExpandedWgConnector or ManhattanWgConnector. or any other connector function with the same input.radius
- bend radius. If unspecified, uses the default radius.start_straight_length
- offset on the starting length before the first bend.end_straight_length
- offset on the ending length after the last bend.sort_ports
- True -> sort the ports according to the axis. False -> no sort applied.cross_section
- CrossSection or function that returns a cross_section.
Returns:
a list of routes the connecting straights.
gdsfactory.routing.add_fiber_single¶
add_fiber_single¶
@cell
def add_fiber_single(component: ComponentSpec = straight_function,
grating_coupler=grating_coupler_te,
layer_label: LayerSpec | None = "LABEL",
fiber_spacing: float = 50,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
route_filter: Callable = get_route_from_waypoints,
min_input_to_output_spacing: float = 200.0,
optical_routing_type: int = 2,
with_loopback: bool = True,
loopback_xspacing: float = 50.0,
component_name: str | None = None,
gc_port_name: str = "o1",
zero_port: str | None = "o1",
get_input_label_text_loopback_function: None
| (Callable) = get_input_label_text_dash_loopback,
get_input_label_text_function: Callable
| None = get_input_label_text_dash,
select_ports: Callable = select_ports_optical,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns component with grating couplers and labels on each port.
It returns grating couplers in north-south orientation. First routes input port gc_port_name south, and other ports north. You can always rotate it for East-West orientation.
Arguments:
component
- component or component function to connect to grating couplers.grating_coupler
- grating coupler instance, function or list of functions.layer_label
- for test and measurement label.fiber_spacing
- between outputs.bend
- bend spec.straight
- straight sepc.route_filter
- function to get route waypoints.min_input_to_output_spacing
- spacing from input to output fiber (um).optical_routing_type
- None: autoselection, 0: no extension.with_loopback
- True, adds loopback reference straight waveguide.loopback_xspacing
- spacing from loopback xmin to component.xmin.component_name
- optional name of component.gc_port_name
- grating coupler waveguide port name.zero_port
- name of the port to move to (0, 0) for the routing to work correctly.get_input_label_text_loopback_function
- for the loopbacks input label.get_input_label_text_function
- for the grating couplers input label.get_input_labels_function
- function to get input labels for grating couplers.select_ports
- function to select ports.cross_section
- cross_section spec.
Arguments:
max_y0_optical
- in um.straight_separation
- spacing between waveguides.list_port_labels
- None, add labels to port indices in this list.connected_port_list_ids
- None # only for type 0 optical routing.nb_optical_ports_lines
- 1.force_manhattan
- False.excluded_ports
- list of ports to exclude.grating_indices
- None.routing_method
- function to ge the route.gc_rotation
- grating_coupler rotation (deg).kwargs
- cross_section settings... code::
assumes grating coupler has o1 input port facing west at xmin = 0
/| | | | | | / | | | | | | o1| | | | | | | \ | | | | | | | |||||_|
| xmin = 0
.. plot:: :include-source:
import gdsfactory as gf
c = gf.components.crossing() cc = gf.routing.add_fiber_single( component=c, optical_routing_type=0, grating_coupler=gf.components.grating_coupler_elliptical_te, ) cc.plot()
gdsfactory.routing.add_fiber_array¶
add_fiber_array¶
@gf.cell
def add_fiber_array(component: ComponentSpec = straight_function,
grating_coupler: ComponentSpecOrList = grating_coupler_te,
gc_port_name: str = "o1",
gc_port_labels: tuple[str, ...] | None = None,
component_name: str | None = None,
select_ports: Callable = select_ports_optical,
cross_section: CrossSectionSpec = "strip",
get_input_labels_function: Callable
| None = get_input_labels_dash,
layer_label: LayerSpec | None = "LABEL",
**kwargs) -> Component
Returns component with south routes and grating_couplers.
You can also use pads or other terminations instead of grating couplers.
Arguments:
component
- component spec to connect to grating couplers.grating_coupler
- spec for route terminations.gc_port_name
- grating coupler input port name.gc_port_labels
- grating coupler list of labels.component_name
- optional for the label.select_ports
- function to select ports.cross_section
- cross_section function.get_input_labels_function
- function to get input labels. None skips labels.layer_label
- optional layer for grating coupler label.
Arguments:
bend
- bend spec.straight
- straight spec.taper
- taper spec.get_input_label_text_loopback_function
- function to get input label test.get_input_label_text_function
- for labels.fanout_length
- if None, automatic calculation of fanout length.max_y0_optical
- in um.with_loopback
- True, adds loopback structures.straight_separation
- from edge to edge.list_port_labels
- None, adds TM labels to port indices in this list.connected_port_list_ids
- names of ports only for type 0 optical routing.nb_optical_ports_lines
- number of grating coupler lines.force_manhattan
- Falseexcluded_ports
- list of port names to exclude when adding gratings.grating_indices
- list of grating coupler indices.routing_straight
- function to route.routing_method
- get_route.optical_routing_type
- None: auto, 0: no extension, 1: standard, 2: check.gc_rotation
- fiber coupler rotation in degrees. Defaults to -90.input_port_indexes
- to connect... plot:: :include-source:
import gdsfactory as gf
c = gf.components.crossing() cc = gf.routing.add_fiber_array( component=c, optical_routing_type=2, grating_coupler=gf.components.grating_coupler_elliptical_te, with_loopback=False ) cc.plot()
gdsfactory.routing.manhattan¶
gen_sref¶
def gen_sref(structure: Component, rotation_angle: float, x_reflection: bool,
port_name: str, position: Coordinate) -> ComponentReference
Place reference of port_name
of structure
at position
.
Keep this convention, otherwise phidl port transform won’t work
- 1 Mirror
- 2 Rotate
- 3 Move
transform¶
def transform(points: ndarray,
translation: ndarray,
angle_deg: int = 0,
x_reflection: bool = False) -> ndarray
Transform points.
Arguments:
points (np.array of shape (N,2) ): points to be transformed.
translation
2d like array - translation vector.angle_deg
- rotation angle.x_reflection
bool - if True, mirror the shape across the x axis (y -> -y).
reverse_transform¶
def reverse_transform(points: ndarray,
translation: Coordinate = (0, 0),
angle_deg: int = 0,
x_reflection: bool = False) -> ndarray
Args are the following.
points (np.array of shape (N,2) ): points to be transformed. translation (2d like array): translation vector. angle_deg: rotation angle. x_reflection: if True, mirror the shape across the x axis (y -> -y).
get_route_error¶
def get_route_error(points,
cross_section: CrossSection | None = None,
layer_path: LayerSpec = (208, 0),
layer_label: LayerSpec = (66, 0),
layer_marker: LayerSpec = (207, 0),
references: list[ComponentReference] | None = None,
with_sbend: bool = False) -> Route
Returns route with error markers.
Arguments:
points
- route waypoints.cross_section
- Optional cross_section.layer_path
- for the error.layer_label
- for the labels.layer_marker
- for point markers.references
- optional list of references.with_sbend
- if True raises Error so we can use it in try, except if False raises Warning.
round_corners¶
def round_corners(points: Coordinates,
straight: ComponentSpec = straight_function,
bend: ComponentSpec = bend_euler,
taper: ComponentSpec | None = None,
straight_fall_back_no_taper: ComponentSpec | None = None,
mirror_straight: bool = False,
straight_ports: list[str] | None = None,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = strip,
on_route_error: Callable = get_route_error,
with_point_markers: bool = False,
with_sbend: bool = False,
**kwargs) -> Route
Returns Route.
- reference list with rounded straight route from a list of manhattan points.
- ports: Tuple of ports.
- length: route length (float).
Arguments:
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
- spec.on_route_error
- function to run when route fails.with_point_markers
- add route points markers (easy for debugging).with_sbend
- add sbend in case there are routing errors.kwargs
- cross_section settings.
generate_manhattan_waypoints¶
def generate_manhattan_waypoints(input_port: Port,
output_port: Port,
start_straight_length: float | None = None,
end_straight_length: float | None = None,
min_straight_length: float | None = None,
bend: ComponentSpec = bend_euler,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = strip,
**kwargs) -> ndarray
Return waypoints for a Manhattan route between two ports.
Arguments:
input_port
- source port.output_port
- destination port.start_straight_length
- Optional start length.end_straight_length
- in um.min_straight_length
- in um.bend
- bend spec.cross_section
- spec.kwargs
- cross_section settings.
route_manhattan¶
def route_manhattan(input_port: Port,
output_port: Port,
straight: ComponentSpec = straight_function,
taper: ComponentSpec | None = None,
start_straight_length: float | None = None,
end_straight_length: float | None = None,
min_straight_length: float | None = None,
bend: ComponentSpec = bend_euler,
with_sbend: bool = True,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = strip,
with_point_markers: bool = False,
on_route_error: Callable = get_route_error,
**kwargs) -> Route
Generates the Manhattan waypoints for a route.
Then creates the straight, taper and bend references that define the route, or create an SBend route.
Arguments:
input_port
- input.output_port
- output.straight
- function.taper
- add taper.start_straight_length
- in um.end_straight_length
- in um.min_straight_length
- min length of straight for any intermediate segment.bend
- bend spec.with_sbend
- add sbend in case there are routing errors.cross_section
- spec.with_point_markers
- add point markers in the route.kwargs
- cross_section settings.
gdsfactory.routing.add_pads¶
add_pads_bot¶
@cell
def add_pads_bot(component: ComponentSpec = straight_heater_metal,
select_ports: Callable = select_ports_electrical,
port_names: Strs | None = None,
component_name: str | None = None,
cross_section: CrossSectionSpec = "metal_routing",
get_input_labels_function: Callable | None = None,
layer_label: LayerSpec = "TEXT",
pad_port_name: str = "e1",
pad_port_labels: tuple[str, ...] | None = None,
pad: ComponentSpec = pad_rectangular,
bend: ComponentSpec = "wire_corner",
straight_separation: float | None = None,
pad_spacing: float | str = "pad_spacing",
optical_routing_type: int | None = 1,
**kwargs) -> Component
Returns new component with ports connected bottom pads.
Arguments:
component
- component spec to connect to.select_ports
- function to select_ports.port_names
- optional port names. Overrides select_ports.component_name
- optional for the label.cross_section
- cross_section spec.get_input_labels_function
- function to get input labels. None skips labels.layer_label
- optional layer for grating coupler label.pad_port_name
- pad input port name.pad_port_labels
- pad list of labels.pad
- spec for route terminations.bend
- bend spec.straight_separation
- from wire edge to edge. Defaults to xs.width+xs.gappad_spacing
- in um. Defaults to pad_spacing constant from the PDK.optical_routing_type
- None: auto, 0: no extension, 1: standard, 2: check.
Arguments:
straight
- straight spec.taper
- taper spec.get_input_label_text_loopback_function
- function to get input label test.get_input_label_text_function
- for labels.fanout_length
- if None, automatic calculation of fanout length.max_y0_optical
- in um.with_loopback
- True, adds loopback structures.list_port_labels
- None, adds TM labels to port indices in this list.connected_port_list_ids
- names of ports only for type 0 optical routing.nb_optical_ports_lines
- number of grating coupler lines.force_manhattan
- Falseexcluded_ports
- list of port names to exclude when adding gratings.grating_indices
- list of grating coupler indices.routing_straight
- function to route.routing_method
- get_route.gc_rotation
- fiber coupler rotation in degrees. Defaults to -90.input_port_indexes
- to connect... plot:: :include-source:
import gdsfactory as gf c = gf.components.pad() cc = gf.routing.add_pads_bot(component=c, port_names=(“e1”, “e4”), fanout_length=50) cc.plot()
add_pads_top¶
@gf.cell
def add_pads_top(component: ComponentSpec = straight_heater_metal,
**kwargs) -> Component
Returns new component with ports connected top pads.
Arguments:
component
- component spec to connect to.
Arguments:
select_ports
- function to select_ports.port_names
- optional port names. Overrides select_ports.component_name
- optional for the label.cross_section
- cross_section function.get_input_labels_function
- function to get input labels. None skips labels.layer_label
- optional layer for grating coupler label.pad_port_name
- pad input port name.pad_port_labels
- pad list of labels.pad
- spec for route terminations.bend
- bend spec.straight_separation
- from edge to edge.straight
- straight spec.taper
- taper spec.get_input_label_text_loopback_function
- function to get input label test.get_input_label_text_function
- for labels.fanout_length
- if None, automatic calculation of fanout length.max_y0_optical
- in um.with_loopback
- True, adds loopback structures.list_port_labels
- None, adds TM labels to port indices in this list.connected_port_list_ids
- names of ports only for type 0 optical routing.nb_optical_ports_lines
- number of grating coupler lines.force_manhattan
- Falseexcluded_ports
- list of port names to exclude when adding gratings.grating_indices
- list of grating coupler indices.routing_straight
- function to route.routing_method
- get_route.optical_routing_type
- None: auto, 0: no extension, 1: standard, 2: check.gc_rotation
- fiber coupler rotation in degrees. Defaults to -90.input_port_indexes
- to connect... plot:: :include-source:
import gdsfactory as gf c = gf.components.pad() cc = gf.routing.add_pads_top(component=c, port_names=(“e1”, “e4”), fanout_length=50) cc.plot()
gdsfactory.routing.route_south¶
route_south¶
def route_south(component: Component,
optical_routing_type: int = 1,
excluded_ports: tuple[str, ...] | None = None,
straight_separation: Number = 4.0,
io_gratings_lines: list[list[ComponentReference]]
| None = None,
gc_port_name: str = "o1",
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
taper: ComponentSpec | None = taper_function,
select_ports: Callable = select_ports_optical,
port_names: Strs | None = None,
cross_section: CrossSectionSpec = strip,
**kwargs) -> Routes
Returns Routes to route a component ports to the south.
Arguments:
component
- component to route.optical_routing_type
- routing heuristic1
or2
1
uses the component size info to estimate the box size.2
only looks at the optical port positions to estimate the size.excluded_ports
- list of port names to NOT route.straight_separation
- in um.io_gratings_lines
- list of ports to which the ports produced by this function will be connected. Supplying this information helps avoiding straight collisions.gc_port_name
- grating coupler port name.bend
- spec.straight
- spec.taper
- spec.select_ports
- function to select_ports.port_names
- optional port names. Overrides select_ports.cross_section
- cross_section spec.kwargs
- cross_section settings.Works well if the component looks roughly like a rectangular box with: north ports on the north of the box. south ports on the south of the box. east ports on the east of the box. west ports on the west of the box.
.. plot:: :include-source:
import gdsfactory as gf
c = gf.components.ring_double() c = gf.Component() ref = c << gf.components.ring_double() r = gf.routing.route_south(ref) for e in r.references: c.add(e) c.plot()
gdsfactory.routing.route_sharp¶
based on phidl.routing.
path_straight¶
def path_straight(port1: Port, port2: Port) -> Path
Return waypoint path between port1 and port2 in a straight line.
Useful when ports point directly at each other.
Arguments:
port1
- start port.port2
- end port.
path_L¶
def path_L(port1: Port, port2: Port) -> Path
Return waypoint path between port1 and port2 in an L shape.
Useful when orthogonal ports can be directly connected with one turn.
Arguments:
port1
- start port.port2
- end port.
path_U¶
def path_U(port1: Port, port2: Port, length1=200) -> Path
Return waypoint path between port1 and port2 in a U shape.
Useful when ports face the same direction or toward each other.
Arguments:
port1
- start port.port2
- end port.length1
- Length of segment exiting port1. Should be larger than bend radius.
path_J¶
def path_J(port1: Port, port2: Port, length1=200, length2=200) -> Path
Return waypoint path between port1 and port2 in a J shape. Useful when orthogonal ports cannot be connected directly with an L shape.
Arguments:
port1
- start port.port2
- end port.length1
- Length of segment exiting port1. Should be larger than bend radius.length2
- Length of segment exiting port2. Should be larger than bend radius.
path_C¶
def path_C(port1: Port,
port2: Port,
length1=100,
left1=100,
length2=100) -> Path
Return waypoint path between port1 and port2 in a C shape. Useful when ports are parallel and face away from each other.
Arguments:
port1
- start port.port2
- end port.length1
- Length of route segment coming out of port1. Should be at larger than bend radius.left1
- Length of route segment that turns left (or right if negative) from port1. Should be larger than twice the bend radius.length2
- Length of route segment coming out of port2. Should be larger than bend radius.
path_manhattan¶
def path_manhattan(port1: Port, port2: Port, radius: float) -> Path
Return waypoint path between port1 and port2 using manhattan routing. Routing uses straight, L, U, J, or C waypoint path as needed. Ports must face orthogonal or parallel directions.
Arguments:
port1
- start port.port2
- end port.radius
- Bend radius for 90 degree bend.
path_Z¶
def path_Z(port1: Port, port2: Port, length1=100, length2=100) -> Path
Return waypoint path between port1 and port2 in a Z shape. Ports can have any relative orientation.
Arguments:
port1
- start port.port2
- end port.length1
- Length of route segment coming out of port1.length2
- Length of route segment coming out of port2.
path_V¶
def path_V(port1: Port, port2: Port) -> Path
Return waypoint path between port1 and port2 in a V shape. Useful when ports point to a single connecting point.
Arguments:
port1
- start port.port2
- end port.
route_sharp¶
@gf.cell
def route_sharp(port1: Port,
port2: Port,
width: float | None = None,
path_type: str = "manhattan",
manual_path=None,
layer: LayerSpec | None = None,
cross_section: CrossSectionSpec | None = None,
port_names: tuple[str, str] = ("o1", "o2"),
**kwargs) -> Component
Returns Component route between ports.
Arguments:
port1
- start port.port2
- end port.width
- None, int, float, array-like[2], or CrossSection. If None, the route linearly tapers between the widths the ports If set to a single number (e.g.width=1.7
): makes a fixed-width route If set to a 2-element array (e.g.width=[1.8,2.5]
): makes a route whose width varies linearly from width[0] to width[1] If set to a CrossSection: uses the CrossSection parameters for the route. path_type : {‘manhattan’, ‘L’, ‘U’, ‘J’, ‘C’, ‘V’, ‘Z’, ‘straight’, ‘manual’}.manual_path
- array-like[N][2] or Path Waypoint for manual route.layer
- Layer to put route on.kwargs
- Keyword arguments passed to the waypoint path function.Method of waypoint path creation. Should be one of:
- manhattan: automatic manhattan routing (see path_manhattan() ).
- L: L-shaped path for orthogonal ports that can be directly connected.
- U: U-shaped path for parallel or facing ports.
- J: J-shaped path for orthogonal ports that cannot be directly connected.
- C: C-shaped path for ports that face away from each other.
- Z: Z-shaped path with three segments for ports at any angles.
- V: V-shaped path with two segments for ports at any angles.
- straight: straight path for ports that face each other.
- manual: use an explicit waypoint path provided in manual_path.
.. plot:: :include-source:
import gdsfactory as gf
c = gf.Component(“pads”) c1 = c << gf.components.pad(port_orientation=None) c2 = c << gf.components.pad(port_orientation=None)
c2.movex(400) c2.movey(-200)
route = c << gf.routing.route_sharp(c1.ports[“e4”], c2.ports[“e1”], path_type=“L”) c.plot()
gdsfactory.routing.get_bundle_from_steps¶
get_bundle_from_steps¶
def get_bundle_from_steps(ports1: list[Port],
ports2: list[Port],
steps: list[Step] | None = None,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
taper: ComponentSpec | None = taper_function,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = "strip",
sort_ports: bool = True,
separation: float | None = None,
path_length_match_loops: int | None = None,
path_length_match_extra_length: float = 0.0,
path_length_match_modify_segment_i: int = -2,
enforce_port_ordering: bool = True,
**kwargs) -> list[Route]
Returns a list of routes formed by the given waypoints steps.
Can add bends instead of corners and optionally tapers in straight sections.
Tapering to wider straights reduces the optical loss and phase errors.
get_bundle_from_steps
is a manual version of get_bundle
and a more convenient version of get_bundle_from_waypoints
.
Arguments:
port1
- start ports (list or dict).port2
- end ports (list or dict).steps
- that define the route (x, y, dx, dy) [{‘dx’: 5}, {‘dy’: 10}].bend
- function that returns bends.straight
- function that returns straight waveguides.taper
- function that returns tapers.cross_section
- for routes.sort_ports
- if True sort ports.separation
- center to center, defaults to ports1 separation.kwargs
- cross_section settings... plot:: :include-source:
from functools import partial import gdsfactory as gf
c = gf.Component(“get_route_from_steps_sample”) w = gf.components.array( partial(gf.components.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 = gf.routing.get_bundle_from_steps( p1, p2,
steps=[{"x"
- 150}], )for route in routes: c.add(route.references) c.plot() c.show(show_ports=True)
gdsfactory.routing.get_route_from_steps¶
get_route_from_steps¶
def get_route_from_steps(port1: Port,
port2: Port,
steps: list[Step] | None = None,
bend: ComponentSpec = "bend_euler",
taper: ComponentSpec | None = "taper",
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = "strip",
**kwargs) -> Route
Returns a route formed by the given waypoints steps.
Uses smooth euler bends instead of corners and optionally tapers in straight sections.
Tapering to wider straights reduces the optical loss when auto_widen=True.
get_route_from_steps
is a manual version of get_route
and a more concise and convenient version of get_route_from_waypoints
Arguments:
port1
- start port.port2
- end port.steps
- that define the route (x, y, dx, dy) [{‘dx’: 5}, {‘dy’: 10}].bend
- function that returns bends.straight
- straight spec.taper
- taper spec.cross_section
- cross_section spec.kwargs
- cross_section settings... plot:: :include-source:
import gdsfactory as gf
c = gf.Component(“get_route_from_steps_sample”) w = gf.components.straight() left = c << w right = c << w right.move((100, 80))
obstacle = gf.components.rectangle(size=(100, 10), port_type=None) obstacle1 = c << obstacle obstacle2 = c << obstacle obstacle1.ymin = 40 obstacle2.xmin = 25
p1 = left.ports[‘o2’] p2 = right.ports[‘o2’] route = gf.routing.get_route_from_steps( port1=p1, port2=p2, steps=[
{"x"
- 20},{"y"
- 20},{"x"
- 120},{"y"
- 80}, ], ) c.add(route.references) c.plot() c.show(show_ports=True)
gdsfactory.routing.get_route_astar¶
Node Objects¶
class Node()
__init__¶
def __init__(parent=None, position: tuple = ()) -> None
Initializes a node. A node is a point on the grid.
get_route_astar¶
def get_route_astar(component: Component,
port1: Port,
port2: Port,
resolution: float = 1,
avoid_layers: list[LayerSpec] | None = None,
distance: float = 1,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Route
A* routing function. Finds a route between two ports avoiding obstacles.
Arguments:
component
- Component the route, and ports belong to.port1
- input.port2
- output.resolution
- discretization resolution in um. Lower resolution can help avoid accidental overlapping between route and components but adds more bends. The resolution decides how many “leaps/hops” the algorithm has to do.avoid_layers
- list of layers to avoid.distance
- distance from obstacles in um.cross_section
- spec.kwargs
- cross_section settings.
gdsfactory.routing.route_fiber_single¶
route_fiber_single¶
def route_fiber_single(
component: Component,
fiber_spacing: float = 50.0,
grating_coupler: ComponentSpec = grating_coupler_te,
min_input_to_output_spacing: float = 200.0,
optical_routing_type: int = 1,
port_names: tuple[str, ...] | None = None,
excluded_ports: tuple[str, ...] | None = None,
component_name: str | None = None,
select_ports: Callable = select_ports_optical,
cross_section: CrossSectionSpec = strip,
**kwargs
) -> tuple[list[ComponentReference | Label], list[ComponentReference]]
Returns route Tuple(references, grating couplers) for single fiber input/output.
Arguments:
component
- to add grating couplers.fiber_spacing
- between grating couplers.grating_coupler
- grating coupler Specmin_input_to_output_spacing
- so opposite fibers do not touchoptical_routing_type
- 0 (basic), 1 (standard), 2 (looks at ports)port_names
- port labels that need connectionexcluded_ports
- ports excluded from routingcomponent_name
- Optional component name.select_ports
- function to select ports.cross_section
- spec.kwargs
- cross_section settings
Returns:
elements
- list of ComponentReferences for routes and labelsgrating_couplers
- list of grating_couplers references.. code::
| |E1 W0| | | |E0 |________|
rotates +90 deg and routes West ports to South
the rest of the original ports (East, North, South) will route south
it calls route_fiber_array twice
route_fiber_array is designed to route ports south
E1 E0 || | | | | | | | | | | | | |______| | W0 1st part routes West ports south
then rotates 180 and routes the rest of the ports North
gdsfactory.routing.route_quad¶
Route for electrical based on phidl.routing.route_quad.
route_quad¶
@gf.cell
def route_quad(port1: Port,
port2: Port,
width1: float | None = None,
width2: float | None = None,
layer: gf.typings.LayerSpec = "M1",
manhattan_target_step: float | None = None) -> gf.Component
Routes a basic quadrilateral polygon directly between two ports.
Arguments:
port1
- Port to start route. port2 : Port objects to end route.width1
- Width of quadrilateral at ports. If None, uses port widths.width2
- Width of quadrilateral at ports. If None, uses port widths.layer
- Layer to put the route on.manhattan
- if not none, min step to manhattanize the polygon.. plot:: :include-source:
import gdsfactory as gf
c = gf.Component() pad1 = c << gf.components.pad(size=(50, 50)) pad2 = c << gf.components.pad(size=(10, 10)) pad2.movex(100) pad2.movey(50) route_gnd = c << gf.routing.route_quad( pad1.ports[“e2”], pad2.ports[“e4”], width1=None, width2=None, ) c.show() c.plot()
gdsfactory.routing¶
Functions to create routes between components.
gdsfactory.routing.get_bundle_path_length_match¶
Routes bundles of ports (river routing).
get_bundle_path_length_match¶
def get_bundle_path_length_match(
ports1: list[Port],
ports2: list[Port],
separation: float = 30.0,
end_straight_length: float | None = None,
extra_length: float = 0.0,
nb_loops: int = 1,
modify_segment_i: int = -2,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = _straight,
taper: ComponentSpec | None = taper_function,
start_straight_length: float = 0.0,
route_filter: Callable = get_route_from_waypoints,
sort_ports: bool = True,
cross_section: CrossSectionSpec | MultiCrossSectionAngleSpec = strip,
enforce_port_ordering: bool = True,
**kwargs) -> list[Route]
Returns list of routes that are path length matched.
Arguments:
ports1
- list of ports.ports2
- list of ports.separation
- between the loops.end_straight_length
- if None tries to determine it.extra_length
- distance added to all path length compensation. Useful is we want to add space for extra taper on all branches.nb_loops
- number of extra loops added in the path.modify_segment_i
- index of the segment that accommodates the new turns default is next to last segment.bend
- for bends.straight
- for straights.taper
- spec.start_straight_length
- in um.route_filter
- get_route_from_waypoints.sort_ports
- sorts ports before routing.cross_section
- factory.kwargs
- cross_section settings.Tips:
- If path length matches the wrong segments, change
modify_segment_i
arguments. - Adjust
nb_loops
to avoid too short or too long segments - Adjust
separation
andend_straight_offset
to avoid compensation collisions
.. plot:: :include-source:
import gdsfactory as gf
c = gf.Component(“path_length_match_sample”)
dy = 2000.0 xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650] pitch = 100.0 N = len(xs1) xs2 = [-20 + i * pitch for i in range(N)]
a1 = 90 a2 = a1 + 180 ports1 = [gf.Port(name=f"top_{i}“, center=(xs1[i], +0), width=0.5, orientation=a1, layer=“WG”) for i in range(N)] ports2 = [gf.Port(name=f"bot_{i}”, center=(xs2[i], dy), width=0.5, orientation=a2, layer=“WG”) for i in range(N)]
routes = gf.routing.get_bundle_path_length_match(ports1, ports2, extra_length=44) for route in routes: c.add(route.references)
gf.config.set_plot_options(show_subports=False) c.plot()
- If path length matches the wrong segments, change
gdsfactory.routing.add_electrical_pads_top¶
add_electrical_pads_top¶
@gf.cell
def add_electrical_pads_top(component: ComponentSpec = straight,
direction: str = "top",
spacing: Float2 = (0.0, 100.0),
pad_array: ComponentSpec = pad_array_function,
select_ports: Callable = select_ports_electrical,
port_names: Strs | None = None,
layer: gf.typings.LayerSpec = "MTOP",
**kwargs) -> Component
Returns new component with electrical ports connected to top pad array.
Arguments:
component
- to route.direction
- ‘top’ or ‘right’, sets direction of the array.spacing
- component to pad spacing.pad_array
- function for pad_array.select_ports
- function to select electrical ports.port_names
- optional port names. Overrides select_ports.layer
- for the routes.**kwargs
- extra kwargs for select ports... plot:: :include-source:
import gdsfactory as gf
c = gf.components.straight_heater_metal() cc = gf.routing.add_electrical_pads_top(component=c, spacing=(-150, 30)) cc.plot()
gdsfactory.routing.route_ports_to_side¶
route_ports_to_side¶
def route_ports_to_side(ports: dict[str, Port] | list[Port] | Component
| ComponentReference,
side: str = "north",
x: float | None = None,
y: float | None = None,
routing_func: Callable = get_route,
**kwargs) -> tuple[list[Route], list[Port]]
Routes ports to a given side.
Arguments:
ports
- list/dict/Component/ComponentReference to route to a side.side
- ‘north’, ‘south’, ‘east’ or ‘west’.x
- position to route ports for east/west. None, uses most east/west value.y
- position to route ports for south/north. None, uses most north/south value.routing_func
- the routing function. By default usesget_route
.
Arguments:
radius
- in um.separation
- in um. extend_bottom/extend_top for east/west routing. extend_left, extend_right for south/north routing.
Returns:
List of routes: with routing elements. List of ports: of the new ports.
.. plot:: :include-source:
import gdsfactory as gf
c = gf.Component(‘sample_route_sides’) dummy = gf.components.nxn(north=2, south=2, west=2, east=2) sides = [“north”, “south”, “east”, “west”] d = 100 positions = [(0, 0), (d, 0), (d, d), (0, d)]
for pos, side in zip(positions, sides): dummy_ref = dummy.ref(position=pos) c.add(dummy_ref) routes, ports = gf.routing.route_ports_to_side(dummy_ref, side, layer=(1, 0)) for route in routes: c.add(route.references) for i, p in enumerate(ports): c.add_port(name=f"{side[0]}{i}", port=p)
c.plot()
route_ports_to_x¶
def route_ports_to_x(list_ports: list[Port],
x: float | str = "east",
separation: float = 10.0,
radius: float = 10.0,
extend_bottom: float = 0.0,
extend_top: float = 0.0,
extension_length: float = 0.0,
y0_bottom: float | None = None,
y0_top: float | None = None,
routing_func: RouteFactory = get_route,
backward_port_side_split_index: int = 0,
start_straight_length: float = 0.01,
dx_start: float | None = None,
dy_start: float | None = None,
**routing_func_args) -> tuple[list[Route], list[Port]]
Returns route to x.
Arguments:
list_ports
- reasonably well behaved list of ports. ports facing north ports are norther than any other ports ports facing south ports are souther ... ports facing west ports are the wester ... ports facing east ports are the easter ...x
- float or string. if float: x coordinate to which the ports will be routed if string: “east” -> route to east if string: “west” -> route to westseparation
- in um.radius
- in um.extend_bottom
- in um.extend_top
- in um.extension_length
- in um.y0_bottom
- in um.y0_top
- in um.routing_func
- to route.backward_port_side_split_index
- integer represents and index in the list of backwards ports (bottom to top) all ports with an index strictly lower or equal are routed bottom all ports with an index larger or equal are routed topdx_start
- override minimum starting x distance.dy_start
- override minimum starting y distance.
Returns:
routes
- list of routesports
- list of the new optical ports- routes the bottom-half of the ports facing opposite side of x
- routes the south ports
- front ports
- north ports
route_ports_to_y¶
def route_ports_to_y(
list_ports: list[Port],
y: float | str = "north",
separation: float = 10.0,
radius: float = 10.0,
x0_left: float | None = None,
x0_right: float | None = None,
extension_length: float = 0.0,
extend_left: float = 0.0,
extend_right: float = 0.0,
routing_func: RouteFactory = get_route,
backward_port_side_split_index: int = 0,
start_straight_length: float = 0.01,
dx_start: float | None = None,
dy_start: float | None = None,
**routing_func_args: dict[Any, Any]) -> tuple[list[Route], list[Port]]
Args are the following.
list_ports: reasonably well behaved list of ports. ports facing north ports are norther than any other ports ports facing south ports are souther ... ports facing west ports are the wester ... ports facing east ports are the easter ...
y: float or string. if float: y coordinate to which the ports will be routed if string: “north” -> route to north if string: “south” -> route to south
backward_port_side_split_index: integer this integer represents and index in the list of backwards ports (sorted from left to right) all ports with an index strictly larger are routed right all ports with an index lower or equal are routed left separation: in um. radius: in um.
Returns:
- a list of Routes
- a list of the new optical ports
First route the bottom-half of the back ports (back ports are the one facing opposite side of x) Then route the south ports then the front ports then the north ports
gdsfactory.routing.validation¶
validate_connections¶
def validate_connections(ports1: list[Port], ports2: list[Port],
routes: list[Route]) -> list[Route]
Validates that a set of Routes indeed connects the port-pairs listed in ports1 and ports2. If the Routes form valid connections between ports1 and ports2, the original Routes will be returned. If not, a RouteWarning will be raised, and a set of error traces will be returned instead.
Arguments:
ports1
- the list of starting ports.ports2
- the list of ending ports.routes
- the list of Route objects, purportedly between ports1 and ports2.
Returns:
A list of Routes. If the input routes are valid, they will be returned as-is. Otherwise, a list of error traces will be returned and a RouteWarning will be raised.
make_error_traces¶
def make_error_traces(ports1: list[Port], ports2: list[Port],
message: str) -> list[Route]
Creates a set of error traces showing the intended connectivity between ports1 and ports2. The specified message will be included in the RouteWarning that is raised.
Arguments:
ports1
- the list of starting ports.ports2
- the list of ending ports.message
- a message to include in the RouteWarning that is raised.
Returns:
A list of Routes (the error traces).
is_invalid_bundle_topology¶
def is_invalid_bundle_topology(ports1: list[Port], ports2: list[Port]) -> bool
Returns True if the bundle is topologically unroutable without introducing crossings.
Arguments:
ports1
- the starting ports of the bundleports2
- the ending ports of the bundle
Returns:
True if the bundle is unroutable. False otherwise.
gdsfactory.routing.fanout¶
fanout_component¶
@cell
def fanout_component(component: ComponentSpec,
port_names: tuple[str, ...],
pitch: tuple[float, float] = (0.0, 20.0),
dx: float = 20.0,
sort_ports: bool = True,
auto_rename_ports: bool = True,
enforce_port_ordering: bool = True,
**kwargs) -> Component
Returns component with Sbend fanout routes.
Arguments:
component
- to fanout ports.port_names
- list of port names.pitch
- target port spacing for new component.dx
- how far the fanout in x direction.sort_ports
- sort ports.auto_rename_ports
- auto_rename_ports.kwargs
- for get_route_sbend... plot:: :include-source:
import gdsfactory as gf c = gf.components.mmi2x2()
cc = gf.routing.fanout_component( component=c, port_names=tuple(c.get_ports_dict(orientation=0).keys()) ) cc.plot()
fanout_ports¶
def fanout_ports(ports: list[gf.Port],
pitch: tuple[float, float] = (0.0, 20.0),
dx: float = 20.0,
**kwargs) -> list[gf.typings.Route]
Returns fanout Sbend routes.
Arguments:
ports
- list of ports.pitch
- target port spacing for new component.dx
- how far the fanout.kwargs
- for route_basic.
gdsfactory.routing.utils¶
flip¶
def flip(port: Port) -> Port
Returns port copy with Flip Port orientation.
direction_ports_from_list_ports¶
def direction_ports_from_list_ports(
optical_ports: list[Port]) -> dict[str, list[Port]]
Returns a dict of WENS ports.
check_ports_have_equal_spacing¶
def check_ports_have_equal_spacing(list_ports: list[Port]) -> float64
Returns port separation.
Raises error if not constant.
get_list_ports_angle¶
def get_list_ports_angle(list_ports: list[Port]) -> float64 | int
Returns the orientation/angle (in degrees) of a list of ports.
gdsfactory.routing.get_route¶
get_route
returns a Manhattan route between two ports.
get_route
only works for an individual routes. For routing groups of ports you need to use get_bundle
instead
To make a route, you need to supply:
- input port
- output port
- bend
- straight
- taper to taper to wider straights and reduce straight loss (Optional)
To generate a straight route:
Generate the backbone of the route. This is a list of manhattan coordinates that the route would pass through if it used only sharp bends (right angles)
Replace the corners by bend references (with rotation and position computed from the manhattan backbone)
Add tapers if needed and if space permits
generate straight portions in between tapers or bends
A Route
is a dataclass with:
- references: list of references for tapers, bends and straight waveguides
- ports: a dict of port name to Port, usually two ports “input” and “output”
- length: a float with the length of the route
get_route¶
@validate_call
def get_route(input_port: Port,
output_port: Port,
bend: ComponentSpec = bend_euler,
with_sbend: bool = False,
straight: ComponentSpec = straight_function,
taper: ComponentSpec | None = None,
start_straight_length: float | None = None,
end_straight_length: float | None = None,
min_straight_length: float | None = None,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = "strip",
**kwargs) -> Route
Returns a Manhattan Route between 2 ports.
The references are straights, bends and tapers.
get_route
is an automatic version of get_route_from_steps
.
Arguments:
input_port
- start port.output_port
- end port.bend
- bend spec.with_sbend
- add sbend in case there are routing errors.straight
- straight spec.taper
- taper spec.start_straight_length
- length of starting straight.end_straight_length
- length of end straight.min_straight_length
- min length of straight for any intermediate segment.cross_section
- spec.kwargs
- cross_section settings... plot:: :include-source:
import gdsfactory as gf
c = gf.Component(‘sample_connect’) mmi1 = c << gf.components.mmi1x2() mmi2 = c << gf.components.mmi1x2() mmi2.move((40, 20)) route = gf.routing.get_route(mmi1.ports[“o2”], mmi2.ports[“o1”], radius=5) c.add(route.references) c.plot()
get_route_from_waypoints¶
def get_route_from_waypoints(waypoints: Coordinates,
bend: Callable = bend_euler,
straight: Callable = straight_function,
taper: Callable | None = taper_function,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Route
Returns a route formed by the given waypoints with bends instead of corners and optionally tapers in straight sections. Tapering to wider straights reduces the optical loss. get_route_from_waypoints
is a manual version of get_route
get_route_from_steps
is a more concise and convenient version of get_route_from_waypoints
also available in gf.routing.
Arguments:
waypoints
- Coordinates that define the route.bend
- function that returns bends.straight
- function that returns straight waveguides.taper
- function that returns tapers.cross_section
- spec.kwargs
- cross_section settings... plot:: :include-source:
import gdsfactory as gf
c = gf.Component(“waypoints_sample”)
w = gf.components.straight() left = c << w right = c << w right.move((100, 80))
obstacle = gf.components.rectangle(size=(100, 10)) obstacle1 = c << obstacle obstacle2 = c << obstacle obstacle1.ymin = 40 obstacle2.xmin = 25
p0x, p0y = left.ports[“o2”].center p1x, p1y = right.ports[“o2”].center o = 10 # vertical offset to overcome bottom obstacle ytop = 20
routes = gf.routing.get_route_from_waypoints( [ (p0x, p0y), (p0x + o, p0y), (p0x + o, ytop), (p1x + o, ytop), (p1x + o, p1y), (p1x, p1y), ], ) c.add(routes.references) c.plot()
gdsfactory.routing.get_input_labels¶
get_input_labels¶
def get_input_labels(
io_gratings: list[ComponentReference],
ordered_ports: list[Port],
component_name: str,
layer_label: LayerSpec,
gc_port_name: str,
get_input_label_text_function=get_input_label_text) -> list[Label]
Returns list of labels for a list of grating coupler references.
Arguments:
io_gratings
- grating coupler references.ordered_ports
- list of ordered_ports.component_name
- component name.layer_label
- layer spec for the label.gc_port_name
- gc_port_name port name.get_input_label_function
- function to get input label.
gdsfactory.routing.factories¶
gdsfactory.routing.path_length_matching¶
path_length_matched_points¶
def path_length_matched_points(list_of_waypoints: list[ndarray],
margin: float = 0.0,
modify_segment_i: int = -2,
extra_length: float = 0.0,
nb_loops: int = 1,
bend: ComponentSpec = bend_euler,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = "strip",
**kwargs) -> list[ndarray]
Several types of paths won’t match correctly. We do not try to handle all the corner cases here. You will need to modify the input list of waypoints in some cases.
Arguments:
list_of_waypoints
- [[p1, p2, p3,...], [q1, q2, q3,...], ...] the number of turns have to be identical (usually means same number of points. exception is if there are some flat angles)margin
- some extra space to budget for in addition to the bend radius in most cases, the default is finemodify_segment_i
- index of the segment which accommodates the new turns default is next to last segment (-2)extra_length
- distance added to all path length compensation. Useful is we want to add space for extra taper on all branchesnb_loops
- number of extra loops added in the path if nb_loops==0, no extra loop is added, instead, in each route, the segment indexed bymodify_segment_i
is elongated to match the longest route inlist_of_waypoints
bend
- bend functioncross_section
- cross_section factory **kwargsReturns
- another list of waypoints where- the path_length of each waypoints list are identical
- the number of turns are identical
path_length_matched_points_add_waypoints¶
def path_length_matched_points_add_waypoints(
list_of_waypoints: list[ndarray],
modify_segment_i: int = -2,
bend: ComponentSpec = bend_euler,
margin: float = 0.0,
extra_length: float = 0.0,
nb_loops: int = 1,
cross_section: CrossSectionSpec | MultiCrossSectionAngleSpec = "strip",
**kwargs) -> list[ndarray]
Args are the following.
list_of_waypoints: a list of list_of_points:
[[p1, p2, p3,...], [q1, q2, q3,...], ...]
- the number of turns have to be identical
(usually means same number of points. exception is if there are
some flat angles)
modify_segment_i: index of the segment which accommodates the new turns
default is next to last segment
bend: for bends
margin: some extra space to budget for in addition to the bend radius
in most cases, the default is fine
extra_length: distance added to all path length compensation.
Useful is we want to add space for extra taper on all branches
nb_loops: number of extra loops added in the path
cross_section: factory
**kwargs: cross_section settings
returns: another list of waypoints where: - the path_length of each waypoints list are identical - the number of turns are identical
Several types of paths won’t match correctly. We do not try to handle all the corner cases here. If the paths are not well behaved, the input list_of_waypoints needs to be modified.
To have flexibility in the path length, we need to add 4 bends One path has to be converted in this way:
.. code::
__
| |
| | This length is adjusted to make all path with the same length
| |
___| |___
gdsfactory.routing.add_electrical_pads_top_dc¶
add_electrical_pads_top_dc¶
@cell
def add_electrical_pads_top_dc(
component: ComponentSpec = straight_heater_metal,
spacing: Float2 = (0.0, 100.0),
pad_array: ComponentSpec = "pad_array",
select_ports: Callable = select_ports_electrical,
get_bundle_function: Callable = get_bundle_electrical,
port_names: Strs | None = None,
**kwargs) -> Component
Returns new component with electrical ports connected to top pad array.
Arguments:
component
- component spec to connect to.spacing
- component to pad spacing.pad_array
- component spec for pad_array.select_ports
- function to select_ports.get_bundle_function
- function to route bundle of ports.port_names
- optional port names. Overrides select_ports.kwargs
- route settings... plot:: :include-source:
import gdsfactory as gf c = gf.components.straight_heater_metal(length=100) c = gf.routing.add_electrical_pads_top_dc(c, width=10) c.plot()
gdsfactory.routing.get_route_sbend¶
get_route_sbend¶
def get_route_sbend(port1: Port, port2: Port, **kwargs) -> Route
Returns an Sbend Route to connect two ports.
Arguments:
port1
- start port.port2
- end port.keyword Args:
npoints
- number of points.with_cladding_box
- square bounding box to avoid DRC errors.cross_section
- function.kwargs
- cross_section settings... plot:: :include-source:
import gdsfactory as gf
c = gf.Component(“demo_route_sbend”) mmi1 = c << gf.components.mmi1x2() mmi2 = c << gf.components.mmi1x2() mmi2.movex(50) mmi2.movey(5) route = gf.routing.get_route_sbend(mmi1.ports[‘o2’], mmi2.ports[‘o1’]) c.add(route.references) c.plot()
gdsfactory.routing.get_bundle_sbend¶
get_bundle_sbend¶
def get_bundle_sbend(ports1: Port,
ports2: Port,
sort_ports: bool = True,
enforce_port_ordering: bool = True,
**kwargs) -> list[Route]
Returns a list of routes from ports1 to ports2.
Arguments:
ports1
- start ports.ports2
- end ports.sort_ports
- sort ports.kwargs
- cross_section settings.
Returns:
list of routes.
gdsfactory.routing.auto_taper¶
taper_to_cross_section¶
def taper_to_cross_section(
port: Port,
cross_section: CrossSectionSpec) -> ComponentReference | None
Returns taper ComponentReference from a port to a given cross-section placed so that it connects to the input port.
Assumes that the taper component has width1
and width2
which map to the input and output port widths.
Arguments:
port
- a port to connect to, usually from a ComponentReferencecross_section
- a cross-section to transition to.. plot:: :include-source:
from gdsfactory.routing.auto_taper import taper_to_cross_section from gdsfactory.cross_section import strip import gdsfactory as gf
c = gf.Component()
create a component reference to connect to¶
wg = c << gf.components.straight()
create a taper reference transitioning to strip from the rib waveguide¶
taper = taper_to_cross_section(wg.ports[‘o1’], strip(width=2.0))
add the taper reference to the parent component¶
c.add(taper) c.plot()
gdsfactory.routing.get_bundle_from_waypoints¶
get_bundle_from_waypoints¶
def get_bundle_from_waypoints(ports1: list[Port],
ports2: list[Port],
waypoints: Coordinates,
straight: ComponentSpec = straight_function,
taper: ComponentSpec = taper_function,
bend: ComponentSpec = bend_euler,
sort_ports: bool = True,
cross_section: CrossSectionSpec
| MultiCrossSectionAngleSpec = strip,
separation: float | None = None,
on_route_error: Callable = get_route_error,
path_length_match_loops: int | None = None,
path_length_match_extra_length: float = 0.0,
path_length_match_modify_segment_i: int = -2,
**kwargs) -> list[Route]
Returns list of routes that connect bundle of ports with bundle of routes.
Routes follow a list of waypoints. Take a look at get_bundle_from_steps for easier definition.
Arguments:
ports1
- list of ports.ports2
- list of ports.waypoints
- list of points defining a route.straight
- function that returns straights.taper
- function that returns tapers.bend
- function that returns bends.sort_ports
- sorts ports.cross_section
- cross_section.separation
- center to center, defaults to ports1 separation.on_route_error
- function to call for routing errors.path_length_match_loops
- Integer number of loops to add to bundle for path length matching (won’t try to match if None).path_length_match_extra_length
- Extra length to add to path length matching loops (requires path_length_match_loops != None).path_length_match_modify_segment_i
- Index of straight segment to add path length matching loops to (requires path_length_match_loops != None).kwargs
- cross_section settings.
gdsfactory.routing.route_fiber_array¶
route_fiber_array¶
def route_fiber_array(
component: Component,
fiber_spacing: str | float = "fiber_array_spacing",
grating_coupler: ComponentSpecOrList = grating_coupler_te,
bend: ComponentSpec = bend_euler,
straight: ComponentSpec = straight_function,
taper: ComponentSpec = taper_function,
fanout_length: float | None = None,
max_y0_optical: None = None,
with_loopback: bool = True,
nlabels_loopback: int = 2,
straight_separation: float = 6.0,
straight_to_grating_spacing: float = 5.0,
optical_routing_type: int | None = None,
connected_port_names: None = None,
nb_optical_ports_lines: int = 1,
force_manhattan: bool = False,
excluded_ports: list[str] | None = None,
grating_indices: list[int] | None = None,
route_filter: Callable = get_route_from_waypoints,
gc_port_name: str = "o1",
gc_rotation: int = -90,
layer_label: LayerSpec = "TEXT",
layer_label_loopback: LayerSpec = "TEXT",
component_name: str | None = None,
x_grating_offset: int = 0,
port_names: Strs | None = None,
get_input_label_text_loopback_function:
Callable = get_input_label_text_dash_loopback,
get_input_label_text_function: Callable | None = get_input_label_text_dash,
get_input_labels_function: Callable | None = get_input_labels_dash,
select_ports: Callable = select_ports_optical,
cross_section: CrossSectionSpec = strip,
**kwargs
) -> tuple[
list[ComponentReference | Label],
list[list[ComponentReference]],
list[Port],
list[Port],
]
Returns component I/O elements for adding grating couplers with a fiber array Many components are fine with the defaults.
Arguments:
component
- component spec to connect to.fiber_spacing
- spacing between the optical fibers.grating_coupler
- grating coupler instance, function or list of functions.bend
- for bends.straight
- straight.fanout_length
- target distance between gratings and the southmost component port. If None, automatically calculated.max_y0_optical
- Maximum y coordinate at which the intermediate optical ports can be set. Usually fine to leave at None.with_loopback
- If True, add compact loopback alignment ports.nlabels_loopback
- number of labels of align ports (0: no labels, 1: first port, 2: both ports2)straight_separation
- min separation between routing straights.straight_to_grating_spacing
- from align ports.optical_routing_type
- There are three options for optical routing.0
is very basic but can be more compact. Can also be used in combination withconnected_port_names
. or to route some components which otherwise fail with type1
.1
is the standard routing.2
uses the optical ports as a guideline for the component’s physical size (instead of using the actual component size). Useful where the component is large due to metal tracks- ``None: leads to an automatic decision based on size and number of I/O of the component.
connected_port_names
- only for type 0 optical routing. Can specify which ports goes to which grating assuming the gratings are ordered from left to right. e.g [‘N0’, ‘W1’,‘W0’,‘E0’,‘E1’, ‘N1’ ] or [4,1,7,3]nb_optical_ports_lines
- number of lines with I/O grating couplers. One line by default.WARNING
- Only works properly if:- nb_optical_ports_lines divides the total number of ports.
- the components have an equal number of inputs and outputs.
force_manhattan
- sometimes port linker defaults to an S-bend due to lack of space to do manhattan. Force manhattan offsets all the ports to replace the s-bend by a straight link. This fails if multiple ports have the same issue.excluded_ports
- ports excluded from routing.grating_indices
- allows to fine skip some grating slots. e.g [0,1,4,5] will put two gratings separated by the pitch. Then there will be two empty grating slots, and after that an additional two gratings.route_filter
- straight and bend factoriesgc_port_name
- grating_coupler port name, where to route straights.gc_rotation
- grating_coupler rotation (deg).layer_label
- for measurement labels.component_name
- name of component.x_grating_offset
- x offset.port_names
- port labels to route_to_fiber_array.get_input_label_text_loopback_function
- function to get input labels for grating couplers.get_input_label_text_function
- for the label.get_input_labels_function
- for the label.select_ports
- function to select ports for which to add grating couplers.kwargs
- cross_section settings.
Returns:
elements
- list of references and labels.gratings
- grating coupler reference list.ports_grating_input_waveguide
- grating coupler input waveguide ports.ports_loopback
- list of grating coupler input waveguide ports.ports_component
- list of optical ports.
gdsfactory.routing.all_angle¶
get_connector¶
def get_connector(name: str) -> Connector
Gets a connector function by name.
Arguments:
name
- the name of the connector function to retrieve.
Returns:
The specified connector function.
vector_intersection¶
def vector_intersection(p0,
a0,
p1,
a1,
max_distance=100000,
raise_error=True) -> np.ndarray | None
Gets the intersection point between two vectors, specified by (point, angle) pairs, (p0, a0) and (p1, a1).
Arguments:
p0
- x,y location of vector 0a0
- angle of vector 0 [degrees]p1
- x,y location of vector 1a1
- angle of vector 1 [degrees]max_distance
- maximum search distance for an intersection [um]raise_error
- if True, raises an error if no intersection is found. Otherwise, returns None in that case.
Returns:
The (x,y) point of intersection, if one is found. Otherwise None.
low_loss_connector¶
def low_loss_connector(port1: Port,
port2: Port,
prioritized_cross_sections: list[CrossSectionSpec]
| None = None,
**kwargs) -> list[ComponentReference]
Routes between two ports, using the lowest-loss cross-section which will fit.
Arguments:
port1
- the starting portport2
- the ending portprioritized_cross_sections
- a list of cross-sections, sorted by preference (starting with most preferred). If None, uses the global variable LOW_LOSS_CROSS_SECTIONS
Arguments:
kwargs are added for API compatibility, but they are ignored.
Returns:
A list of component references comprising the connection
straight_connector¶
def straight_connector(
port1: Port,
port2: Port,
cross_section: CrossSectionSpec = "strip") -> list[ComponentReference]
Connects between the two ports with a straight of the given cross-section.
Arguments:
port1
- the starting port.port2
- the ending port.cross_section
- the cross-section to use.
Returns:
A list of component references comprising the connection.
auto_taper_connector¶
def auto_taper_connector(
port1: Port,
port2: Port,
cross_section: CrossSectionSpec = "strip",
inner_connector: Connector = straight_connector
) -> list[ComponentReference]
Connects the two ports with a straight in the specified cross_section, adding tapers at either end if necessary.
Arguments:
port1
- the first port.port2
- the final port.cross_section
- the primary cross section to use for the route.inner_connector
- the connector to use after attaching tapers.
Returns:
A list of references comprising the connection.
CONNECTORS¶
A dictionary of named connectors which can be used for all-angle routing
get_bundle_all_angle¶
def get_bundle_all_angle(ports1: list[Port],
ports2: list[Port],
steps: list[StepAllAngle] | None = None,
cross_section: CrossSectionSpec = "strip",
bend: ComponentSpec = "bend_euler",
connector: str = "low_loss",
start_angle: float | None = None,
end_angle: float | None = None,
end_connector: str | None = None,
end_cross_section: CrossSectionSpec | None = None,
separation: float | None = None,
**kwargs) -> list[Route]
Connects a bundle of ports, allowing steps which create waypoints at arbitrary, non-manhattan angles.
Arguments:
ports1
- ports at the start of the bundle.ports2
- ports at the end of the bundle.steps
- a list of steps, which contain directives on how to proceed with the route. “x”, “y”, “dx”, “dy”, “ds”, “exit_angle”, “cross_section”, “connector”, “separation”. The first route, between ports1[0] and ports2[0] will take on the role of the primary route, and other routes will follow, given the bundling logic. It is assume that both ports1 and ports2 are sorted.cross_section
- the default cross-section of the bends. Then the specified connector may also use this information for straights in between.bend
- the default component to use for the bends.connector
- the default connector to use to connect between two ports.start_angle
- if defined and different from the angle of port1, will cap the starting port with a bend, as to exit with this angle.end_angle
- if defined, and different from the angle of port2, will cap the ending port with a bend, as to exit with this angle.end_connector
- specifies the connector to use for the final straight segment of the route.end_cross_section
- specifies the cross section to use for the final straight segment of the route.separation
- specifies the separation between adjacent routes. If None, will query each segment’s cross-section’s and choose the largest value.kwargs
- added for compatibility, but in general, kwargs will be ignored with a warning.
Returns:
List of Routes between ports1 and ports2.
.. plot:: :include-source:
import gdsfactory as gf c = gf.Component(“demo”)
mmi = gf.components.mmi2x2(width_mmi=10, gap_mmi=3) mmi1 = c << mmi mmi2 = c << mmi
mmi2.move((100, 30)) mmi2.rotate(30)
routes = gf.routing.get_bundle_all_angle( mmi1.get_ports_list(orientation=0), [mmi2.ports[“o2”], mmi2.ports[“o1”]], connector=None, ) for route in routes: c.add(route.references) c.plot()
gdsfactory.routing.fanout2x2¶
fanout2x2¶
@gf.cell
def fanout2x2(component: ComponentSpec = straight,
port_spacing: float = 20.0,
bend_length: float | None = None,
npoints: int = 101,
select_ports: Callable = select_ports_optical,
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Returns component with Sbend fanout routes.
Arguments:
component
- to fanout.port_spacing
- for the returned component.bend_length
- length of the bend (defaults to port_spacing).npoints
- for sbend.select_ports
- function to select optical_ports ports.cross_section
- cross_section spec.kwargs
- cross_section settings... plot:: :include-source:
import gdsfactory as gf c = gf.components.nxn(west=2, east=2)
cc = gf.routing.fanout2x2(component=c, port_spacing=20) cc.plot()
gdsfactory.routing.get_bundle_corner¶
get_bundle_corner¶
def get_bundle_corner(ports1: list[Port],
ports2: list[Port],
route_filter: Callable[...,
Route] = get_route_from_waypoints,
separation: float = 5.0,
path_length_match_loops: int | None = None,
path_length_match_extra_length: float = 0.0,
path_length_match_modify_segment_i: int = -2,
enforce_port_ordering: bool = True,
**kwargs) -> list[Route]
Connect banks of ports with either 90Deg or 270Deg angle between them.
Arguments:
ports1
- list of start ports.ports2
- list of end ports.route_filter
- filter to apply to the manhattan waypoints e.gget_route_from_waypoints
for deep etch strip straight.separation
- in um.path_length_match_loops
- optional number of loops for path length matching.path_length_match_extra_length
- extra length (um) for path length matching.path_length_match_modify_segment_i
- segment to increase length.enforce_port_ordering
- If True, enforce that the ports are connected in the specific order.
Returns:
returns a list of elements which can be added to a component.
[route_filter(r) for r in routes]
where routes is a list of coordinates list
e.g with default get_route_from_waypoints
.
::
Bend-types
90 Deg bend A1 A2 AN | | ... | | | / / / / / / / B1 ----/ / _/ B2 -----/ / / ... _/ BN --------/
270 Deg bend
/------------
/
/ /-------\
/ / \
| / /--\ | |
| / / | | ...|
| | / B1 B2 BN
| | |
| \ --- A1
| ----- A2
| ...
------ AN
gdsfactory.routing.get_bundle_u¶
get_bundle_udirect¶
def get_bundle_udirect(ports1: list[Port],
ports2: list[Port],
route_filter: Callable = get_route_from_waypoints,
separation: float = 5.0,
start_straight_length: float = 0.01,
end_straight_length: float = 0.01,
bend: ComponentSpec = bend_euler,
path_length_match_loops: int | None = None,
path_length_match_extra_length: float = 0.0,
path_length_match_modify_segment_i: int = -2,
enforce_port_ordering: bool = True,
**kwargs) -> list[Route]
Returns list of routes.
Arguments:
ports1
- list of start ports.ports2
- list of end ports.route_filter
- filter to apply to the manhattan waypoints e.gget_route_from_waypoints
for deep etch strip straight.separation
- between straights.start_straight_length
- in um.end_straight_length
- in um.bend
- bend spec.path_length_match_loops
- Integer number of loops to add to bundle for path length matching (won’t try to match if None).path_length_match_extra_length
- Extra length to add to path length matching loops (requires path_length_match_loops != None).path_length_match_modify_segment_i
- Index of straight segment to add path length matching loops to (requires path_length_match_loops != None).enforce_port_ordering
- If True, enforce that the ports are connected in the specific order.
Returns:
[route_filter(r) for r in routes] where routes is a list of lists of coordinates
e.g with default get_route_from_waypoints
,
returns list of elements which can be added to a component
Used for routing multiple ports back to a bundled input in a component
::
X
- start portsD
- End portsOn this example below, the axis is along X
X------
| X----\ | ... | | X--\ | | | | | D-------------------/ | | ... | | D---------------------/ | D----------------------- D-----------------------
D---------------------\ | ... | | D-------------------\ | | | | | X--/ | | ... | | X----/ | | X------/
get_bundle_uindirect¶
def get_bundle_uindirect(ports1: list[Port],
ports2: list[Port],
route_filter: Callable = get_route_from_waypoints,
separation: float = 5.0,
extension_length: float = 0.0,
start_straight_length: float = 0.01,
end_straight_length: float = 0.01,
enforce_port_ordering: bool = True,
**routing_params) -> list[Route]
Returns list of routes.
Arguments:
ports1
- list of start ports.ports2
- list of end ports.route_filter
- filter to apply to the manhattan waypoints e.gget_route_from_waypoints
for deep etch strip straightseparation
- center to center waveguide spacing.extension_length
- in um.start_straight_length
- extends in um.end_straight_length
- in um.
Returns:
list of routes, where each route has references, ports and length.
Used for routing multiple ports back to a bundled input in a component
::
X
- start portsD
- End portsX------ X---- | ... | | X--\ | | | | | /--------------------------/ | | | | | | /--------------------------/ | | | | | | /--------------------------/ | | | | | --D | ----D | ... ------D /------D | ... | /----D | | /--D | | | | | -------------------------- | | | | --------------------------\ | | | | --------------------------\ | | | | | X--/ | | ... | | X----/ | X------/ ‘’’
gdsfactory.routing.add_electrical_pads_shortest¶
add_electrical_pads_shortest¶
@gf.cell
def add_electrical_pads_shortest(
component: ComponentSpec = straight,
pad: ComponentSpec = "pad",
pad_port_spacing: float = 50.0,
select_ports: Callable = select_ports_electrical,
port_names: Strs | None = None,
port_orientation: float = 90,
layer: gf.typings.LayerSpec = "M3") -> Component
Returns new Component with a pad by each electrical port.
Arguments:
component
- to route.pad
- pad element or function.pad_port_spacing
- spacing between pad and port.select_ports
- function to select ports.port_orientation
- in degrees.port_names
- optional port names. Overrides select_ports.layer
- for the routing... plot:: :include-source:
import gdsfactory as gf c = gf.components.straight_heater_metal(length=100) c = gf.routing.add_electrical_pads_shortest(c, port_orientation=270) c.plot()
gdsfactory.routing.get_routes_bend180¶
get_routes_bend180¶
def get_routes_bend180(ports: list[Port] | dict[str, Port],
bend: ComponentSpec = bend_euler,
cross_section: CrossSectionSpec = strip,
bend_port1: str | None = None,
bend_port2: str | None = None,
**kwargs) -> Routes
Returns routes made by 180 degree bends.
Arguments:
ports
- List or dict of ports.bend
- function for bend.cross_section
- spec.bend_port1
- name.bend_port2
- name.kwargs
- bend settings... plot:: :include-source:
import gdsfactory as gf
c = gf.Component(“get_routes_bend180”) pad_array = gf.components.pad_array(orientation=270) c1 = c << pad_array c2 = c << pad_array c2.rotate(90) c2.movex(1000) c2.ymax = -200
routes_bend180 = gf.routing.get_routes_bend180( ports=c2.get_ports_list(), radius=75 / 2, ) c.add(routes_bend180.references)
routes = gf.routing.get_bundle( c1.get_ports_list(), routes_bend180.ports, ) for route in routes: c.add(route.references) c.plot()
gdsfactory.routing.get_routes_straight¶
get_routes_straight¶
def get_routes_straight(ports: list[Port] | dict[str, Port],
straight: ComponentSpec = straight,
**kwargs) -> Routes
Returns routes made by 180 degree straights.
Arguments:
ports
- List or dict of ports.straight
- function for straight.kwargs
- waveguide settings... plot:: :include-source:
import gdsfactory as gf
c = gf.Component(“get_routes_straight”) pad_array = gf.components.pad_array() c1 = c << pad_array c2 = c << pad_array c2.ymax = -200
routes = gf.routing.get_routes_straight(ports=c1.get_ports_list(), length=200) c.add(routes.references) c.plot()
gdsfactory.difftest¶
GDS regression test. Inspired by lytest.
diff¶
def diff(ref_file: PathType,
run_file: PathType,
xor: bool = True,
test_name: str = "") -> bool
Returns True if files are different, prints differences and shows them in klayout.
Arguments:
ref_file
- reference (old) file.run_file
- run (new) file.xor
- runs xor on every layer between ref and run files.test_name
- prefix for the new cell.
difftest¶
def difftest(component: gf.Component,
test_name: gf.Component | None = None,
dirpath: pathlib.Path = PATH.gds_ref,
xor: bool = True,
dirpath_run: pathlib.Path = PATH.gds_run) -> None
Avoids GDS regressions tests on the GeometryDifference.
If files are the same it returns None. If files are different runs XOR between new component and the GDS reference stored in dirpath and raises GeometryDifference if there are differences and show differences in KLayout.
If it runs for the fist time it just stores the GDS reference.
Arguments:
component
- to test if it has changed.test_name
- used to store the GDS file.dirpath
- directory where reference files are stored.xor
- runs XOR.dirpath_run
- directory to store gds file generated by the test.
gdsfactory.symbols¶
symbol¶
def symbol(func: _F, *args, **kwargs) -> _F
Decorator for Component symbols.
Wraps cell_without_validator Validates type annotations with pydantic.
Implements a cache so that if a symbol has already been built
it will return the component from the cache directly.
This avoids 2 exact cells that are not references of the same cell
You can always over-ride this with cache = False
.
When decorate your functions with cell you get:
- CACHE: avoids creating duplicated cells.
- name: gives Components a unique name based on parameters.
- adds Component.info with default, changed and full component settings.
Arguments:
autoname
bool - if True renames component based on args and kwargs.name
str - Optional (ignored when autoname=True).cache
bool - returns component from the cache if it already exists. if False creates a new component. by default True avoids having duplicated cells with the same name.info
- updates component.info dict.prefix
- name_prefix, defaults to function name.max_name_length
- truncates name beyond some characters (32) with a hash.decorator
- function to run over the component.
symbol_from_cell¶
def symbol_from_cell(func: _F, to_symbol: Callable[[Component, ...],
Component]) -> _F
Creates a symbol function from a component function.
Arguments:
func
- the cell functionto_symbol
- the function that transforms the output of the cell function into a symbol
Returns:
a symbol function
floorplan_with_block_letters¶
@symbol
def floorplan_with_block_letters(
component: Component, copy_layers: LayerSpecs = ("WG", )) -> Component
Returns symbol with same floorplan as component layout, function name and optionally shapes on layers copied from the original layout.
Arguments:
component
- the layout component.copy_layers
- if specified, copies layers from the layout into the symbol.
Returns:
A component representing the symbol.
gdsfactory.write_cells¶
Generate the code from a GDS file based PDK.
get_script¶
def get_script(gdspath: PathType, module: str | None = None) -> str
Returns script for importing a fixed cell.
Arguments:
gdspath
- fixed cell gdspath.module
- if any includes plot directive.
get_import_gds_script¶
def get_import_gds_script(dirpath: PathType, module: str | None = None) -> str
Returns import_gds script from a directory with all the GDS files.
Arguments:
dirpath
- fixed cell directory path.module
- Optional plot directive to plot imported component.
write_cells_recursively¶
def write_cells_recursively(
cell: gdstk.Cell,
unit: float = 1e-6,
precision: float = 1e-9,
timestamp: datetime.datetime | None = _timestamp2019,
dirpath: pathlib.Path | None = None) -> dict[str, Path]
Write gdstk cells recursively.
Arguments:
cell
- gdstk cell.unit
- unit size for objects in library. 1um by default.precision
- for library dimensions (m). 1nm by default.timestamp
- Defaults to 2019-10-25. If None uses current time.dirpath
- directory for the GDS file to write to.
Returns:
gdspaths
- dict of cell name to gdspath.
write_cells¶
def write_cells(gdspath: PathType | None = None,
dirpath: PathType | None = None,
unit: float = 1e-6,
precision: float = 1e-9,
timestamp: datetime.datetime | None = _timestamp2019,
recursively: bool = False,
flatten: bool = False) -> dict[str, Path]
Writes cells into separate GDS files.
Arguments:
gdspath
- GDS file to write cells.dirpath
- directory path to write GDS files to. Defaults to current working directory.unit
- unit size for objects in library. 1um by default.precision
- for object dimensions in the library (m). 1nm by default.timestamp
- Defaults to 2019-10-25. If None uses current time.recursively
- writes all cells recursively. If False writes only top cells.flatten
- flatten cell.
Returns:
gdspaths
- dict of cell name to gdspath.
gdsfactory.grid¶
pack a list of components into a grid.
Adapted from PHIDL https://
grid¶
@cell
def grid(components: tuple[ComponentSpec, ...] | None = None,
spacing: tuple[float, float] = (5.0, 5.0),
separation: bool = True,
shape: tuple[int, int] | None = None,
align_x: str = "x",
align_y: str = "y",
edge_x: str = "x",
edge_y: str = "ymax",
rotation: int = 0,
h_mirror: bool = False,
v_mirror: bool = False,
add_ports_prefix: bool = True,
add_ports_suffix: bool = False) -> Component
Returns Component with a 1D or 2D grid of components.
Arguments:
components
- Iterable to be placed onto a grid. (can be 1D or 2D).spacing
- between adjacent elements on the grid, can be a tuple for different distances in height and width.separation
- If True, guarantees elements are separated with fixed spacing if False, elements are spaced evenly along a grid.shape
- x, y shape of the grid (see np.reshape). If no shape and the list is 1D, if np.reshape were run with (1, -1).align_x
- {‘x’, ‘xmin’, ‘xmax’} for x (column) alignment along.align_y
- {‘y’, ‘ymin’, ‘ymax’} for y (row) alignment along.edge_x
- {‘x’, ‘xmin’, ‘xmax’} for x (column) (ignored if separation = True).edge_y
- {‘y’, ‘ymin’, ‘ymax’} for y (row) along (ignored if separation = True).rotation
- for each component in degrees.h_mirror
- horizontal mirror y axis (x, 1) (1, 0). most common mirror.v_mirror
- vertical mirror using x axis (1, y) (0, y).add_ports_prefix
- adds port names with prefix.add_ports_suffix
- adds port names with suffix.
Returns:
Component containing components grid.
.. plot:: :include-source:
import gdsfactory as gf
components = [gf.components.triangle(x=i) for i in range(1, 10)] c = gf.grid( components, shape=(1, len(components)), rotation=0, h_mirror=False, v_mirror=True, spacing=(100, 100), ) c.plot()
grid_with_text¶
@cell
def grid_with_text(components: tuple[ComponentSpec, ...] | None = None,
text_prefix: str = "",
text_offsets: tuple[Float2, ...] = ((0, 0), ),
text_anchors: tuple[Anchor, ...] = ("cc", ),
text_mirror: bool = False,
text_rotation: int = 0,
text: ComponentSpec | None = text_rectangular,
labels: tuple[str, ...] | None = None,
**kwargs) -> Component
Returns Component with 1D or 2D grid of components with text labels.
Arguments:
components
- Iterable to be placed onto a grid. (can be 1D or 2D).text_prefix
- for labels. For example. ‘A’ will produce ‘A1’, ‘A2’, ...text_offsets
- relative to component anchor. Defaults to center.text_anchors
- relative to component (ce cw nc ne nw sc se sw center cc).text_mirror
- if True mirrors text.text_rotation
- Optional text rotation.text
- function to add text labels.labels
- optional, specify a tuple of labels rather than using a text_prefix.keyword Args:
spacing
- between adjacent elements on the grid, can be a tuple for different distances in height and width.separation
- If True, guarantees elements are separated with fixed spacing if False, elements are spaced evenly along a grid.shape
- x, y shape of the grid (see np.reshape). If no shape and the list is 1D, if np.reshape were run with (1, -1).align_x
- {‘x’, ‘xmin’, ‘xmax’} to perform the x (column) alignment along.align_y
- {‘y’, ‘ymin’, ‘ymax’} to perform the y (row) alignment along.edge_x
- {‘x’, ‘xmin’, ‘xmax’} to perform the x (column) distribution ignored if separation = True.edge_y
- {‘y’, ‘ymin’, ‘ymax’} to perform the y (row) distribution along ignored if separation = True.rotation
- for each reference in degrees... plot:: :include-source:
import gdsfactory as gf
components = [gf.components.triangle(x=i) for i in range(1, 10)] c = gf.grid_with_text( components, shape=(1, len(components)), rotation=0, h_mirror=False, v_mirror=True, spacing=(100, 100), text_offsets=((0, 100), (0, -100)), text_anchors=(“nc”, “sc”), ) c.plot()
gdsfactory.snap¶
snaps values and coordinates to the GDS grid in nm.
gdsfactory.samples.pdk¶
gdsfactory.samples.pdk.fab_d¶
gdsfactory.samples.pdk.fab_d.phase_shifters¶
gdsfactory.samples.pdk.test_fab_c¶
Test all the components in fab_c.
In gdsfactory we use gdslib as a place to store the GDS files.
For your PDK i recommend that you store the store the reference GDS files on the same repo as you store the code. See code below
from __future__ import annotations
from functools import partial
import pathlib
dirpath = pathlib.Path(__file__).absolute().with_suffix(".gds")
def test_gds(component_name: str) -> None:
component = cells[component_name]()
test_name = f"fabc_{component_name}"
difftest(component, test_name=test_name, dirpath=dirpath)
test_gds¶
def test_gds(component_name: str) -> None
Avoid regressions in GDS names, shapes and layers.
Runs XOR and computes the area.
test_settings¶
def test_settings(component_name: str,
data_regression: DataRegressionFixture) -> None
Avoid regressions in component settings and ports.
test_assert_ports_on_grid¶
def test_assert_ports_on_grid(component_name: str) -> None
Ensures all ports are on grid to avoid 1nm gaps.
gdsfactory.samples.pdk.fab_c_to_updk¶
Write FabC example PDK into uPDK YAML format.
gdsfactory.samples.pdk.fab_c¶
FabC example.
get_layer_stack_fab_c¶
def get_layer_stack_fab_c(thickness: float = 350.0) -> LayerStack
Returns generic LayerStack.
gdsfactory.samples.13_component_netlist¶
netlist_yaml¶
@gf.cell
def netlist_yaml() -> Component
Test netlist yaml.
.. code::
arm_top
_____
| |
CP1= =CP2= |_____|
arm_bot
gdsfactory.samples.17_ports¶
Ports define where each port has the follow properties.
- name
- center: (x, y)
- width:
- orientation: (deg) 0, 90, 180, 270. where 0 faces east, 90 (north), 180 (west), 270 (south)
component_with_port¶
@gf.cell
def component_with_port(length: float = 5.0,
width: float = 0.5,
layer: LayerSpec = "WG") -> Component
Returns a component with one port on the west side.
Arguments:
length
- in um.width
- waveguide width in um.layer
- layer.
gdsfactory.samples.30_lidar_pcell¶
LiDAR demo.
Exercise1. increase the number of elements of the phase array.
Exercise2. Make a PCell.
lidar¶
@gf.cell
def lidar(
noutputs=2**2,
antenna_pitch=2.0,
splitter_tree_spacing=(50.0, 70.0)) -> gf.Component
LiDAR demo.
Arguments:
noutputs
- number of outputs.antenna_pitch
- pitch of the antennas.splitter_tree_spacing
- spacing of the splitter tree.
gdsfactory.samples.23_reticle¶
Sample of a reticle top level Component.
gdsfactory.samples.30_lidar_with_pads¶
LiDAR demo with pads.
Exercise1. increase the number of elements of the phase array.
Exercise2. Make a PCell.
gdsfactory.samples.23_reticle_passives_pack¶
mzi_te¶
def mzi_te(**kwargs) -> Component
Returns MZI with TE grating couplers.
demo_pack¶
@gf.cell
def demo_pack() -> Component
Sample reticle.
gdsfactory.samples.19_references¶
gdsfactory.samples.all_angle_routing¶
demo_all_angle_routing¶
@cell
def demo_all_angle_routing() -> Component
Demonstrate all-angle routing.
gdsfactory.samples.big_device¶
big_device¶
@gf.cell
def big_device(size: tuple[float, float] = (400.0, 400.0),
nports: int = 16,
spacing: float = 15.0,
layer: tuple[int, int] = (1, 0),
wg_width: float = 0.5,
cross_section: CrossSectionSpec = "strip") -> Component
Big component with N ports on each side.
Arguments:
size
- x, y.nports
- number of ports.spacing
- in um.layer
- spec.wg_width
- waveguide width in um.cross_section
- spec.
gdsfactory.samples.23_reticle_passives_grid¶
mzi_te¶
def mzi_te(**kwargs) -> Component
Returns MZI with TE grating couplers.
gdsfactory.samples.01_component_pcell_with_pins¶
You can add pins in a pin layer to clearly see the component ports.
straight_narrow¶
@gf.cell
def straight_narrow(length: float = 5.0,
width: float = 0.3,
layer: LayerSpec = (2, 0)) -> gf.Component
Returns straight Component.
Arguments:
length
- of the straight.width
- in um.layer
- layer spec
gdsfactory.samples.30_lidar¶
LiDAR demo.
Exercise1. increase the number of elements of the phase array.
Exercise2. Make a PCell.
gdsfactory.samples.06_remapping_layers¶
You can remap layers.
gdsfactory.samples.demo.drc_errors¶
Write GDS with sample errors.
enclosing¶
@gf.cell
def enclosing(
enclosing: float = 0.1,
layer1: Layer = (40, 0),
layer2: Layer = (41, 0)
) -> Component
Layer1 must be enclosed by layer2 by value.
checks if layer1 encloses (is bigger than) layer2 by value
gdsfactory.samples.demo¶
gdsfactory.samples.demo.layers_sky130¶
gdsfactory.samples.demo.lvs¶
LVS demo.
pads_correct¶
@gf.cell
def pads_correct(pad=gf.components.pad,
cross_section="metal3") -> gf.Component
Returns 2 pads connected with metal wires.
pads_shorted¶
@gf.cell
def pads_shorted(pad=gf.components.pad,
cross_section="metal3") -> gf.Component
Returns 2 pads connected with metal wires.
gdsfactory.samples.demo.layers_xsection¶
gdsfactory.samples.demo.pcell¶
PCell demo.
mzi_with_bend¶
@gf.cell
def mzi_with_bend(radius: float = 10)
Returns MZI interferometer with bend.
gdsfactory.samples.demo.benchmark.snap_demo_phidl¶
gdsfactory.samples.demo.benchmark.fill_demo¶
fill is now slower.
This code takes now 5 seconds to run.
in version 5.18.6 it was taking 0.66 seconds to run
gdsfactory.samples¶
gdsfactory.samples.18_port_markers¶
You can define a function to add pins.
gdsfactory.samples.01_component_pcell¶
Based on phidl tutorial.
We’ll start by assuming we have a function straight() which already exists and makes us a simple straight waveguide. Many functions like this exist in the gdsfactory.components library and are ready-for-use. We write this one out fully just so it’s explicitly clear what’s happening
straight_wide¶
@gf.cell
def straight_wide(length: float = 5.0,
width: float = 1.0,
layer: LayerSpec = (2, 0)) -> gf.Component
Returns straight Component.
Arguments:
length
- of the straight.width
- in um.layer
- layer spec
gdsfactory.samples.12_component_refs¶
Lets create a crossing component with two references to other components (crossing_arm).
- add references to a component (one of the arm references rotated)
- add ports from the child references into the parent cell
- use Component.auto_rename_ports() to rename ports according to their location
crossing_arm¶
@gf.cell
def crossing_arm(
wg_width: float = 0.5,
r1: float = 3.0,
r2: float = 1.1,
taper_width: float = 1.2,
taper_length: float = 3.4,
layer_wg: Layer = (1, 0),
layer_slab: Layer = (2, 0)
) -> Component
Crossing arm.
Arguments:
wg_width
- waveguide width.r1
- radius of the ellipse.r2
- radius of the ellipse.taper_width
- width of the taper.taper_length
- length of the taper.layer_wg
- waveguide layer.layer_slab
- slab layer.
gdsfactory.samples.08_group¶
Group references. Distribute them as you want.
Distribute different references in the X direction.
gdsfactory.samples.15_component_sequence1¶
You can use component_sequence as a convenient function for cascading components, where you need to keep track of multiple tapers, doped sections, heaters etc...
The idea is to associate one symbol per type of section. A section is uniquely defined by the component, input port name and output port name.
The mapping between symbols and components is supplied by a dictionary. The actual chain of components is supplied by a string or a list
gdsfactory.samples.25_slot_cross_section¶
Small demonstration of the slot cross_section utilizing add_center_section=False.
gdsfactory.samples.snap_issue¶
snap issue
gdsfactory.samples.11_component_layout¶
Lets create a new component.
We create a function which returns a gf.Component.
Lets build straight crossing out of a vertical and horizontal arm
- Create a component using a function with the cell decorator to define the name automatically and uniquely.
- Define the polygons in the component
- Add ports to the component so you can connect it with other components
crossing_arm¶
@gf.cell
def crossing_arm(wg_width: float = 0.5,
r1: float = 3.0,
r2: float = 1.1,
taper_width: float = 1.2,
taper_length: float = 3.4) -> Component
Returns a crossing arm.
Arguments:
wg_width
- waveguide width.r1
- radius of the ellipse.r2
- radius of the ellipse.taper_width
- width of the taper.taper_length
- length of the taper.
gdsfactory.samples.07_flattening_device¶
From phidl tutorial.
Flattening a Component
Sometimes you want to remove cell structure from a Component while keeping all of the shapes/polygons intact and in place.
The Component.flatten() method returns a new flatten Component with all the
polygons inside the Component, and removes all the underlying references.
Also, if you specify the single_layer
argument it will move all of the
polygons to that single layer.
gdsfactory.samples.04_connect¶
based on phidl tutorial.
Connecting devices with connect()
The connect command allows you to connect ComponentReference ports together like Lego blocks.
There is an optional parameter called overlap
which is
useful if you have shapes you want to intersect with some overlap,
or with a negative number if you want to separate the ports.
gdsfactory.samples.03_move¶
based on phidl tutorial.
Manipulating geometry 1 - Basic movement and rotation
There are several actions we can take to move and rotate the geometry. These actions include movement, rotation, and reflection.
gdsfactory.samples.21_add_fiber_array¶
You can route all component optical ports to a fiber array.
gdsfactory.samples.snap_bends¶
Snap bends together.
gdsfactory.samples.02_component_autoname¶
When you create components you have to make sure they have unique names.
the cell decorator gives unique names to components that depend on their parameters.
gdsfactory.samples.16_component_sequence2¶
cutback_phase¶
@gf.cell
def cutback_phase(straight_length: float = 100.0,
bend_radius: float = 12.0,
n: int = 2) -> Component
Modulator sections connected by bends.
Arguments:
straight_length
- length of the straight waveguides.bend_radius
- radius of the bends.n
- number of modulator sections.
gdsfactory.samples.24_doe_2¶
Design of Experiment (DOE) with custom add_fiber_array function.
In this case add_fiber_array does not add labels.
You can use gf.add_labels.add_labels_to_ports.
gdsfactory.samples.24_doe_3¶
Design of Experiment (DOE) with custom add_fiber_array function.
In this case add_fiber_array does not add labels.
You can use gf.add_labels.add_labels_to_ports.
gdsfactory.samples.05_remove_layers¶
You can remove a list of layers from a component.
gdsfactory.samples.14_component_connectivity¶
ring_single_sample¶
@gf.cell
def ring_single_sample(gap: float = 0.2,
radius: float = 10.0,
length_x: float = 4.0,
length_y: float = 0.010,
coupler_ring: ComponentSpec = "coupler_ring",
straight: ComponentSpec = "straight",
bend: ComponentSpec = "bend_euler",
cross_section: CrossSectionSpec = "strip",
**kwargs) -> Component
Single bus ring made of a ring coupler.
(cb: bottom) connected with two vertical straights (wl: left, wr: right) two bends (bl, br) and horizontal straight (wg: top).
Arguments:
gap
- gap between for coupler.radius
- for the bend and coupler.length_x
- ring coupler length.length_y
- vertical straight length.coupler_ring
- ring coupler function.straight
- straight function.bend
- 90 degrees bend function.cross_section
- spec.kwargs
- cross_section settings... code::
bl-wt-br | | wl wr length_y | | --==cb==-- gap
length_x
gdsfactory.samples.22_add_pads¶
You can also use the fiber array routing functions for connecting to pads.
gdsfactory.samples.20_components¶
Components. You can adapt some component functions from the gdsfactory.components
module. Each function there returns a Component object. Here are two equivalent functions.
gdsfactory.samples.22_add_fiber_single¶
You can also connect a component with single fiber INPUT and OUTPUTS (no fiber array).
gdsfactory.samples.24_doe¶
Lets pack a doe and export it with metadata.
gdsfactory.install¶
Install Klayout and GIT plugins.
install_gdsdiff¶
def install_gdsdiff() -> None
Install gdsdiff tool for GIT.
get_klayout_path¶
def get_klayout_path() -> pathlib.Path
Returns KLayout path.
copy¶
def copy(src: pathlib.Path, dest: pathlib.Path) -> None
Copy overwriting file or directory.
install_klayout_package¶
def install_klayout_package() -> None
Install gdsfactory KLayout package.
Equivalent to using KLayout package manager.
install_klayout_technology¶
def install_klayout_technology(tech_dir: pathlib.Path,
tech_name: str | None = None) -> None
Install technology to KLayout.
convert_py_to_ipynb¶
def convert_py_to_ipynb(files=py_files,
output_folder=PATH.cwd / "notebooks") -> None
Convert notebooks from markdown to ipynb.
gdsfactory.add_tapers¶
get_ports_and_tapers¶
def get_ports_and_tapers(
component: ComponentSpec,
taper: ComponentSpec = taper_function,
select_ports: Callable | None = select_ports_optical
) -> tuple[list[Port], list[ComponentReference]]
Returns ports and taper elements for a component.
add_tapers¶
@cell
def add_tapers(component: ComponentSpec,
taper: ComponentFactory = taper_function,
select_ports: Callable | None = select_ports_optical,
ports: list[Port] | None = None,
taper_port_name1: str = "o1",
taper_port_name2: str = "o2") -> Component
Returns new component with taper in all optical ports.
Arguments:
component
- spec for the component to add tap ers to.taper
- taper spec for each port.select_ports
- function to select ports.ports
- Optional list of ports to add tapers to. Defaults to select_ports(component.ports).taper_port_name1
- for input.taper_port_name2
- for output.
gdsfactory.add_ports¶
Add ports from pin markers or labels.
add_ports_from_markers_square¶
def add_ports_from_markers_square(component: Component,
pin_layer: LayerSpec = "DEVREC",
port_layer: LayerSpec | None = None,
orientation: int | None = 90,
min_pin_area_um2: float = 0,
max_pin_area_um2: float = 150 * 150,
pin_extra_width: float = 0.0,
port_names: tuple[str, ...] | None = None,
port_name_prefix: str | None = None,
port_type: str = "optical") -> Component
Add ports from square markers at the port center in port_layer.
Arguments:
component
- to read polygons from and to write ports to.pin_layer
- for port markers.port_layer
- for the new created port.orientation
- in degrees 90 north, 0 east, 180 west, 270 south.min_pin_area_um2
- ignores pins with area smaller than min_pin_area_um2.max_pin_area_um2
- ignore pins for area above certain size.pin_extra_width
- 2*offset from pin to straight.port_names
- names of the ports (defaults to {i}).port_name_prefix
- defaults to ‘o’ for optical and ‘e’ for electrical.port_type
- optical, electrical.
add_ports_from_markers_center¶
def add_ports_from_markers_center(component: Component,
pin_layer: LayerSpec = "PORT",
port_layer: LayerSpec | None = None,
inside: bool = False,
tol: float = 0.1,
pin_extra_width: float = 0.0,
min_pin_area_um2: float | None = None,
max_pin_area_um2: float = 150.0 * 150.0,
skip_square_ports: bool = False,
xcenter: float | None = None,
ycenter: float | None = None,
port_name_prefix: str | None = None,
port_type: str = "optical",
short_ports: bool = False,
auto_rename_ports: bool = True,
debug: bool = False) -> Component
Add ports from pins guessing port orientation from component boundary.
Arguments:
component
- to read polygons from and to write ports to.pin_layer
- GDS layer for maker [int, int].port_layer
- for the new created port.inside
- True-> markers inside. False-> markers at center.tol
- tolerance area to search ports at component boundaries xmin, ymin, xmax, xmax.pin_extra_width
- 2*offset from pin to straight.min_pin_area_um2
- ignores pins with area smaller than min_pin_area_um2.max_pin_area_um2
- ignore pins for area above certain size.skip_square_ports
- skips square ports (hard to guess orientation).xcenter
- for guessing orientation of rectangular ports.ycenter
- for guessing orientation of rectangular ports.port_name_prefix
- defaults to ‘o’ for optical and ‘e’ for electrical ports.port_type
- type of port (optical, electrical ...).short_ports
- if the port is on the short side rather than the long side auto_rename_ports:debug
- if True prints ports that are skipped.For inside=False the port location is at the middle of the PIN
.. code::
| | | | ||| |||____ | pin_extra_width/2 > 0 ||| ||| ||| |||____ ||| ||| | __ | |||_| ||
For inside=True all the pin is inside the port
.. code::
| | | | |_ | | | | || | | | | __ | |||__|
dx < dy: port is east or west x > xc: east x < xc: west
dx > dy: port is north or south y > yc: north y < yc: south
dx = dy x > xc: east x < xc: west
add_ports_from_labels¶
def add_ports_from_labels(component: Component,
port_width: float,
port_layer: LayerSpec,
xcenter: float | None = None,
port_name_prefix: str | None = None,
port_type: str = "optical",
get_name_from_label: bool = False,
layer_label: LayerSpec | None = None,
fail_on_duplicates: bool = False,
port_orientation: float | None = None,
guess_port_orientation: bool = True) -> Component
Add ports from labels.
Assumes that all ports have a label at the port center. because labels do not have width, you have to manually specify the ports width
Arguments:
component
- to read polygons from and to write ports to.port_width
- for ports.port_layer
- for the new created port.xcenter
- center of the component, for guessing port orientation.port_name_prefix
- defaults to ‘o’ for optical and ‘e’ for electrical.port_type
- optical, electrical. layer_label:fail_on_duplicates
- raises ValueError for duplicated port names. if False adds incremental suffix (1, 2 ...) to port name.port_orientation
- None for electrical ports.guess_port_orientation
- assumes right: 0, left: 180, top: 90, bot: 270.
add_ports_from_siepic_pins¶
def add_ports_from_siepic_pins(
component: Component,
pin_layer_optical: LayerSpec = "PORT",
port_layer_optical: LayerSpec | None = None,
pin_layer_electrical: LayerSpec = "PORTE",
port_layer_electrical: LayerSpec | None = None) -> Component
Add ports from SiEPIC-type cells, where the pins are defined as paths.
Looks for label, path pairs.
Arguments:
component
- component.pin_layer_optical
- layer for optical pins.port_layer_optical
- layer for optical ports.pin_layer_electrical
- layer for electrical pins.port_layer_electrical
- layer for electrical ports.
gdsfactory.add_loopback¶
Add loopback reference for a grating coupler array.
add_loopback¶
def add_loopback(port1: Port,
port2: Port,
grating: ComponentSpec,
grating_separation: float = 127.0,
grating_rotation: int = -90,
grating_port_name: str = "o1",
bend: ComponentSpec = gf.components.bend_euler,
south_waveguide_spacing: float | None = None,
inside: bool = True,
**kwargs) -> list[ComponentReference]
Return loopback (grating coupler align reference) references.
Input grating generated on the left of port1 Output grating generated on the right of port2
Arguments:
port1
- start port.port2
- end port.grating
- fiber coupler.grating_separation
- grating pitch.grating_rotation
- in degrees.grating_port_name
- fiber port name for grating coupler.bend
- bend spec.south_waveguide_spacing
- spacing from loopback to grating_coupler.ymininside
- add loopback inside.kwargs
- cross_section settings... code::
inside = True
|<-separation | | | | | | | | | | GC | port1 port2 | GC___ | | | | | | south_waveguide_spacing |____________________| |
inside = False
| | | | | | | | | | | GC port1 port2 GC | ___ | | | | | | south_waveguide_spacing |________________________________| |
gdsfactory.fill¶
Dummy fill to keep density constant.
Adapted from PHIDL https://
fill_cell_rectangle¶
@cell
def fill_cell_rectangle(size: Float2 = (20.0, 20.0),
layers: LayerSpecs = (0, 1, 3),
densities: Floats = (0.5, 0.25, 0.7),
inverted=(False, False, False)) -> Component
Returns Component on multiple layers to be used as fill.
based on phidl.geometry
Arguments:
size
- x, y dimensions of the fill area for all layers.layers
- Specific layer(s) to put fill cell rectangle geometry on.densities
- Fill densities for each layer specified inlayers
. Must be the same size aslayers
.inverted
- array-like or bool If true, inverts the fill area for corresponding layer. Must be the same size aslayers
.
fill_rectangle¶
@cell
def fill_rectangle(component: ComponentOrReference,
fill_layers: LayerSpecs,
fill_size=(5.0, 5.0),
avoid_layers: LayerSpecs | None = None,
include_layers: LayerSpecs | None = None,
margin: float = 5.0,
fill_densities: float | Floats = (0.5, 0.25, 0.7),
fill_inverted: list[float] | None = None,
bbox: object | None = None) -> Component
Returns rectangular fill pattern and fills all empty areas.
In the input component and returns a component that contains just the fill Dummy fill keeps density constant during fabrication
Arguments:
component
- Component to fill.fill_layers
- list of layers. fill pattern layers.fill_size
- Rectangular size of the fill element.avoid_layers
- Layers to be avoided (not filled) in D.include_layers
- Layers to be filled, supersedes avoid_layers.margin
- Margin spacing around avoided areas.fill_densities
- defines the fill pattern density (1.0 == fully filled).fill_inverted
- inverts the fill pattern.bbox
- x, y limit the fill pattern to the area defined by this bounding box.
fill_rectangle_custom¶
@cell
def fill_rectangle_custom(component: Component,
fill_cell: ComponentSpec,
spacing: tuple[float, float],
avoid_layers: LayerSpecs | None = None,
margin: float = 5.0,
bbox: object | None = None) -> Component
Returns custom fill pattern to fill all empty areas.
In the input component and returns a component that contains just the fill Dummy fill keeps density constant during fabrication.
Arguments:
component
- Component to fill.fill_cell
- Component to use as fill cell.spacing
- x, y pitch for fill.avoid_layers
- Layers to be avoided (not filled) in D.margin
- Margin spacing around avoided areas.bbox
- x, y limit the fill pattern to the area defined by this bounding box.
- Vogelbacher, F., Nevlacsil, S., Sagmeister, M., Kraft, J., Unterrainer, K., & Hainberger, R. (2019). Analysis of silicon nitride partial Euler waveguide bends. Optics Express, 27(22), 31394. 10.1364/oe.27.031394
- Fatemi, R., Abiri, B., Khachaturian, A., & Hajimiri, A. (2018). High sensitivity active flat optics optical phased array receiver with a two-dimensional aperture. Optics Express, 26(23), 29983. 10.1364/oe.26.029983
- Dong, P., Qian, W., Liang, H., Shafiiha, R., Feng, D., Li, G., Cunningham, J. E., Krishnamoorthy, A. V., & Asghari, M. (2010). Thermally tunable silicon racetrack resonators with ultralow tuning power. Optics Express, 18(19), 20298. 10.1364/oe.18.020298
- Jacques, M., Samani, A., El-Fiky, E., Patel, D., Xing, Z., & Plant, D. V. (2019). Optimization of thermo-optic phase-shifter design and mitigation of thermal crosstalk on the SOI platform. Optics Express, 27(8), 10456. 10.1364/oe.27.010456
- Novack, A., Streshinsky, M., Ding, R., Liu, Y., Lim, A. E.-J., Lo, G.-Q., Baehr-Jones, T., & Hochberg, M. (2014). Progress in silicon platforms for integrated optics. Nanophotonics, 3(4–5), 205–214. 10.1515/nanoph-2013-0034