From d8702af5b94ab38aedcd61606499bbfbe8f1e44e Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 1 Feb 2026 15:04:34 -0800 Subject: [PATCH] misc doc updates --- README.md | 50 ++++++++++++++++++++++++++++++++++ masque/abstract.py | 5 ++-- masque/builder/builder.py | 3 +- masque/builder/renderpather.py | 2 +- masque/library.py | 3 +- masque/pattern.py | 2 +- 6 files changed, 57 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 250eef3..62b13bb 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,55 @@ A layout consists of a hierarchy of `Pattern`s stored in a single `Library`. Each `Pattern` can contain `Ref`s pointing at other patterns, `Shape`s, `Label`s, and `Port`s. +Library / Pattern hierarchy: +``` + +-----------------------------------------------------------------------+ + | Library | + | | + | Name: "MyChip" ...> Name: "Transistor" | + | +---------------------------+ : +---------------------------+ | + | | [Pattern] | : | [Pattern] | | + | | | : | | | + | | shapes: {...} | : | shapes: { | | + | | ports: {...} | : | "Si": [, ...] | | + | | | : | "M1": [, ...]}| | + | | refs: | : | ports: {G, S, D} | | + | | "Transistor": [Ref, Ref]|..: +---------------------------+ | + | +---------------------------+ | + | | + | # (`refs` keys resolve to Patterns within the Library) | + +-----------------------------------------------------------------------+ +``` + + +Pattern internals: +``` + +---------------------------------------------------------------+ + | [Pattern] | + | | + | shapes: { | + | (1, 0): [Polygon, Circle, ...], # Geometry by layer | + | (2, 0): [Path, ...] | + | "M1" : [Path, ...] | + | "M2" : [Polygon, ...] | + | } | + | | + | refs: { # Key sets target name, Ref sets transform | + | "my_cell": [ | + | Ref(offset=(0,0), rotation=0), | + | Ref(offset=(10,0), rotation=R90, repetition=Grid(...)) | + | ] | + | } | + | | + | ports: { | + | "in": Port(offset=(0,0), rotation=0, ptype="M1"), | + | "out": Port(offset=(10,0), rotation=R180, ptype="wg") | + | } | + | | + +---------------------------------------------------------------+ +``` + + `masque` departs from several "classic" GDSII paradigms: - A `Pattern` object does not store its own name. A name is only assigned when the pattern is placed into a `Library`, which is effectively a name->`Pattern` mapping. @@ -236,3 +285,4 @@ my_pattern.ref(_make_my_subpattern(), offset=..., ...) * Better interface for polygon operations (e.g. with `pyclipper`) - de-embedding - boolean ops +* tuple / string layer auto-translation diff --git a/masque/abstract.py b/masque/abstract.py index 248c8a5..7135eba 100644 --- a/masque/abstract.py +++ b/masque/abstract.py @@ -24,6 +24,7 @@ class Abstract(PortList): When snapping a sub-component to an existing pattern, only the name (not contained in a `Pattern` object) and port info is needed, and not the geometry itself. """ + # Alternate design option: do we want to store a Ref instead of just a name? then we can translate/rotate/mirror... __slots__ = ('name', '_ports') name: str @@ -48,8 +49,6 @@ class Abstract(PortList): self.name = name self.ports = copy.deepcopy(ports) - # TODO do we want to store a Ref instead of just a name? then we can translate/rotate/mirror... - def __repr__(self) -> str: s = f' Self: """ - Rotate the Abstract around the a location. + Rotate the Abstract around a pivot point. Args: pivot: (x, y) location to rotate around diff --git a/masque/builder/builder.py b/masque/builder/builder.py index ee1d277..1b534b5 100644 --- a/masque/builder/builder.py +++ b/masque/builder/builder.py @@ -210,7 +210,8 @@ class Builder(PortList): self.pattern.rect(*args, **kwargs) return self - # Note: We're a superclass of `Pather`, where path() means something different... + # Note: We're a superclass of `Pather`, where path() means something different, + # so we shouldn't wrap Pattern.path() #@wraps(Pattern.path) #def path(self, *args, **kwargs) -> Self: # self.pattern.path(*args, **kwargs) diff --git a/masque/builder/renderpather.py b/masque/builder/renderpather.py index 303a59d..7f18e77 100644 --- a/masque/builder/renderpather.py +++ b/masque/builder/renderpather.py @@ -487,7 +487,7 @@ class RenderPather(PatherMixin): # Fall back to drawing two L-bends ccw0 = jog > 0 kwargs_no_out = (kwargs | {'out_ptype': None}) - t_port0, _ = tool.planL( ccw0, length / 2, in_ptype=in_ptype, **kwargs_no_out) + t_port0, _ = tool.planL( ccw0, length / 2, in_ptype=in_ptype, **kwargs_no_out) # TODO length/2 may fail with asymmetric ptypes jog0 = Port((0, 0), 0).measure_travel(t_port0)[0][1] t_port1, _ = tool.planL(not ccw0, abs(jog - jog0), in_ptype=t_port0.ptype, **kwargs) jog1 = Port((0, 0), 0).measure_travel(t_port1)[0][1] diff --git a/masque/library.py b/masque/library.py index 9e7c133..0ed5271 100644 --- a/masque/library.py +++ b/masque/library.py @@ -141,7 +141,6 @@ class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta): Args: tops: Name(s) of the pattern(s) to check. Default is all patterns in the library. - skip: Memo, set patterns which have already been traversed. Returns: Set of all referenced pattern names @@ -274,7 +273,7 @@ class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta): For an in-place variant, see `Pattern.flatten`. Args: - tops: The pattern(s) to flattern. + tops: The pattern(s) to flatten. flatten_ports: If `True`, keep ports from any referenced patterns; otherwise discard them. dangling_ok: If `True`, no error will be thrown if any diff --git a/masque/pattern.py b/masque/pattern.py index 7e0a79e..dc7d058 100644 --- a/masque/pattern.py +++ b/masque/pattern.py @@ -1241,7 +1241,7 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable): ports specified by `map_out`. Examples: - ======list, === + ========= - `my_pat.plug(subdevice, {'A': 'C', 'B': 'B'}, map_out={'D': 'myport'})` instantiates `subdevice` into `my_pat`, plugging ports 'A' and 'B' of `my_pat` into ports 'C' and 'B' of `subdevice`. The connected ports