Layout#

All UBC ubcpdk.cells are conveniently combined into the ubcpdk.components module.

import gdsfactory as gf

from ubcpdk import PDK, cells

PDK.activate()
2026-02-10 11:42:31.718 | WARNING  | doroutes.pcells:<module>:25 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.722 | WARNING  | doroutes.pcells:<module>:48 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.724 | WARNING  | doroutes.pcells:<module>:110 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.725 | WARNING  | doroutes.pcells:<module>:149 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.727 | WARNING  | doroutes.pcells:<module>:168 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.728 | WARNING  | doroutes.pcells:<module>:210 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.729 | WARNING  | doroutes.pcells:<module>:244 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.731 | WARNING  | doroutes.pcells:<module>:269 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.
2026-02-10 11:42:31.732 | WARNING  | doroutes.pcells:<module>:294 - Cannot determine output type ((D)KCell type)from annotation <class 'kfactory.kcell.DKCell'>. Trying to continue but likely this will fail.

Fixed Component cells#

Most ubcpdk components are imported from GDS files as fixed cells.

c = cells.ebeam_crossing4()
c.plot()
../_images/7f9b696739692278b02cf60ba35d3c83903e3d3eecaa18db81c1d42df2da681a.png
c = cells.ebeam_swg_edgecoupler()
c.plot()
../_images/b05ca8f67e87c3eacba3f2faa946ab7de33edca14eaab2c6484c0d40e45d422c.png
c = cells.ebeam_bdc_te1550()
c.plot()
../_images/92f1118d20f2675fdb96c535683af91263eeb7b37073e3205a052c02f1621081.png
c = cells.ebeam_adiabatic_te1550()
c.plot()
../_images/a3c7abb4633280d2b74c89281ff74a1c7e9d27874e2804a97577a8bfb0d1f201.png
c = cells.ebeam_y_adiabatic()
c.plot()
../_images/84d617a635ec15d6ca941af435bc6b9e7252ba6f1f082048600b44a6c9058a48.png
c = cells.ebeam_y_1550()
c.plot()
../_images/42a3f0c7d4312be19760ccfd1cca560767307a2250795bff057989c6b6202f36.png

Parametric Component PCells#

You can also define cells adapted from gdsfactory generic pdk.

c = cells.straight(length=2)
c.plot()
../_images/f087adb6b99181e90de31b59024cbcc608e916bc6048c2b92bff41d1c8d406b0.png
c = cells.bend_euler(radius=5)
c.plot()
../_images/6c442ec140ac37d49e557c0b4dae783a80c39852863550f4f090d39e5282e336.png
c = cells.spiral()
c.plot()
../_images/3f002bc58a2df6bba1058bf24f36eb66ef3488630a0252a02bee017070a19061.png
c = cells.ring_single_heater()
c.plot()
../_images/37309a07265c76a832cea7a9861a2839d3e1e27f04d7f0fbce3aa9426f57d3ea.png

Components with grating couplers#

To test your devices you can add grating couplers. Both for single fibers and for fiber arrays.

splitter = cells.ebeam_y_1550()
mzi = gf.components.mzi(splitter=splitter)
mzi.plot()
../_images/cb2f1d2fdfb5a0a737fd97046dd1ee8ef17e2b0a6b00839143519d921cde847f.png
component_fiber_array = cells.add_fiber_array(component=mzi, fanout_length=5)
component_fiber_array.plot()
../_images/700f17d87a06021fa6f46b3da7b694d3ccf4b3e1a1ca274059e089bdb4b02ede.png
c = cells.ring_single_heater()
c = cells.add_fiber_array_pads_rf(c)
c.plot()
../_images/2fab93c217e6065783884f0c17db6c442f12ab7f99f6e3a1d584c345cebb5a0f.png
c = cells.mzi_heater()
c = cells.add_fiber_array_pads_rf(c)
c.plot()
../_images/ce876a4bb82841393f24bf40e42c9ec226820a9dcff7fc95dada555d67a0add7.png

3D rendering#

scene = c.to_3d()
scene.show()

Die assembly#

from functools import partial

import gdsfactory as gf

from ubcpdk.tech import LAYER

size = (440, 470)
add_gc = cells.add_fiber_array


@gf.cell
def EBeam_JoaquinMatres_1() -> gf.Component:
    """Add DBR cavities."""
    e = [add_gc(cells.straight())]
    e += [add_gc(cells.mzi(delta_length=dl)) for dl in [9.32, 93.19]]
    e += [
        add_gc(cells.ring_single(radius=12, gap=gap, length_x=coupling_length))
        for gap in [0.2]
        for coupling_length in [2.5, 4.5, 6.5]
    ]

    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_1()
c.show()  # show in klayout
c.plot()  # plot in notebook
2026-02-10 11:42:36.735 | WARNING  | kfactory.kcell:show:3958 - Could not connect to klive server
../_images/d064899e3f0b549b001e7a205b279d867bb177da5bc2a7fd3ccb64b92850fd6c.png
def EBeam_JoaquinMatres_2() -> gf.Component:
    """spirals for extracting straight waveguide loss"""

    e = [
        cells.add_fiber_array(component=cells.spiral(n_loops=8, length=length))
        for length in [0, 100, 200]
    ]

    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_2()
c.show()  # show in klayout
c.plot()  # plot in notebook
2026-02-10 11:42:37.097 | WARNING  | kfactory.kcell:show:3958 - Could not connect to klive server
../_images/b76a1441cc5f7fbfeea2dde62e7a1ad939b9160aeedcb59effe32a8b3c8e2122.png
def EBeam_JoaquinMatres_3() -> gf.Component:
    """Contains mirror cavities and structures inside a resonator."""
    e = []
    e += [add_gc(cells.ebeam_crossing4())]
    e += [add_gc(cells.ebeam_adiabatic_te1550())]
    e += [add_gc(cells.ebeam_bdc_te1550())]
    e += [add_gc(cells.ebeam_y_1550())]
    e += [add_gc(cells.straight(), component_name=f"straight_{i}") for i in range(2)]
    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_3()
c.show()  # show in klayout
c.plot()  # plot in notebook
2026-02-10 11:42:37.443 | ERROR    | kfactory.kcell:name:687 - Name conflict in kfactory.kcell::name at line 687
Renaming Unnamed_349 (cell_index=349) to straight_L10_CSstrip_WNone_N2_with_gc would cause it to be named the same as:
 - straight_L10_CSstrip_WNone_N2_with_gc (cell_index=130), function_name=None, basename=None
2026-02-10 11:42:37.470 | ERROR    | kfactory.kcell:name:687 - Name conflict in kfactory.kcell::name at line 687
Renaming Unnamed_351 (cell_index=351) to straight_L10_CSstrip_WNone_N2_with_gc would cause it to be named the same as:
 - straight_L10_CSstrip_WNone_N2_with_gc (cell_index=349), function_name=None, basename=None
 - straight_L10_CSstrip_WNone_N2_with_gc (cell_index=130), function_name=None, basename=None
2026-02-10 11:42:37.519 | WARNING  | kfactory.kcell:show:3958 - Could not connect to klive server
../_images/1db094cc36db00703f088dd765acd0de5201042ec39e1d0791528a9ffa35f2cd.png
def EBeam_JoaquinMatres_4() -> gf.Component:
    """MZI interferometers."""
    mzi = partial(gf.components.mzi, splitter=cells.ebeam_y_1550)
    mzis = [mzi(delta_length=delta_length) for delta_length in [10, 40]]
    mzis_gc = [cells.add_fiber_array(mzi, fanout_length=5) for mzi in mzis]

    mzis = [cells.mzi_heater(delta_length=delta_length) for delta_length in [40]]
    mzis_heater_gc = [
        cells.add_fiber_array_pads_rf(mzi, orientation=90) for mzi in mzis
    ]

    e = mzis_gc + mzis_heater_gc
    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_4()
c.show()  # show in klayout
c.plot()  # plot in notebook
2026-02-10 11:42:37.752 | WARNING  | kfactory.kcell:show:3958 - Could not connect to klive server
../_images/e7ceb77106d0466098e08d0d4317436137e6f37f7b7d2846af568da401d6f2b3.png
def EBeam_JoaquinMatres_5() -> gf.Component:
    """Ring resonators."""

    rings = []
    for length_x in [4, 6]:
        ring = cells.ring_single_heater(length_x=length_x)
        ring_gc = cells.add_fiber_array_pads_rf(ring, pad_yspacing=10)
        rings.append(ring_gc)

    c = gf.Component()
    _ = c << gf.pack(rings, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_5()
c.show()  # show in klayout
c.plot()  # plot in notebook
2026-02-10 11:42:38.026 | WARNING  | kfactory.kcell:show:3958 - Could not connect to klive server
../_images/5e61215ba91433738767fe4efd102d44017e7a657cc1ce751ba627cf7ee423ea.png