masque/examples/tutorial/library.py

114 lines
3.9 KiB
Python
Raw Normal View History

"""
Tutorial: authoring a mixed library with `BuildLibrary`.
This example assumes you have already read `devices.py` and generated the
`circuit.gds` file it writes. The goal here is not the photonic-crystal geometry
itself, but rather how Masque lets you combine imported GDS cells with
python-generated recipes, then turn that declaration set into a normal library
for downstream assembly and writing.
"""
from typing import Any
2022-02-27 21:21:44 -08:00
from pprint import pformat
from masque import BuildLibrary, Pather, Pattern, cell
from masque.file.gdsii import writefile
from masque.file.gdsii_lazy import readfile
2022-02-27 21:21:44 -08:00
import basic_shapes
import devices
from basic_shapes import GDS_OPTS
def make_mixed_waveguide(lib: BuildLibrary) -> Pattern:
"""
Recipe which assembles imported and generated cells behind the builder API.
"""
circ = Pather(library=lib, ports='tri_l3cav')
# First way to specify what we are plugging in: request an explicit abstract.
circ.plug(lib.abstract('wg10'), {'input': 'right'})
# Second way: use an AbstractView, which behaves like a mapping of names
# to abstracts.
abstracts = lib.abstract_view()
circ.plug(abstracts['wg10'], {'output': 'left'})
# Third way: let Pather resolve a pattern name through its own library.
circ.plug('tri_wg10', {'input': 'right'})
circ.plug('tri_wg10', {'output': 'left'})
return circ.pattern
2022-02-27 21:21:44 -08:00
def main() -> None:
builder = BuildLibrary()
cells = builder.cells
2022-02-27 21:21:44 -08:00
#
# Load some devices from a GDS file
#
# Scan circuit.gds and prepare to lazy-load its contents. Port labels are
# imported on first materialization, but the raw source remains untouched
# until we build the final library.
gds_lib, _properties = readfile('circuit.gds')
builder.add_source(gds_lib.with_ports_from_data(layers=[(3, 0)], max_depth=1))
2022-02-27 21:21:44 -08:00
print('Registered imported cells:\n' + pformat(list(gds_lib.keys())))
2022-02-27 21:21:44 -08:00
#
# Register some new devices, this time from python code rather than GDS.
2022-02-27 21:21:44 -08:00
#
cells.triangle = basic_shapes.triangle(devices.RADIUS)
2023-07-17 20:22:04 -07:00
opts: dict[str, Any] = dict(
lattice_constant=devices.LATTICE_CONSTANT,
hole='triangle',
)
2022-02-27 21:21:44 -08:00
cells.tri_wg10 = cell(devices.waveguide)(length=10, mirror_periods=5, **opts)
cells.tri_wg05 = cell(devices.waveguide)(length=5, mirror_periods=5, **opts)
cells.tri_wg28 = cell(devices.waveguide)(length=28, mirror_periods=5, **opts)
cells.tri_bend0 = cell(devices.bend)(mirror_periods=5, **opts)
cells.tri_ysplit = cell(devices.y_splitter)(mirror_periods=5, **opts)
cells.tri_l3cav = cell(devices.perturbed_l3)(xy_size=(4, 10), **opts, hole_lib=builder)
cells.mixed_wg_cav = cell(make_mixed_waveguide)(builder)
print('Declared cells waiting to be built:\n' + pformat(list(builder.keys())))
2022-02-27 21:21:44 -08:00
#
# Build the declaration set into a normal library.
2022-02-27 21:21:44 -08:00
#
built = builder.build()
print('Built library contains:\n' + pformat(list(built.keys())))
2022-02-27 21:21:44 -08:00
#
# Continue designing against the built library.
2022-02-27 21:21:44 -08:00
#
# The built result behaves like a normal mutable library, so downstream code
# can use Pather, abstract views, and writing without going back through the
# builder interface.
circ = Pather.interface(source='mixed_wg_cav', library=built)
circ.plug('tri_bend0', {'input': 'right'})
circ.plug('tri_bend0', {'input': 'left'}, mirrored=True) # mirror since no tri y-symmetry
circ.plug('tri_bend0', {'input': 'right'})
circ.plug('bend0', {'output': 'left'})
circ.plug('bend0', {'output': 'left'})
circ.plug('bend0', {'output': 'left'})
circ.plug('tri_wg10', {'input': 'right'})
circ.plug('tri_wg28', {'input': 'right'})
circ.plug('tri_wg10', {'input': 'right', 'output': 'left'})
built['loop_segment'] = circ.pattern
2022-02-27 21:21:44 -08:00
#
# Write all devices into a GDS file.
2022-02-27 21:21:44 -08:00
#
2023-01-24 23:25:10 -08:00
print('Writing library to file...')
writefile(built, 'library.gds', **GDS_OPTS)
2022-02-27 21:21:44 -08:00
if __name__ == '__main__':
main()