diff --git a/README.md b/README.md index 6448b26..4565cad 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ References are accomplished by listing the target's name, not its `Pattern` obje ## Glossary - `Library`: A collection of named cells. OASIS or GDS "library" or file. -- `Tree`: Any `{name: pattern}` mapping which has only one topcell. +- "tree": Any Library which has only one topcell. - `Pattern`: A collection of geometry, text labels, and reference to other patterns. OASIS or GDS "Cell", DXF "Block". - `Ref`: A reference to another pattern. GDS "AREF/SREF", OASIS "Placement". @@ -142,11 +142,6 @@ my_pattern.ref(new_name, ...) # instantiate the cell # In practice, you may do lots of my_pattern.ref(lib << make_tree(...), ...) - -# With a `Builder` and `place()`/`plug()` the `lib <<` portion can be implicit: -my_builder = Builder(library=lib, ...) -... -my_builder.place(make_tree(...)) ``` We can also use this shorthand to quickly add and reference a single flat (as yet un-named) pattern: diff --git a/masque/__init__.py b/masque/__init__.py index 15210ba..3ed2a6f 100644 --- a/masque/__init__.py +++ b/masque/__init__.py @@ -38,7 +38,7 @@ from .pattern import Pattern, map_layers, map_targets, chain_elements from .library import ( ILibraryView, ILibrary, LibraryView, Library, LazyLibrary, - AbstractView, TreeView, Tree, + AbstractView, ) from .ports import Port, PortList from .abstract import Abstract diff --git a/masque/builder/builder.py b/masque/builder/builder.py index a401abc..68de9e6 100644 --- a/masque/builder/builder.py +++ b/masque/builder/builder.py @@ -8,7 +8,7 @@ import logging from numpy.typing import ArrayLike from ..pattern import Pattern -from ..library import ILibrary, TreeView +from ..library import ILibrary from ..error import BuildError from ..ports import PortList, Port from ..abstract import Abstract @@ -190,7 +190,7 @@ class Builder(PortList): def plug( self, - other: Abstract | str | Pattern | TreeView, + other: Abstract | str | Pattern, map_in: dict[str, str], map_out: dict[str, str | None] | None = None, *, @@ -201,16 +201,11 @@ class Builder(PortList): ) -> Self: """ Wrapper around `Pattern.plug` which allows a string for `other`. - The `Builder`'s library is used to dereference the string (or `Abstract`, if - one is passed with `append=True`). If a `TreeView` is passed, it is first - added into `self.library`. + one is passed with `append=True`). Args: - other: An `Abstract`, string, `Pattern`, or `TreeView` describing the - device to be instatiated. If it is a `TreeView`, it is first - added into `self.library`, after which the topcell is plugged; - an equivalent statement is `self.plug(self.library << other, ...)`. + other: An `Abstract`, string, or `Pattern` describing the device to be instatiated. map_in: dict of `{'self_port': 'other_port'}` mappings, specifying port connections between the two devices. map_out: dict of `{'old_name': 'new_name'}` mappings, specifying @@ -248,10 +243,6 @@ class Builder(PortList): logger.error('Skipping plug() since device is dead') return self - if not isinstance(other, (str, Abstract, Pattern)): - # We got a Tree; add it into self.library and grab an Abstract for it - other = self.library << other - if isinstance(other, str): other = self.library.abstract(other) if append and isinstance(other, Abstract): @@ -270,7 +261,7 @@ class Builder(PortList): def place( self, - other: Abstract | str | Pattern | TreeView, + other: Abstract | str | Pattern, *, offset: ArrayLike = (0, 0), rotation: float = 0, @@ -281,17 +272,12 @@ class Builder(PortList): append: bool = False, ) -> Self: """ - Wrapper around `Pattern.place` which allows a string or `TreeView` for `other`. - + Wrapper around `Pattern.place` which allows a string for `other`. The `Builder`'s library is used to dereference the string (or `Abstract`, if - one is passed with `append=True`). If a `TreeView` is passed, it is first - added into `self.library`. + one is passed with `append=True`). Args: - other: An `Abstract`, string, `Pattern`, or `TreeView` describing the - device to be instatiated. If it is a `TreeView`, it is first - added into `self.library`, after which the topcell is plugged; - an equivalent statement is `self.plug(self.library << other, ...)`. + other: An `Abstract`, string, or `Pattern` describing the device to be instatiated. offset: Offset at which to place the instance. Default (0, 0). rotation: Rotation applied to the instance before placement. Default 0. pivot: Rotation is applied around this pivot point (default (0, 0)). @@ -320,10 +306,6 @@ class Builder(PortList): logger.error('Skipping place() since device is dead') return self - if not isinstance(other, (str, Abstract, Pattern)): - # We got a Tree; add it into self.library and grab an Abstract for it - other = self.library << other - if isinstance(other, str): other = self.library.abstract(other) if append and isinstance(other, Abstract): diff --git a/masque/library.py b/masque/library.py index 947f6b9..c0d8c93 100644 --- a/masque/library.py +++ b/masque/library.py @@ -14,7 +14,7 @@ Classes include: - `AbstractView`: Provides a way to use []-indexing to generate abstracts for patterns in the linked library. Generated with `ILibraryView.abstract_view()`. """ -from typing import Callable, Self, Type, TYPE_CHECKING, cast, TypeAlias, Protocol, Literal +from typing import Callable, Self, Type, TYPE_CHECKING, cast from typing import Iterator, Mapping, MutableMapping, Sequence import logging import base64 @@ -26,7 +26,7 @@ from collections import defaultdict from abc import ABCMeta, abstractmethod import numpy -from numpy.typing import ArrayLike, NDArray +from numpy.typing import ArrayLike from .error import LibraryError, PatternError from .utils import rotation_matrix_2d, layer_t @@ -42,24 +42,7 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) -class visitor_function_t(Protocol): - """ Signature for `Library.dfs()` visitor functions. """ - def __call__( - self, - pattern: 'Pattern', - hierarchy: tuple[str | None, ...], - memo: dict, - transform: NDArray[numpy.float64] | Literal[False], - ) -> Pattern: - ... - - -TreeView: TypeAlias = Mapping[str, 'Pattern'] -""" A name-to-`Pattern` mapping which is expected to have only one top-level cell """ - -Tree: TypeAlias = MutableMapping[str, 'Pattern'] -""" A mutable name-to-`Pattern` mapping which is expected to have only one top-level cell """ - +visitor_function_t = Callable[..., 'Pattern'] SINGLE_USE_PREFIX = '_' """ @@ -387,9 +370,6 @@ class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta): def top(self) -> str: """ Return the name of the topcell, or raise an exception if there isn't a single topcell - - Raises: - LibraryError if there is not exactly one topcell. """ tops = self.tops() if len(tops) != 1: @@ -399,9 +379,6 @@ class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta): def top_pattern(self) -> 'Pattern': """ Shorthand for self[self.top()] - - Raises: - LibraryError if there is not exactly one topcell. """ return self[self.top()] @@ -461,7 +438,7 @@ class ILibraryView(Mapping[str, 'Pattern'], metaclass=ABCMeta): if transform is None or transform is True: transform = numpy.zeros(4) elif transform is not False: - transform = numpy.array(transform, dtype=float, copy=False) + transform = numpy.array(transform) original_pattern = pattern @@ -697,15 +674,7 @@ class ILibrary(ILibraryView, MutableMapping[str, 'Pattern'], metaclass=ABCMeta): return rename_map - def __lshift__(self, other: TreeView) -> str: - """ - `add()` items from a tree (single-topcell name: pattern mapping) into this one, - and return the name of the tree's topcell (in this library; it may have changed - based on `add()`'s default `rename_theirs` argument). - - Raises: - LibraryError if there is more than one topcell in `other`. - """ + def __lshift__(self, other: Mapping[str, 'Pattern']) -> str: if len(other) == 1: name = next(iter(other)) else: @@ -723,13 +692,6 @@ class ILibrary(ILibraryView, MutableMapping[str, 'Pattern'], metaclass=ABCMeta): return new_name def __le__(self, other: Mapping[str, 'Pattern']) -> Abstract: - """ - Perform the same operation as `__lshift__` / `<<`, but return an `Abstract` instead - of just the pattern's name. - - Raises: - LibraryError if there is more than one topcell in `other`. - """ new_name = self << other return self.abstract(new_name) @@ -865,7 +827,7 @@ class ILibrary(ILibraryView, MutableMapping[str, 'Pattern'], metaclass=ABCMeta): if name_func is None: def name_func(_pat, _shape): - return self.get_name(SINGLE_USE_PREFIX + 'rep') + return self.get_name(SINGLE_USE_PREFIX = 'rep') for pat in tuple(self.values()): for layer in pat.shapes: