Bookmarks
A bookmark is a named bbox attached to a cell. In the Lumicron viewer it shows up in the Bookmarks panel; tapping it fits-to-screen on the geometry. Machine-readable test intent belongs to Registry, not Bookmarks.
Bookmarks restore a saved layout point/region/view, including camera state and optional notes. They are application metadata and never fabricated GDS/OASIS polygons. The application carries them in portable .lum annotation metadata.
Two ways to declare a bookmark
"""Bookmarks — labeled fit-to-screen markers for the viewer.
A bookmark is a named bbox attached to a cell. In the Lumicron viewer it
appears in the Bookmarks panel, and tapping it fits-to-screen on the
component. Two flavors:
1. Free-floating: `c.add(lm.Bookmark("name", at=(x, y)))`
2. Attached to a placement chain: `.add_bookmark(name="...")`
"""
import lumicron as lm
import lumicron.pdks.elyon_demo.all as pdk
@lm.pcell
def BookmarkDemo():
c = lm.CELL("BookmarkDemo")
pad = lm.Rectangle(x_dim=80, y_dim=80, layer=pdk.LAYER.MTL1)
# Bookmark attached to a placement — auto-fits the placed pad in the viewer.
c.add(pad)
c.Place(pad).at((0, 0)).add_bookmark(name="pad_1")
c.add(pad)
c.Place(pad).at((300, 0)).add_bookmark(name="pad_2", group="pads")
# Free-floating bookmark — bookmarks an arbitrary location with notes.
c.add(lm.Bookmark(
"alignment_mark",
at=(150, 150),
notes="Coarse-align target — visible at 5× under microscope.",
))
return c
if __name__ == "__main__":
BookmarkDemo().to_gds("bookmark_demo.gds")- Attached to a placement chain (
.add_bookmark(name=...)) - the bookmark’s bbox tracks the placement’s world bbox after every.at(),.move_by(),.rotate_by(). This is the form to reach for almost always. - Free-floating (
c.add(lm.Bookmark("name", at=(x, y)))) - for arbitrary annotations like alignment marks or zoom-to-region targets.
Groups
Pass group="..." to bind multiple bookmarks into a BookmarkGroup. The viewer shows groups as collapsible sections in the Bookmarks panel:
for i, position in enumerate(modulator_xs):
chip.add(modulator)
chip.Place(modulator).at((position, 0)) \
.add_bookmark(name=f"mod_{i}", group="modulators")All bookmarks sharing the same group= end up in a single BookmarkGroup when the application resolves the cell.
Notes
notes= accepts a markdown string. The viewer renders it in the device-info card when the bookmark is selected.
chip.add(lm.Bookmark(
"alignment_mark",
at=(150, 150),
notes="Coarse-align target - visible at 5× under microscope.",
))Notes are editable in-app too - a script can establish a default and the test engineer can refine it later without touching the script.
Auto-named bookmarks on placements
If you pass bookmark=True to Place(...) without a bookmark_name=, the bookmark is named after the placed cell:
chip.Place(mzi_cell, bookmark=True).at((0, 0)) # bookmark name: "MZI"Pass bookmark_name="..." to override. This shorthand is equivalent to:
chip.Place(mzi_cell).at((0, 0)).add_bookmark(name="...")Empty names are rejected
lm.Bookmark("", at=(0, 0)) raises ValueError. Same for whitespace-only names and add_bookmark(name=""). This catches a frequent typo where a name slot is meant to receive a value from a config dict but the dict is missing the key.
Notebook Notes
A Note carries user-authored information. A Bookmark means “take me here”; a Note means “here is information about this design.” Keep them separate:
chip.add(lm.Note(id="review-1", title="Review coupling gap",
body="Check this value before tapeout."))Add Notes to the selected top cell. Child Notes are not automatically promoted. targetBookmarkID may reference a resolved Bookmark UUID when that identity is available; invalid targets are rejected at annotation export. A Note does not claim that a simulation or test ran or passed.
Legacy .lum annotation schema 1 and saved model Pin keys remain readable. New annotation output uses schema 2, bookmarks, authoredBookmarkIndex, and targetBookmarkID. Conflicting old/new keys fail explicitly.