Import PDK#
Importing a PDK from GDS Files#
For foundry PDKs, we highly recommend using GDSFactory PDKs. See available PDKs here.
If your foundry does not yet have a GDSFactory PDK, you can import a PDK from GDS files into GDSFactory. To do this, you will need:
A GDS file containing all the cells you want to import into the PDK (or multiple GDS files, each containing a separate design).
Ideally, you should also obtain:
KLayout layer properties files – to define the layers available for custom components. This allows you to create a LayerMap that associates layer names with
(GDS_LAYER, GDS_PURPOSE)
.Layer stack information – including material index, thickness, and the Z positions of each layer.
DRC rules – If these are not provided, you can easily build them using KLayout.
GDS files efficiently describe geometry using References, which store each geometry only once in memory. However, most GDS tools lack a clear standard for storing device metadata such as settings, port locations, port widths, and port angles.
gdsfactory
addresses this limitation by storing metadata inside the GDS and provide built-in functions to add pins.
To save a GDS file in gdsfactory
, use:
Component.write_gds()
However if you want to avoid the port and settings metadata you can use:
Component.write_gds(with_metadata=False)
import gdsfactory as gf
from gdsfactory.config import PATH
from gdsfactory.technology import lyp_to_dataclass
c = gf.components.mzi()
c.plot()

You can write GDS files.
gdspath = c.write_gds("extra/mzi.gds")
c.pprint_ports()
┏━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓ ┃ name ┃ width ┃ orientation ┃ layer ┃ center ┃ port_type ┃ ┡━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩ │ o1 │ 0.5 │ 180.0 │ WG (1/0) │ (-10.0, 0.0) │ optical │ │ o2 │ 0.5 │ 0.0 │ WG (1/0) │ (81.10000000000001, 0.0) │ optical │ └──────┴───────┴─────────────┴──────────┴──────────────────────────┴───────────┘
You can read GDS files into gdsfactory thanks to the import_gds
function
import_gds
reads the same GDS file from disk without losing any information.
Gdsfactory stores the settings and the ports as part of the GDS metadata
c = gf.import_gds(gdspath)
c.pprint_ports()
c.plot()
┏━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓ ┃ name ┃ width ┃ orientation ┃ layer ┃ center ┃ port_type ┃ ┡━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩ │ o1 │ 0.5 │ 180.0 │ WG (1/0) │ (-10.0, 0.0) │ optical │ │ o2 │ 0.5 │ 0.0 │ WG (1/0) │ (81.10000000000001, 0.0) │ optical │ └──────┴───────┴─────────────┴──────────┴──────────────────────────┴───────────┘

add ports from pins#
Sometimes the GDS does not have YAML metadata, therefore you need to figure out the port locations, widths and orientations.
gdsfactory provides you with functions that will add ports to the component by looking for pins shapes on a specific layers (port_markers or pins)
There are different pin standards supported to automatically add ports to components:
PINs towards the inside of the port (port at the outer part of the PIN)
PINs with half of the pin inside and half outside (port at the center of the PIN)
PIN with only labels (no shapes). You have to manually specify the width of the port.
Lets add pins, save a GDS and then import it back.
c = gf.components.straight()
c_with_pins = gf.add_pins.add_pins_container(component=c)
c_with_pins.plot()

c_with_pins.ports = [] # lets rely on the pins to extract the ports
gdspath = c_with_pins.write_gds("extra/wg.gds")
c2 = gf.import_gds(gdspath)
c2.plot()

c2.ports # import_gds does not automatically add the pins
[]
c3 = gf.import_gds(gdspath)
c3 = gf.add_ports.add_ports_from_markers_inside(c3, pin_layer="PORT")
c3.plot()

c3.pprint_ports()
┏━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━┓ ┃ name ┃ width ┃ orientation ┃ layer ┃ center ┃ port_type ┃ ┡━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━┩ │ o1 │ 0.5 │ 180.0 │ WG_PIN (1/10) │ (0.0, 0.0) │ optical │ │ o2 │ 0.5 │ 0.0 │ WG_PIN (1/10) │ (10.0, 0.0) │ optical │ └──────┴───────┴─────────────┴───────────────┴─────────────┴───────────┘
Foundries provide PDKs in different formats and commercial tools.
The easiest way to import a PDK into gdsfactory is to:
have each GDS cell into a separate GDS file
have one GDS file with all the cells inside
Have a KLayout layermap. Makes easier to create the layermap.
With that you can easily create the PDK as as python package.
Thanks to having a gdsfactory PDK as a python package you can:
version control your PDK using GIT to keep track of changes and work on a team
write tests of your pdk components to avoid unwanted changes from one component to another.
ensure you maintain the quality of the PDK with continuous integration checks
pin the version of gdsfactory, so new updates of gdsfactory won’t affect your code
name your PDK version using semantic versioning. For example patches increase the last number (0.0.1 -> 0.0.2)
install your PDK easily
pip install pdk_fab_a
and easily interface with other tools
To create a Python package you can start from a customizable template (thanks to cookiecutter)
You can create a python package by running this 2 commands inside a terminal:
pip install cookiecutter
cookiecutter gh:joamatab/python
It will ask you some questions to fill in the template for the python package.
Then you can add the information about the GDS files and the Layers inside that package
print(lyp_to_dataclass(PATH.klayout_lyp))
from gdsfactory.typings import Layer
from gdsfactory.technology.layer_map import LayerMap
class LayerMapFab(LayerMap):
CAPACITOR: Layer = (42, 0)
DEEPTRENCH: Layer = (4, 0)
DEEP_ETCH: Layer = (3, 6)
DICING: Layer = (65, 0)
DRC_EXCLUDE: Layer = (67, 0)
DRC_MARKER: Layer = (205, 0)
DevRec: Layer = (68, 0)
ERROR_PATH: Layer = (1000, 0)
Errors: Layer = (69, 0)
FLOORPLAN: Layer = (64, 0)
FbrTgt: Layer = (81, 0)
GE: Layer = (5, 0)
GENPP: Layer = (26, 0)
GEPPP: Layer = (29, 0)
LABEL_INSTANCES: Layer = (206, 0)
LABEL_OPTICAL_IO: Layer = (201, 0)
LABEL_SETTINGS: Layer = (202, 0)
Lumerical: Layer = (733, 0)
M1: Layer = (41, 0)
M1TILES: Layer = (191, 0)
M2: Layer = (45, 0)
M3: Layer = (49, 0)
METALOPEN: Layer = (46, 0)
MH: Layer = (47, 0)
MONITOR: Layer = (101, 0)
N: Layer = (20, 0)
NOTILE_M1: Layer = (71, 0)
NOTILE_M2: Layer = (72, 0)
NOTILE_M3: Layer = (73, 0)
NP: Layer = (22, 0)
NPP: Layer = (24, 0)
OXIDE_ETCH: Layer = (6, 0)
PDPP: Layer = (27, 0)
PP: Layer = (23, 0)
PPP: Layer = (25, 0)
P_210: Layer = (21, 0)
PinRec: Layer = (1, 10)
PinRecM: Layer = (1, 11)
SHALLOW_ETCH: Layer = (2, 6)
SHOW_PORTS: Layer = (1, 12)
SILICIDE: Layer = (39, 0)
SIM_REGION: Layer = (100, 0)
SITILES: Layer = (190, 0)
SLAB150: Layer = (2, 0)
SLAB150CLAD: Layer = (2, 9)
SLAB90: Layer = (3, 0)
SLAB90CLAD: Layer = (3, 1)
SOURCE: Layer = (110, 0)
TE: Layer = (203, 0)
TM: Layer = (204, 0)
Text: Layer = (66, 0)
VIA1: Layer = (44, 0)
VIA2: Layer = (43, 0)
VIAC: Layer = (40, 0)
WAFER: Layer = (999, 0)
WGCLAD: Layer = (111, 0)
WGN_Nitride: Layer = (34, 0)
WGclad_material: Layer = (36, 0)
Waveguide: Layer = (1, 0)
XS_BOX: Layer = (300, 0)
XS_GE: Layer = (315, 0)
XS_M2: Layer = (399, 0)
XS_MH: Layer = (306, 0)
XS_N: Layer = (320, 0)
XS_NPP: Layer = (321, 0)
XS_OVERLAY: Layer = (311, 0)
XS_OXIDE_M1: Layer = (305, 0)
XS_OXIDE_M2: Layer = (307, 0)
XS_OXIDE_M3: Layer = (311, 0)
XS_OXIDE_MH: Layer = (317, 0)
XS_OXIDE_ML: Layer = (309, 0)
XS_OX_NIT_CLAD: Layer = (304, 0)
XS_OX_SI: Layer = (302, 0)
XS_P: Layer = (330, 0)
XS_PDPP: Layer = (327, 0)
XS_PPP: Layer = (331, 0)
XS_SI: Layer = (301, 0)
XS_SIN: Layer = (319, 0)
XS_SIN2: Layer = (305, 0)
XS_SI_SLAB: Layer = (313, 0)
XS_VIA1: Layer = (308, 0)
XS_VIA2: Layer = (310, 0)
XS_VIAC: Layer = (303, 0)
LAYER = LayerMapFab
# lets create a sample PDK (for demo purposes only) using GDSfactory
# if the PDK is in a commercial tool you can also do this. Make sure you save a single pdk.gds
sample_pdk_cells = gf.grid(
(
gf.components.straight,
gf.components.bend_euler,
gf.components.grating_coupler_elliptical,
)
)
sample_pdk_cells.write_gds("extra/pdk.gds")
sample_pdk_cells

gf.clear_cache()
# we write the sample PDK into a single GDS file
gf.write_cells.write_cells_recursively(gdspath="extra/pdk.gds", dirpath="extra/gds")
{'bend_euler_RNone_A90_P0_d7c3a5a9': PosixPath('/home/runner/work/gdsfactory/gdsfactory/notebooks/extra/gds/bend_euler_RNone_A90_P0_d7c3a5a9.gds'),
'straight_L10_N2_CSstrip_WNone': PosixPath('/home/runner/work/gdsfactory/gdsfactory/notebooks/extra/gds/straight_L10_N2_CSstrip_WNone.gds'),
'grating_coupler_ellipti_07e69d9a': PosixPath('/home/runner/work/gdsfactory/gdsfactory/notebooks/extra/gds/grating_coupler_ellipti_07e69d9a.gds'),
'Unnamed_21': PosixPath('/home/runner/work/gdsfactory/gdsfactory/notebooks/extra/gds/Unnamed_21.gds')}
print(gf.write_cells.get_import_gds_script("extra/gds"))
from pathlib import Path
from functools import partial
import gdsfactory as gf
add_ports_optical = partial(
gf.add_ports.add_ports_from_markers_inside, pin_layer=(1, 0), port_layer=(2, 0)
)
add_ports_electrical = partial(
gf.add_ports.add_ports_from_markers_inside, pin_layer=(41, 0), port_layer=(1, 0)
)
add_ports = gf.compose(add_ports_optical, add_ports_electrical)
gdsdir = Path('/home/runner/work/gdsfactory/gdsfactory/notebooks/extra/gds')
import_gds = partial(gf.import_gds, post_process=add_ports)
@gf.cell
def Unnamed_21()->gf.Component:
'''Returns Unnamed_21 fixed cell.'''
return import_gds(gdsdir/'Unnamed_21.gds')
@gf.cell
def bend_euler_RNone_A90_P0_d7c3a5a9()->gf.Component:
'''Returns bend_euler_RNone_A90_P0_d7c3a5a9 fixed cell.'''
return import_gds(gdsdir/'bend_euler_RNone_A90_P0_d7c3a5a9.gds')
@gf.cell
def grating_coupler_ellipti_07e69d9a()->gf.Component:
'''Returns grating_coupler_ellipti_07e69d9a fixed cell.'''
return import_gds(gdsdir/'grating_coupler_ellipti_07e69d9a.gds')
@gf.cell
def straight_L10_N2_CSstrip_WNone()->gf.Component:
'''Returns straight_L10_N2_CSstrip_WNone fixed cell.'''
return import_gds(gdsdir/'straight_L10_N2_CSstrip_WNone.gds')
You can also include the code to plot each fix cell in the docstring.
print(gf.write_cells.get_import_gds_script("extra/gds", module="samplepdk.components"))
from pathlib import Path
from functools import partial
import gdsfactory as gf
add_ports_optical = partial(
gf.add_ports.add_ports_from_markers_inside, pin_layer=(1, 0), port_layer=(2, 0)
)
add_ports_electrical = partial(
gf.add_ports.add_ports_from_markers_inside, pin_layer=(41, 0), port_layer=(1, 0)
)
add_ports = gf.compose(add_ports_optical, add_ports_electrical)
gdsdir = Path('/home/runner/work/gdsfactory/gdsfactory/notebooks/extra/gds')
import_gds = partial(gf.import_gds, post_process=add_ports)
@gf.cell
def Unnamed_21()->gf.Component:
'''Returns Unnamed_21 fixed cell.
.. plot::
:include-source:
import samplepdk
c = samplepdk.components.Unnamed_21()
c.plot()
'''
return import_gds(gdsdir/'Unnamed_21.gds')
@gf.cell
def bend_euler_RNone_A90_P0_d7c3a5a9()->gf.Component:
'''Returns bend_euler_RNone_A90_P0_d7c3a5a9 fixed cell.
.. plot::
:include-source:
import samplepdk
c = samplepdk.components.bend_euler_RNone_A90_P0_d7c3a5a9()
c.plot()
'''
return import_gds(gdsdir/'bend_euler_RNone_A90_P0_d7c3a5a9.gds')
@gf.cell
def grating_coupler_ellipti_07e69d9a()->gf.Component:
'''Returns grating_coupler_ellipti_07e69d9a fixed cell.
.. plot::
:include-source:
import samplepdk
c = samplepdk.components.grating_coupler_ellipti_07e69d9a()
c.plot()
'''
return import_gds(gdsdir/'grating_coupler_ellipti_07e69d9a.gds')
@gf.cell
def straight_L10_N2_CSstrip_WNone()->gf.Component:
'''Returns straight_L10_N2_CSstrip_WNone fixed cell.
.. plot::
:include-source:
import samplepdk
c = samplepdk.components.straight_L10_N2_CSstrip_WNone()
c.plot()
'''
return import_gds(gdsdir/'straight_L10_N2_CSstrip_WNone.gds')
Import PDK from other python packages#
You can Write the cells to GDS and use the
Ideally you also start transitioning your legacy code Pcells into gdsfactory syntax. It’s a great way to learn the gdsfactory way!
Here is some advice:
Ask your foundry for the gdsfactory PDK.
Leverage the generic pdk cells available in gdsfactory.
Write tests for your cells.
Break the cells into small reusable functions.
use GIT to track changes.
review your code with your colleagues and other gdsfactory developers to get feedback. This is key to get better at coding gdsfactory.
get rid of any warnings you see.
Import PDK from YAML uPDK#
gdsfactory supports read and write to uPDK YAML definition
Lets write a PDK into uPDK YAML definition and then convert it back to a gdsfactory script.
the uPDK extracts the code from the docstrings.
def evanescent_coupler_sample() -> None:
"""Evanescent coupler example.
Args:
coupler_length: length of coupling (min: 0.0, max: 200.0, um).
"""
pass
from gdsfactory.samples.pdk.fab_c import PDK
PDK.activate()
yaml_pdk = PDK.to_updk()
print(yaml_pdk)
blocks:
bend_euler_nc:
bbox:
- - -3.0
- -3.5
- - 13.5
- -3.5
- - 13.5
- 10.0
- - -3.0
- 10.0
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_nc
pins:
o1:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 10.0
- 10.0
- 90.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
bend_euler_no:
bbox:
- - -3.0
- -3.45
- - 13.450000000000001
- -3.45
- - 13.450000000000001
- 10.0
- - -3.0
- 10.0
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_no
pins:
o1:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- 10.0
- 10.0
- 90.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
bend_euler_sc:
bbox:
- - -3.0
- -3.25
- - 13.25
- -3.25
- - 13.25
- 10.0
- - -3.0
- 10.0
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_sc
pins:
o1:
alias: null
doc: null
width: 0.5
xsection: 71c66a08_500
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.5
xsection: 71c66a08_500
xya:
- 10.0
- 10.0
- 90.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
bend_euler_so:
bbox:
- - -3.0
- -3.2
- - 13.200000000000001
- -3.2
- - 13.200000000000001
- 10.0
- - -3.0
- 10.0
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_so
pins:
o1:
alias: null
doc: null
width: 0.4
xsection: 71c66a08_400
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.4
xsection: 71c66a08_400
xya:
- 10.0
- 10.0
- 90.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
gc_sc:
bbox:
- - -3.0
- -14.128
- - 40.18
- -14.128
- - 40.18
- 14.128
- - -3.0
- 14.128
doc: Canvas where you add polygons, instances and ports.
parameters: {}
pins:
o1:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 10.0
xsection: 7a93073b_10000
xya:
- 16.6
- 0.0
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
mmi1x2_nc:
bbox:
- - -13.0
- -4.5
- - 18.5
- -4.5
- - 18.5
- 4.5
- - -13.0
- 4.5
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_nc
width_mmi:
doc: null
max: 0
min: 0
type: int
unit: null
value: 3
pins:
o1:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- -10.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 15.5
- 0.625
- 0.0
o3:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 15.5
- -0.625
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
mmi1x2_no:
bbox:
- - -13.0
- -4.5
- - 18.5
- -4.5
- - 18.5
- 4.5
- - -13.0
- 4.5
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_no
width_mmi:
doc: null
max: 0
min: 0
type: int
unit: null
value: 3
pins:
o1:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- -10.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- 15.5
- 0.625
- 0.0
o3:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- 15.5
- -0.625
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
mmi1x2_sc:
bbox:
- - -13.0
- -4.5
- - 18.5
- -4.5
- - 18.5
- 4.5
- - -13.0
- 4.5
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_sc
width_mmi:
doc: null
max: 0
min: 0
type: int
unit: null
value: 3
pins:
o1:
alias: null
doc: null
width: 0.5
xsection: 71c66a08_500
xya:
- -10.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.5
xsection: 71c66a08_500
xya:
- 15.5
- 0.625
- 0.0
o3:
alias: null
doc: null
width: 0.5
xsection: 71c66a08_500
xya:
- 15.5
- -0.625
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
mmi1x2_so:
bbox:
- - -13.0
- -4.5
- - 18.5
- -4.5
- - 18.5
- 4.5
- - -13.0
- 4.5
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_so
width_mmi:
doc: null
max: 0
min: 0
type: int
unit: null
value: 3
pins:
o1:
alias: null
doc: null
width: 0.4
xsection: 71c66a08_400
xya:
- -10.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.4
xsection: 71c66a08_400
xya:
- 15.5
- 0.625
- 0.0
o3:
alias: null
doc: null
width: 0.4
xsection: 71c66a08_400
xya:
- 15.5
- -0.625
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
mzi_nc:
bbox:
- - -13.0
- -31.125
- - 84.10000000000001
- -31.125
- - 84.10000000000001
- 26.125
- - -13.0
- 26.125
doc: Canvas where you add polygons, instances and ports.
parameters:
add_optical_ports_arms:
doc: null
max: 0
min: 0
type: bool
unit: null
value: false
auto_rename_ports:
doc: null
max: 0
min: 0
type: bool
unit: null
value: true
bend:
doc: null
max: 0
min: 0
type: str
unit: null
value: bend_euler_nc
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_nc
delta_length:
doc: null
max: 0
min: 0
type: float
unit: null
value: 10
length_x:
doc: null
max: 0
min: 0
type: float
unit: null
value: 0.1
length_y:
doc: null
max: 0
min: 0
type: float
unit: null
value: 2
min_length:
doc: null
max: 0
min: 0
type: float
unit: null
value: 0.01
mirror_bot:
doc: null
max: 0
min: 0
type: bool
unit: null
value: false
nbends:
doc: null
max: 0
min: 0
type: int
unit: null
value: 2
port1:
doc: null
max: 0
min: 0
type: str
unit: null
value: o1
port2:
doc: null
max: 0
min: 0
type: str
unit: null
value: o2
port_e0_combiner:
doc: null
max: 0
min: 0
type: str
unit: null
value: o3
port_e0_splitter:
doc: null
max: 0
min: 0
type: str
unit: null
value: o3
port_e1_combiner:
doc: null
max: 0
min: 0
type: str
unit: null
value: o2
port_e1_splitter:
doc: null
max: 0
min: 0
type: str
unit: null
value: o2
splitter:
doc: null
max: 0
min: 0
type: str
unit: null
value: mmi1x2_nc
straight:
doc: null
max: 0
min: 0
type: str
unit: null
value: straight_nc
with_splitter:
doc: null
max: 0
min: 0
type: bool
unit: null
value: true
pins:
o1:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- -10.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 81.10000000000001
- 0.0
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
mzi_no:
bbox:
- - -13.0
- -31.075
- - 84.10000000000001
- -31.075
- - 84.10000000000001
- 26.075
- - -13.0
- 26.075
doc: Canvas where you add polygons, instances and ports.
parameters:
add_optical_ports_arms:
doc: null
max: 0
min: 0
type: bool
unit: null
value: false
auto_rename_ports:
doc: null
max: 0
min: 0
type: bool
unit: null
value: true
bend:
doc: null
max: 0
min: 0
type: str
unit: null
value: bend_euler_no
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_no
delta_length:
doc: null
max: 0
min: 0
type: float
unit: null
value: 10
length_x:
doc: null
max: 0
min: 0
type: float
unit: null
value: 0.1
length_y:
doc: null
max: 0
min: 0
type: float
unit: null
value: 2
min_length:
doc: null
max: 0
min: 0
type: float
unit: null
value: 0.01
mirror_bot:
doc: null
max: 0
min: 0
type: bool
unit: null
value: false
nbends:
doc: null
max: 0
min: 0
type: int
unit: null
value: 2
port1:
doc: null
max: 0
min: 0
type: str
unit: null
value: o1
port2:
doc: null
max: 0
min: 0
type: str
unit: null
value: o2
port_e0_combiner:
doc: null
max: 0
min: 0
type: str
unit: null
value: o3
port_e0_splitter:
doc: null
max: 0
min: 0
type: str
unit: null
value: o3
port_e1_combiner:
doc: null
max: 0
min: 0
type: str
unit: null
value: o2
port_e1_splitter:
doc: null
max: 0
min: 0
type: str
unit: null
value: o2
splitter:
doc: null
max: 0
min: 0
type: str
unit: null
value: mmi1x2_no
straight:
doc: null
max: 0
min: 0
type: str
unit: null
value: straight_no
with_splitter:
doc: null
max: 0
min: 0
type: bool
unit: null
value: true
pins:
o1:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- -10.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- 81.10000000000001
- 0.0
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
straight_nc:
bbox:
- - -3.0
- -3.5
- - 13.0
- -3.5
- - 13.0
- 3.5
- - -3.0
- 3.5
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_nc
pins:
o1:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 10.0
- 0.0
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
straight_no:
bbox:
- - -3.0
- -3.45
- - 13.0
- -3.45
- - 13.0
- 3.45
- - -3.0
- 3.45
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_no
pins:
o1:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.9
xsection: 7a93073b_900
xya:
- 10.0
- 0.0
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
straight_sc:
bbox:
- - -3.0
- -3.5
- - 13.0
- -3.5
- - 13.0
- 3.5
- - -3.0
- 3.5
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_nc
pins:
o1:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 1.0
xsection: 7a93073b_1000
xya:
- 10.0
- 0.0
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
straight_so:
bbox:
- - -3.0
- -3.2
- - 13.0
- -3.2
- - 13.0
- 3.2
- - -3.0
- 3.2
doc: Canvas where you add polygons, instances and ports.
parameters:
cross_section:
doc: null
max: 0
min: 0
type: str
unit: null
value: strip_so
pins:
o1:
alias: null
doc: null
width: 0.4
xsection: 71c66a08_400
xya:
- 0.0
- 0.0
- 180.0
o2:
alias: null
doc: null
width: 0.4
xsection: 71c66a08_400
xya:
- 10.0
- 0.0
- 0.0
settings:
Properties:
doc: ''
max: 0
min: 0
type: float
unit: null
value: 0.0
info:
doc: dictionary that includes derived properties, simulation_settings, settings
max: 0
min: 0
type: float
unit: null
value: 0.0
header:
description: fab_c_demopdk
xsections:
strip_nc:
width: 1.0
strip_no:
width: 0.9
strip_sc:
width: 0.5
strip_so:
width: 0.4
from gdsfactory.component import GDSDIR_TEMP
from gdsfactory.read.from_updk import from_updk
yamlpath = GDSDIR_TEMP / "pdk.yml"
yamlpath.write_text(yaml_pdk)
gdsfactory_script = from_updk(yamlpath)
print(gdsfactory_script)
import sys
from functools import partial
import gdsfactory as gf
from gdsfactory.get_factories import get_cells
from gdsfactory.add_pins import add_pins_inside2um
cell = gf.cell
layer_bbox = (68, 0)
layer_bbmetal = None
layer_pin_label = None
layer_pin = None
layer_pin_optical = None
layer_pin_electrical = None
layer_label = None
layer_text = (1, 0)
text_function = partial(gf.components.text, layer=layer_text, justify="center", size=2.0)
add_pins = partial(add_pins_inside2um, layer_label=layer_label, layer=layer_pin_optical)
strip_nc = gf.CrossSection(width=1.0)
strip_no = gf.CrossSection(width=0.9)
strip_sc = gf.CrossSection(width=0.5)
strip_so = gf.CrossSection(width=0.4)
cross_sections = dict(strip_nc=strip_nc,strip_no=strip_no,strip_sc=strip_sc,strip_so=strip_so)
@gf.cell
def bend_euler_nc(cross_section:str=strip_nc)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.bend_euler_nc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.5], [13.5, -3.5], [13.5, 10.0], [-3.0, 10.0]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'bend_euler_nc:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_1000', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_1000'
c.add_port(name='o2', cross_section='7a93073b_1000', center=(10.0, 10.0), orientation=90.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_1000'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def bend_euler_no(cross_section:str=strip_no)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.bend_euler_no()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.45], [13.450000000000001, -3.45], [13.450000000000001, 10.0], [-3.0, 10.0]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'bend_euler_no:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_900', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_900'
c.add_port(name='o2', cross_section='7a93073b_900', center=(10.0, 10.0), orientation=90.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_900'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def bend_euler_sc(cross_section:str=strip_sc)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.bend_euler_sc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.25], [13.25, -3.25], [13.25, 10.0], [-3.0, 10.0]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'bend_euler_sc:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='71c66a08_500', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '71c66a08_500'
c.add_port(name='o2', cross_section='71c66a08_500', center=(10.0, 10.0), orientation=90.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '71c66a08_500'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def bend_euler_so(cross_section:str=strip_so)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.bend_euler_so()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.2], [13.200000000000001, -3.2], [13.200000000000001, 10.0], [-3.0, 10.0]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'bend_euler_so:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='71c66a08_400', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '71c66a08_400'
c.add_port(name='o2', cross_section='71c66a08_400', center=(10.0, 10.0), orientation=90.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '71c66a08_400'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def gc_sc()->gf.Component:
"""Canvas where you add polygons, instances and ports.
.. plot::
:include-source:
from pdk import cells
c = cells.gc_sc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -14.128], [40.18, -14.128], [40.18, 14.128], [-3.0, 14.128]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'gc_sc'
c.add_label(text=f'Parameters:\n', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_1000', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_1000'
c.add_port(name='o2', cross_section='7a93073b_10000', center=(16.6, 0.0), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_10000'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def mmi1x2_nc(cross_section:str=strip_nc, width_mmi:int=3)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
width_mmi: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.mmi1x2_nc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-13.0, -4.5], [18.5, -4.5], [18.5, 4.5], [-13.0, 4.5]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'mmi1x2_nc:cross_section={cross_section},width_mmi={width_mmi}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}\nwidth_mmi={width_mmi}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_1000', center=(-10.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_1000'
c.add_port(name='o2', cross_section='7a93073b_1000', center=(15.5, 0.625), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_1000'
c.add_port(name='o3', cross_section='7a93073b_1000', center=(15.5, -0.625), orientation=0.0, port_type='optical')
c.ports['o3'].info['cross_section'] = '7a93073b_1000'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def mmi1x2_no(cross_section:str=strip_no, width_mmi:int=3)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
width_mmi: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.mmi1x2_no()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-13.0, -4.5], [18.5, -4.5], [18.5, 4.5], [-13.0, 4.5]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'mmi1x2_no:cross_section={cross_section},width_mmi={width_mmi}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}\nwidth_mmi={width_mmi}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_900', center=(-10.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_900'
c.add_port(name='o2', cross_section='7a93073b_900', center=(15.5, 0.625), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_900'
c.add_port(name='o3', cross_section='7a93073b_900', center=(15.5, -0.625), orientation=0.0, port_type='optical')
c.ports['o3'].info['cross_section'] = '7a93073b_900'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def mmi1x2_sc(cross_section:str=strip_sc, width_mmi:int=3)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
width_mmi: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.mmi1x2_sc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-13.0, -4.5], [18.5, -4.5], [18.5, 4.5], [-13.0, 4.5]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'mmi1x2_sc:cross_section={cross_section},width_mmi={width_mmi}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}\nwidth_mmi={width_mmi}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='71c66a08_500', center=(-10.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '71c66a08_500'
c.add_port(name='o2', cross_section='71c66a08_500', center=(15.5, 0.625), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '71c66a08_500'
c.add_port(name='o3', cross_section='71c66a08_500', center=(15.5, -0.625), orientation=0.0, port_type='optical')
c.ports['o3'].info['cross_section'] = '71c66a08_500'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def mmi1x2_so(cross_section:str=strip_so, width_mmi:int=3)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
width_mmi: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.mmi1x2_so()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-13.0, -4.5], [18.5, -4.5], [18.5, 4.5], [-13.0, 4.5]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'mmi1x2_so:cross_section={cross_section},width_mmi={width_mmi}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}\nwidth_mmi={width_mmi}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='71c66a08_400', center=(-10.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '71c66a08_400'
c.add_port(name='o2', cross_section='71c66a08_400', center=(15.5, 0.625), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '71c66a08_400'
c.add_port(name='o3', cross_section='71c66a08_400', center=(15.5, -0.625), orientation=0.0, port_type='optical')
c.ports['o3'].info['cross_section'] = '71c66a08_400'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def mzi_nc(add_optical_ports_arms:bool=False, auto_rename_ports:bool=True, bend:str=bend_euler_nc, cross_section:str=strip_nc, delta_length:float=10, length_x:float=0.1, length_y:float=2, min_length:float=0.01, mirror_bot:bool=False, nbends:int=2, port1:str=o1, port2:str=o2, port_e0_combiner:str=o3, port_e0_splitter:str=o3, port_e1_combiner:str=o2, port_e1_splitter:str=o2, splitter:str=mmi1x2_nc, straight:str=straight_nc, with_splitter:bool=True)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
add_optical_ports_arms: None (min: 0, max: 0, None).
auto_rename_ports: None (min: 0, max: 0, None).
bend: None (min: 0, max: 0, None).
cross_section: None (min: 0, max: 0, None).
delta_length: None (min: 0, max: 0, None).
length_x: None (min: 0, max: 0, None).
length_y: None (min: 0, max: 0, None).
min_length: None (min: 0, max: 0, None).
mirror_bot: None (min: 0, max: 0, None).
nbends: None (min: 0, max: 0, None).
port1: None (min: 0, max: 0, None).
port2: None (min: 0, max: 0, None).
port_e0_combiner: None (min: 0, max: 0, None).
port_e0_splitter: None (min: 0, max: 0, None).
port_e1_combiner: None (min: 0, max: 0, None).
port_e1_splitter: None (min: 0, max: 0, None).
splitter: None (min: 0, max: 0, None).
straight: None (min: 0, max: 0, None).
with_splitter: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.mzi_nc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-13.0, -31.125], [84.10000000000001, -31.125], [84.10000000000001, 26.125], [-13.0, 26.125]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'mzi_nc:add_optical_ports_arms={add_optical_ports_arms},auto_rename_ports={auto_rename_ports},bend={bend},cross_section={cross_section},delta_length={delta_length},length_x={length_x},length_y={length_y},min_length={min_length},mirror_bot={mirror_bot},nbends={nbends},port1={port1},port2={port2},port_e0_combiner={port_e0_combiner},port_e0_splitter={port_e0_splitter},port_e1_combiner={port_e1_combiner},port_e1_splitter={port_e1_splitter},splitter={splitter},straight={straight},with_splitter={with_splitter}'
c.add_label(text=f'Parameters:\nadd_optical_ports_arms={add_optical_ports_arms}\nauto_rename_ports={auto_rename_ports}\nbend={bend}\ncross_section={cross_section}\ndelta_length={delta_length}\nlength_x={length_x}\nlength_y={length_y}\nmin_length={min_length}\nmirror_bot={mirror_bot}\nnbends={nbends}\nport1={port1}\nport2={port2}\nport_e0_combiner={port_e0_combiner}\nport_e0_splitter={port_e0_splitter}\nport_e1_combiner={port_e1_combiner}\nport_e1_splitter={port_e1_splitter}\nsplitter={splitter}\nstraight={straight}\nwith_splitter={with_splitter}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_1000', center=(-10.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_1000'
c.add_port(name='o2', cross_section='7a93073b_1000', center=(81.10000000000001, 0.0), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_1000'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def mzi_no(add_optical_ports_arms:bool=False, auto_rename_ports:bool=True, bend:str=bend_euler_no, cross_section:str=strip_no, delta_length:float=10, length_x:float=0.1, length_y:float=2, min_length:float=0.01, mirror_bot:bool=False, nbends:int=2, port1:str=o1, port2:str=o2, port_e0_combiner:str=o3, port_e0_splitter:str=o3, port_e1_combiner:str=o2, port_e1_splitter:str=o2, splitter:str=mmi1x2_no, straight:str=straight_no, with_splitter:bool=True)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
add_optical_ports_arms: None (min: 0, max: 0, None).
auto_rename_ports: None (min: 0, max: 0, None).
bend: None (min: 0, max: 0, None).
cross_section: None (min: 0, max: 0, None).
delta_length: None (min: 0, max: 0, None).
length_x: None (min: 0, max: 0, None).
length_y: None (min: 0, max: 0, None).
min_length: None (min: 0, max: 0, None).
mirror_bot: None (min: 0, max: 0, None).
nbends: None (min: 0, max: 0, None).
port1: None (min: 0, max: 0, None).
port2: None (min: 0, max: 0, None).
port_e0_combiner: None (min: 0, max: 0, None).
port_e0_splitter: None (min: 0, max: 0, None).
port_e1_combiner: None (min: 0, max: 0, None).
port_e1_splitter: None (min: 0, max: 0, None).
splitter: None (min: 0, max: 0, None).
straight: None (min: 0, max: 0, None).
with_splitter: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.mzi_no()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-13.0, -31.075], [84.10000000000001, -31.075], [84.10000000000001, 26.075], [-13.0, 26.075]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'mzi_no:add_optical_ports_arms={add_optical_ports_arms},auto_rename_ports={auto_rename_ports},bend={bend},cross_section={cross_section},delta_length={delta_length},length_x={length_x},length_y={length_y},min_length={min_length},mirror_bot={mirror_bot},nbends={nbends},port1={port1},port2={port2},port_e0_combiner={port_e0_combiner},port_e0_splitter={port_e0_splitter},port_e1_combiner={port_e1_combiner},port_e1_splitter={port_e1_splitter},splitter={splitter},straight={straight},with_splitter={with_splitter}'
c.add_label(text=f'Parameters:\nadd_optical_ports_arms={add_optical_ports_arms}\nauto_rename_ports={auto_rename_ports}\nbend={bend}\ncross_section={cross_section}\ndelta_length={delta_length}\nlength_x={length_x}\nlength_y={length_y}\nmin_length={min_length}\nmirror_bot={mirror_bot}\nnbends={nbends}\nport1={port1}\nport2={port2}\nport_e0_combiner={port_e0_combiner}\nport_e0_splitter={port_e0_splitter}\nport_e1_combiner={port_e1_combiner}\nport_e1_splitter={port_e1_splitter}\nsplitter={splitter}\nstraight={straight}\nwith_splitter={with_splitter}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_900', center=(-10.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_900'
c.add_port(name='o2', cross_section='7a93073b_900', center=(81.10000000000001, 0.0), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_900'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def straight_nc(cross_section:str=strip_nc)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.straight_nc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.5], [13.0, -3.5], [13.0, 3.5], [-3.0, 3.5]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'straight_nc:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_1000', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_1000'
c.add_port(name='o2', cross_section='7a93073b_1000', center=(10.0, 0.0), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_1000'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def straight_no(cross_section:str=strip_no)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.straight_no()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.45], [13.0, -3.45], [13.0, 3.45], [-3.0, 3.45]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'straight_no:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_900', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_900'
c.add_port(name='o2', cross_section='7a93073b_900', center=(10.0, 0.0), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_900'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def straight_sc(cross_section:str=strip_nc)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.straight_sc()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.5], [13.0, -3.5], [13.0, 3.5], [-3.0, 3.5]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'straight_sc:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='7a93073b_1000', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '7a93073b_1000'
c.add_port(name='o2', cross_section='7a93073b_1000', center=(10.0, 0.0), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '7a93073b_1000'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
@gf.cell
def straight_so(cross_section:str=strip_so)->gf.Component:
"""Canvas where you add polygons, instances and ports.
Args:
cross_section: None (min: 0, max: 0, None).
.. plot::
:include-source:
from pdk import cells
c = cells.straight_so()
c.draw_ports()
c.plot()
"""
c = gf.Component()
c.add_polygon([[-3.0, -3.2], [13.0, -3.2], [13.0, 3.2], [-3.0, 3.2]], layer=layer_bbox)
xc = c.x
yc = c.y
name = f'straight_so:cross_section={cross_section}'
c.add_label(text=f'Parameters:\ncross_section={cross_section}', position=(0,0), layer=layer_label)
c.add_port(name='o1', cross_section='71c66a08_400', center=(0.0, 0.0), orientation=180.0, port_type='optical')
c.ports['o1'].info['cross_section'] = '71c66a08_400'
c.add_port(name='o2', cross_section='71c66a08_400', center=(10.0, 0.0), orientation=0.0, port_type='optical')
c.ports['o2'].info['cross_section'] = '71c66a08_400'
c.name = name
if layer_pin:
add_pins(c, layer=layer_pin)
return c
if __name__ == "__main__":
c = straight_so()
c.show()
Build your own PDK#
You can create a PDK as a python library using a cookiecutter template. For example, you can use this one.
pip install cookiecutter
cookiecutter gh:joamatab/python
Or you can fork the ubcpdk and create new PCell functions that use the correct layers for your foundry. For example.
from gdsfactory.technology import LayerMap
class LayerMap(LayerMap):
WGCORE = (3, 0)
DEVREC: Layer = (68, 0)
PORT: Layer = (1, 10) # PinRec
PORTE: Layer = (1, 11) # PinRecM
FLOORPLAN: Layer = (99, 0)
TE: Layer = (203, 0)
TM: Layer = (204, 0)
TEXT: Layer = (66, 0)
LABEL_INSTANCE: Layer = (66, 0)
LAYER = LayerMap