diff --git a/masque/file/dxf.py b/masque/file/dxf.py index 0f0b753..335cd80 100644 --- a/masque/file/dxf.py +++ b/masque/file/dxf.py @@ -59,8 +59,8 @@ def write(pattern: Pattern, array with rotated instances must be manhattan _after_ having a compensating rotation applied. Args: - patterns: A Pattern or list of patterns to write to file. - file: Filename or stream object to write to. + patterns: A Pattern or list of patterns to write to the stream. + stream: Stream object to write to. modify_original: If `True`, the original pattern is modified as part of the writing process. Otherwise, a copy is made and `deepunlock()`-ed. Default `False`. diff --git a/masque/file/gdsii.py b/masque/file/gdsii.py index a1f0877..98a9a51 100644 --- a/masque/file/gdsii.py +++ b/masque/file/gdsii.py @@ -1,5 +1,15 @@ """ GDSII file format readers and writers + +Note that GDSII references follow the same convention as `masque`, + with this order of operations: + 1. Mirroring + 2. Rotation + 3. Scaling + 4. Offset and array expansion (no mirroring/rotation/scaling applied to offsets) + + Scaling, rotation, and mirroring apply to individual instances, not grid + vectors or offsets. """ from typing import List, Any, Dict, Tuple, Callable, Union, Sequence, Iterable, Optional import re @@ -23,7 +33,6 @@ from ..shapes import Polygon, Path from ..utils import rotation_matrix_2d, get_bit, set_bit, vector2, is_scalar, layer_t from ..utils import remove_colinear_vertices, normalize_mirror -#TODO document how GDS rotation / mirror works #TODO absolute positioning @@ -65,8 +74,8 @@ def write(patterns: Union[Pattern, List[Pattern]], prior to calling this function. Args: - patterns: A Pattern or list of patterns to write to file. - file: Filename or stream object to write to. + patterns: A Pattern or list of patterns to write to the stream. + stream: Stream object to write to. meters_per_unit: Written into the GDSII file, meters per (database) length unit. All distances are assumed to be an integer multiple of this unit, and are stored as such. logical_units_per_unit: Written into the GDSII file. Allows the GDSII to specify a diff --git a/masque/repetition.py b/masque/repetition.py index e1297d2..96c9214 100644 --- a/masque/repetition.py +++ b/masque/repetition.py @@ -22,6 +22,22 @@ class GridRepetition: """ GridRepetition provides support for efficiently embedding multiple copies of a `Pattern` into another `Pattern` at regularly-spaced offsets. + + Note that rotation, scaling, and mirroring are applied to individual instances of the + pattern, not to the grid vectors. + + The order of operations is + 1. A single refernce instance to the target pattern is mirrored + 2. The single instance is rotated. + 3. The instance is scaled by the scaling factor. + 4. The instance is shifted by the provided offset + (no mirroring/scaling/rotation is applied to the offset). + 5. Additional copies of the instance will appear at coordinates specified by + `(offset + aa * a_vector + bb * b_vector)`, with `aa in range(0, a_count)` + and `bb in range(0, b_count)`. All instance locations remain unaffected by + mirroring/scaling/rotation, though each instance's data will be transformed + relative to the instance's location (i.e. relative to the contained pattern's + (0, 0) point). """ __slots__ = ('_pattern', '_offset', @@ -43,7 +59,7 @@ class GridRepetition: """ (x, y) offset for the base instance """ _dose: float - """ Dose factor """ + """ Scaling factor applied to the dose """ _rotation: float """ Rotation of the individual instances in the grid (not the grid vectors). @@ -76,7 +92,7 @@ class GridRepetition: """ Number of instances along the direction specified by the `b_vector` """ identifier: Tuple[Any, ...] - """ Arbitrary identifier """ + """ Arbitrary identifier, used internally by some `masque` functions. """ locked: bool """ If `True`, disallows changes to the GridRepetition """ @@ -96,15 +112,23 @@ class GridRepetition: identifier: Tuple[Any, ...] = ()): """ Args: + pattern: Pattern to reference. a_vector: First lattice vector, of the form `[x, y]`. - Specifies center-to-center spacing between adjacent elements. + Specifies center-to-center spacing between adjacent instances. a_count: Number of elements in the a_vector direction. b_vector: Second lattice vector, of the form `[x, y]`. - Specifies center-to-center spacing between adjacent elements. + Specifies center-to-center spacing between adjacent instances. Can be omitted when specifying a 1D array. b_count: Number of elements in the `b_vector` direction. Should be omitted if `b_vector` was omitted. + offset: (x, y) offset applied to all instances. + rotation: Rotation (radians, counterclockwise) applied to each instance. + Relative to each instance's (0, 0). + mirrored: Whether to mirror individual instances across the x and y axes. + dose: Scaling factor applied to the dose. + scale: Scaling factor applied to the instances' geometry. locked: Whether the `GridRepetition` is locked after initialization. + identifier: Arbitrary tuple, used internally by some `masque` functions. Raises: PatternError if `b_*` inputs conflict with each other diff --git a/masque/subpattern.py b/masque/subpattern.py index 7f4bb87..f0af4c0 100644 --- a/masque/subpattern.py +++ b/masque/subpattern.py @@ -2,6 +2,7 @@ SubPattern provides basic support for nesting Pattern objects within each other, by adding offset, rotation, scaling, and other such properties to the reference. """ +#TODO more top-level documentation from typing import Union, List, Dict, Tuple, Optional, Sequence, TYPE_CHECKING, Any import copy @@ -51,13 +52,11 @@ class SubPattern: """ Whether to mirror the instanc across the x and/or y axes. """ identifier: Tuple[Any, ...] - """ An arbitrary identifier """ + """ Arbitrary identifier, used internally by some `masque` functions. """ locked: bool """ If `True`, disallows changes to the GridRepetition """ - - #TODO more documentation? def __init__(self, pattern: Optional['Pattern'], offset: vector2 = (0.0, 0.0), @@ -67,6 +66,17 @@ class SubPattern: scale: float = 1.0, locked: bool = False, identifier: Tuple[Any, ...] = ()): + """ + Args: + pattern: Pattern to reference. + offset: (x, y) offset applied to the referenced pattern. Not affected by rotation etc. + rotation: Rotation (radians, counterclockwise) relative to the referenced pattern's (0, 0). + mirrored: Whether to mirror the referenced pattern across its x and y axes. + dose: Scaling factor applied to the dose. + scale: Scaling factor applied to the pattern's geometry. + locked: Whether the `SubPattern` is locked after initialization. + identifier: Arbitrary tuple, used internally by some `masque` functions. + """ object.__setattr__(self, 'locked', False) self.identifier = identifier self.pattern = pattern