[docs / examples] Update docs and examples
This commit is contained in:
parent
8100d8095a
commit
fd2698c503
7 changed files with 132 additions and 107 deletions
|
|
@ -1,3 +1,11 @@
|
|||
"""
|
||||
Tutorial: using `LazyLibrary` and `Builder.interface()`.
|
||||
|
||||
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 mix lazily loaded GDS content with
|
||||
python-generated devices inside one library.
|
||||
"""
|
||||
from typing import Any
|
||||
from pprint import pformat
|
||||
|
||||
|
|
@ -12,8 +20,9 @@ from basic_shapes import GDS_OPTS
|
|||
|
||||
|
||||
def main() -> None:
|
||||
# Define a `LazyLibrary`, which provides lazy evaluation for generating
|
||||
# patterns and lazy-loading of GDS contents.
|
||||
# A `LazyLibrary` delays work until a pattern is actually needed.
|
||||
# That applies both to GDS cells we load from disk and to python callables
|
||||
# that generate patterns on demand.
|
||||
lib = LazyLibrary()
|
||||
|
||||
#
|
||||
|
|
@ -23,9 +32,9 @@ def main() -> None:
|
|||
# Scan circuit.gds and prepare to lazy-load its contents
|
||||
gds_lib, _properties = load_libraryfile('circuit.gds', postprocess=data_to_ports)
|
||||
|
||||
# Add it into the device library by providing a way to read port info
|
||||
# This maintains the lazy evaluation from above, so no patterns
|
||||
# are actually read yet.
|
||||
# Add those cells into our lazy library.
|
||||
# Nothing is read yet; we are only registering how to fetch and postprocess
|
||||
# each pattern when it is first requested.
|
||||
lib.add(gds_lib)
|
||||
|
||||
print('Patterns loaded from GDS into library:\n' + pformat(list(lib.keys())))
|
||||
|
|
@ -40,8 +49,8 @@ def main() -> None:
|
|||
hole = 'triangle',
|
||||
)
|
||||
|
||||
# Triangle-based variants. These are defined here, but they won't run until they're
|
||||
# retrieved from the library.
|
||||
# Triangle-based variants. These lambdas are only recipes for building the
|
||||
# patterns; they do not execute until someone asks for the cell.
|
||||
lib['tri_wg10'] = lambda: devices.waveguide(length=10, mirror_periods=5, **opts)
|
||||
lib['tri_wg05'] = lambda: devices.waveguide(length=5, mirror_periods=5, **opts)
|
||||
lib['tri_wg28'] = lambda: devices.waveguide(length=28, mirror_periods=5, **opts)
|
||||
|
|
@ -53,22 +62,22 @@ def main() -> None:
|
|||
# Build a mixed waveguide with an L3 cavity in the middle
|
||||
#
|
||||
|
||||
# Immediately start building from an instance of the L3 cavity
|
||||
# Start a new design by copying the ports from an existing library cell.
|
||||
# This gives `circ2` the same external interface as `tri_l3cav`.
|
||||
circ2 = Builder(library=lib, ports='tri_l3cav')
|
||||
|
||||
# First way to get abstracts is `lib.abstract(name)`
|
||||
# We can use this syntax directly with `Pattern.plug()` and `Pattern.place()` as well as through `Builder`.
|
||||
# First way to specify what we are plugging in: request an explicit abstract.
|
||||
# This works with `Pattern` methods directly as well as with `Builder`.
|
||||
circ2.plug(lib.abstract('wg10'), {'input': 'right'})
|
||||
|
||||
# Second way to get abstracts is to use an AbstractView
|
||||
# This also works directly with `Pattern.plug()` / `Pattern.place()`.
|
||||
# Second way: use an `AbstractView`, which behaves like a mapping of names
|
||||
# to abstracts.
|
||||
abstracts = lib.abstract_view()
|
||||
circ2.plug(abstracts['wg10'], {'output': 'left'})
|
||||
|
||||
# Third way to specify an abstract works by automatically getting
|
||||
# it from the library already within the Builder object.
|
||||
# This wouldn't work if we only had a `Pattern` (not a `Builder`).
|
||||
# Just pass the pattern name!
|
||||
# Third way: let `Builder` resolve a pattern name through its own library.
|
||||
# This shorthand is convenient, but it is specific to helpers that already
|
||||
# carry a library reference.
|
||||
circ2.plug('tri_wg10', {'input': 'right'})
|
||||
circ2.plug('tri_wg10', {'output': 'left'})
|
||||
|
||||
|
|
@ -77,13 +86,15 @@ def main() -> None:
|
|||
|
||||
|
||||
#
|
||||
# Build a device that could plug into our mixed_wg_cav and joins the two ports
|
||||
# Build a second device that is explicitly designed to mate with `circ2`.
|
||||
#
|
||||
|
||||
# We'll be designing against an existing device's interface...
|
||||
# `Builder.interface()` makes a new pattern whose ports mirror an existing
|
||||
# design's external interface. That is useful when you want to design an
|
||||
# adapter, continuation, or mating structure.
|
||||
circ3 = Builder.interface(source=circ2)
|
||||
|
||||
# ... that lets us continue from where we left off.
|
||||
# Continue routing outward from those inherited ports.
|
||||
circ3.plug('tri_bend0', {'input': 'right'})
|
||||
circ3.plug('tri_bend0', {'input': 'left'}, mirrored=True) # mirror since no tri y-symmetry
|
||||
circ3.plug('tri_bend0', {'input': 'right'})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue