diff --git a/examples/generate_gds_perf.py b/examples/generate_gds_perf.py index 6bdd999..7eaebbb 100644 --- a/examples/generate_gds_perf.py +++ b/examples/generate_gds_perf.py @@ -1,4 +1,4 @@ -from masque.file.gdsii_perf import main +from masque.file.gdsii.perf import main if __name__ == '__main__': diff --git a/examples/profile_gdsii_readers.py b/examples/profile_gdsii_readers.py index fb7c99e..0eb05a5 100644 --- a/examples/profile_gdsii_readers.py +++ b/examples/profile_gdsii_readers.py @@ -12,7 +12,7 @@ from masque import LibraryError READERS: dict[str, tuple[str, tuple[str, ...]]] = { 'gdsii': ('masque.file.gdsii', ('readfile',)), - 'gdsii_arrow': ('masque.file.gdsii_arrow', ('readfile', 'arrow_import', 'arrow_convert')), + 'gdsii_arrow': ('masque.file.gdsii.arrow', ('readfile', 'arrow_import', 'arrow_convert')), } diff --git a/examples/tutorial/library.py b/examples/tutorial/library.py index d0ca60e..d7a2615 100644 --- a/examples/tutorial/library.py +++ b/examples/tutorial/library.py @@ -13,7 +13,7 @@ from pprint import pformat from masque import BuildLibrary, Pather, Pattern, cell from masque.file.gdsii import writefile -from masque.file.gdsii_lazy import readfile +from masque.file.gdsii.lazy import readfile import basic_shapes import devices diff --git a/masque/file/gdsii/__init__.py b/masque/file/gdsii/__init__.py new file mode 100644 index 0000000..09a0b03 --- /dev/null +++ b/masque/file/gdsii/__init__.py @@ -0,0 +1,10 @@ +""" +GDSII file format readers and writers. +""" +from .klamath import check_valid_names as check_valid_names +from .klamath import read as read +from .klamath import read_elements as read_elements +from .klamath import readfile as readfile +from .klamath import rint_cast as rint_cast +from .klamath import write as write +from .klamath import writefile as writefile diff --git a/masque/file/gdsii_arrow.py b/masque/file/gdsii/arrow.py similarity index 98% rename from masque/file/gdsii_arrow.py rename to masque/file/gdsii/arrow.py index 95229ea..2fcc7c9 100644 --- a/masque/file/gdsii_arrow.py +++ b/masque/file/gdsii/arrow.py @@ -43,12 +43,12 @@ from numpy.typing import ArrayLike, NDArray import pyarrow from pyarrow.cffi import ffi -from .utils import is_gzipped, tmpfile -from .. import Pattern, Ref, PatternError, LibraryError, Label, Shape -from ..shapes import Polygon, Path, PolyCollection, RectCollection -from ..repetition import Grid -from ..utils import layer_t, annotations_t -from ..library import LazyLibrary, Library, ILibrary, ILibraryView +from ..utils import is_gzipped, tmpfile +from ... import Pattern, Ref, PatternError, LibraryError, Label, Shape +from ...shapes import Polygon, Path, PolyCollection, RectCollection +from ...repetition import Grid +from ...utils import layer_t, annotations_t +from ...library import LazyLibrary, Library, ILibrary, ILibraryView logger = logging.getLogger(__name__) @@ -136,7 +136,7 @@ def _installed_library_candidates() -> list[pathlib.Path]: def _repo_library_candidates() -> list[pathlib.Path]: - repo_root = pathlib.Path(__file__).resolve().parents[2] + repo_root = pathlib.Path(__file__).resolve().parents[3] library_name = _local_library_filename() return [ repo_root / 'klamath-rs' / 'target' / 'release' / library_name, @@ -167,7 +167,7 @@ def is_available() -> bool: def _get_clib() -> Any: - global clib + global clib # noqa: PLW0603 if clib is None: lib_path = find_klamath_rs_library() if lib_path is None: diff --git a/masque/file/gdsii.py b/masque/file/gdsii/klamath.py similarity index 98% rename from masque/file/gdsii.py rename to masque/file/gdsii/klamath.py index 21c6f94..13d9e81 100644 --- a/masque/file/gdsii.py +++ b/masque/file/gdsii/klamath.py @@ -33,12 +33,12 @@ from numpy.typing import ArrayLike, NDArray import klamath from klamath import records -from .utils import is_gzipped, tmpfile -from .. import Pattern, Ref, PatternError, LibraryError, Label, Shape -from ..shapes import Polygon, Path, RectCollection -from ..repetition import Grid -from ..utils import layer_t, annotations_t -from ..library import Library, ILibrary +from ..utils import is_gzipped, tmpfile +from ... import Pattern, Ref, PatternError, LibraryError, Label, Shape +from ...shapes import Polygon, Path, RectCollection +from ...repetition import Grid +from ...utils import layer_t, annotations_t +from ...library import Library, ILibrary logger = logging.getLogger(__name__) diff --git a/masque/file/gdsii_lazy.py b/masque/file/gdsii/lazy.py similarity index 97% rename from masque/file/gdsii_lazy.py rename to masque/file/gdsii/lazy.py index a0b6e6f..7ddc76d 100644 --- a/masque/file/gdsii_lazy.py +++ b/masque/file/gdsii/lazy.py @@ -10,7 +10,7 @@ This module provides the non-Arrow half of Masque's lazy GDS architecture: - the source can be wrapped in `PortsLibraryView` or merged through `OverlayLibrary` -The public surface intentionally parallels `gdsii_lazy_arrow` closely so that +The public surface intentionally parallels `gdsii.lazy_arrow` closely so that callers can swap between the classic and Arrow-backed implementations with minimal changes. """ @@ -29,24 +29,24 @@ import klamath import numpy from klamath import records -from . import gdsii -from .utils import is_gzipped -from .gdsii_lazy_core import write as write, writefile as writefile -from ..error import LibraryError -from ..library import ( +from . import klamath as gdsii +from .lazy_write import write as write, writefile as writefile +from ..utils import is_gzipped +from ...error import LibraryError +from ...library import ( ILibraryView, LibraryView, PortsLibraryView, dangling_mode_t, ) -from ..utils import apply_transforms +from ...utils import apply_transforms if TYPE_CHECKING: from collections.abc import Iterator, Sequence from numpy.typing import NDArray - from ..pattern import Pattern + from ...pattern import Pattern logger = logging.getLogger(__name__) diff --git a/masque/file/gdsii_lazy_arrow.py b/masque/file/gdsii/lazy_arrow.py similarity index 94% rename from masque/file/gdsii_lazy_arrow.py rename to masque/file/gdsii/lazy_arrow.py index a53c1ff..6d14f0a 100644 --- a/masque/file/gdsii_lazy_arrow.py +++ b/masque/file/gdsii/lazy_arrow.py @@ -1,7 +1,7 @@ """ Lazy GDSII readers and writers backed by native Arrow scan/materialize paths. -This module is intentionally separate from `gdsii_arrow` so the eager read path +This module is intentionally separate from `gdsii.arrow` so the eager read path keeps its current behavior and performance profile. """ from __future__ import annotations @@ -16,16 +16,16 @@ import pathlib import numpy -from . import gdsii_arrow -from .utils import is_gzipped -from .gdsii_lazy_core import write as write, writefile as writefile -from ..library import ( +from . import arrow +from .lazy_write import write as write, writefile as writefile +from ..utils import is_gzipped +from ...library import ( ILibraryView, LibraryView, PortsLibraryView, dangling_mode_t, ) -from ..utils import apply_transforms +from ...utils import apply_transforms if TYPE_CHECKING: from collections.abc import Iterator, Sequence @@ -33,7 +33,7 @@ if TYPE_CHECKING: from numpy.typing import NDArray import pyarrow - from ..pattern import Pattern + from ...pattern import Pattern logger = logging.getLogger(__name__) @@ -87,11 +87,11 @@ class _ScanPayload: refs: _ScanRefs def is_available() -> bool: - return gdsii_arrow.is_available() + return arrow.is_available() def _read_header(libarr: pyarrow.StructScalar) -> dict[str, Any]: - return gdsii_arrow._read_header(libarr) + return arrow._read_header(libarr) def _open_source_buffer(path: pathlib.Path) -> _SourceBuffer: @@ -119,10 +119,10 @@ def _extract_scan_payload(libarr: pyarrow.StructScalar) -> _ScanPayload: ref_values = refs.values ref_offsets = refs.offsets.to_numpy() targets = ref_values.field('target').to_numpy() - xy = gdsii_arrow._packed_xy_u64_to_pairs(ref_values.field('xy').to_numpy()) - xy0 = gdsii_arrow._packed_xy_u64_to_pairs(ref_values.field('xy0').to_numpy()) - xy1 = gdsii_arrow._packed_xy_u64_to_pairs(ref_values.field('xy1').to_numpy()) - counts = gdsii_arrow._packed_counts_u32_to_pairs(ref_values.field('counts').to_numpy()) + xy = arrow._packed_xy_u64_to_pairs(ref_values.field('xy').to_numpy()) + xy0 = arrow._packed_xy_u64_to_pairs(ref_values.field('xy0').to_numpy()) + xy1 = arrow._packed_xy_u64_to_pairs(ref_values.field('xy1').to_numpy()) + counts = arrow._packed_counts_u32_to_pairs(ref_values.field('counts').to_numpy()) invert_y = ref_values.field('invert_y').to_numpy(zero_copy_only=False) angle_rad = ref_values.field('angle_rad').to_numpy() scale = ref_values.field('scale').to_numpy() @@ -228,7 +228,7 @@ class ArrowLibrary(ILibraryView): def from_file(cls, filename: str | pathlib.Path) -> ArrowLibrary: path = pathlib.Path(filename).expanduser().resolve() source = _open_source_buffer(path) - scan_arr = gdsii_arrow._scan_buffer_to_arrow(source.data) + scan_arr = arrow._scan_buffer_to_arrow(source.data) assert len(scan_arr) == 1 payload = _extract_scan_payload(scan_arr[0]) return cls(path=path, payload=payload, source=source) @@ -288,9 +288,9 @@ class ArrowLibrary(ILibraryView): ], dtype=numpy.uint64, ) - arrow_arr = gdsii_arrow._read_selected_cells_to_arrow(self._source.data, ranges) + arrow_arr = arrow._read_selected_cells_to_arrow(self._source.data, ranges) assert len(arrow_arr) == 1 - selected_lib, _info = gdsii_arrow.read_arrow(arrow_arr[0]) + selected_lib, _info = arrow.read_arrow(arrow_arr[0]) for name in uncached: pat = selected_lib[name] materialized[name] = pat diff --git a/masque/file/gdsii_lazy_core.py b/masque/file/gdsii/lazy_write.py similarity index 96% rename from masque/file/gdsii_lazy_core.py rename to masque/file/gdsii/lazy_write.py index 988f9a4..8cb167a 100644 --- a/masque/file/gdsii_lazy_core.py +++ b/masque/file/gdsii/lazy_write.py @@ -15,16 +15,16 @@ import pathlib import klamath -from . import gdsii -from .utils import tmpfile -from ..error import LibraryError -from ..library import ILibraryView, OverlayLibrary -from ..library.overlay import _SourceEntry, _materialize_detached_pattern +from . import klamath as gdsii +from ..utils import tmpfile +from ...error import LibraryError +from ...library import ILibraryView, OverlayLibrary +from ...library.overlay import _SourceEntry, _materialize_detached_pattern if TYPE_CHECKING: from collections.abc import Iterator, Mapping - from ..pattern import Pattern + from ...pattern import Pattern logger = logging.getLogger(__name__) diff --git a/masque/file/gdsii_perf.py b/masque/file/gdsii/perf.py similarity index 98% rename from masque/file/gdsii_perf.py rename to masque/file/gdsii/perf.py index 38d1a7d..339d1e0 100644 --- a/masque/file/gdsii_perf.py +++ b/masque/file/gdsii/perf.py @@ -244,7 +244,7 @@ def _annotation(index: int) -> dict[int, bytes]: return {1: f'perf-{index}'.encode('ASCII')} -def _make_box_cell(name: str, index: int, cfg: FixturePreset) -> list[elements.Element]: +def _make_box_cell(index: int, cfg: FixturePreset) -> list[elements.Element]: cell_elements: list[elements.Element] = [] xbase = (index % 17) * 600 ybase = (index // 17) * 180 @@ -277,7 +277,7 @@ def _make_box_cell(name: str, index: int, cfg: FixturePreset) -> list[elements.E return cell_elements -def _make_poly_cell(name: str, index: int, cfg: FixturePreset) -> list[elements.Element]: +def _make_poly_cell(index: int, cfg: FixturePreset) -> list[elements.Element]: cell_elements: list[elements.Element] = [] xbase = (index % 19) * 900 ybase = (index // 19) * 260 @@ -368,12 +368,12 @@ def _poly_cluster_name(index: int) -> str: def _write_box_cells(stream: Any, cfg: FixturePreset) -> None: for idx in range(cfg.box_cells): - _write_struct(stream, _box_name(idx), _make_box_cell(_box_name(idx), idx, cfg)) + _write_struct(stream, _box_name(idx), _make_box_cell(idx, cfg)) def _write_poly_cells(stream: Any, cfg: FixturePreset) -> None: for idx in range(cfg.poly_cells): - _write_struct(stream, _poly_name(idx), _make_poly_cell(_poly_name(idx), idx, cfg)) + _write_struct(stream, _poly_name(idx), _make_poly_cell(idx, cfg)) def _write_wrappers(stream: Any, cfg: FixturePreset) -> None: diff --git a/masque/test/test_gdsii_arrow.py b/masque/test/test_gdsii_arrow.py index b2962f8..47f9ac8 100644 --- a/masque/test/test_gdsii_arrow.py +++ b/masque/test/test_gdsii_arrow.py @@ -14,8 +14,9 @@ from ..library import Library from ..pattern import Pattern from ..repetition import Grid from ..shapes import Path as MPath, Polygon, PolyCollection, RectCollection -from ..file import gdsii, gdsii_arrow -from ..file.gdsii_perf import write_fixture +from ..file import gdsii +from ..file.gdsii import arrow as gdsii_arrow +from ..file.gdsii.perf import write_fixture if not gdsii_arrow.is_available(): @@ -267,7 +268,7 @@ def test_gdsii_arrow_invalid_input_raises_klamath_error(tmp_path: Path) -> None: gds_file.write_bytes(b'not-a-gds') script = textwrap.dedent(f""" - from masque.file import gdsii_arrow + from masque.file.gdsii import arrow as gdsii_arrow try: gdsii_arrow.readfile({str(gds_file)!r}) except Exception as exc: diff --git a/masque/test/test_gdsii_lazy.py b/masque/test/test_gdsii_lazy.py index 3abaab8..026580f 100644 --- a/masque/test/test_gdsii_lazy.py +++ b/masque/test/test_gdsii_lazy.py @@ -4,7 +4,8 @@ import numpy import pytest from numpy.testing import assert_allclose -from ..file import gdsii, gdsii_lazy +from ..file import gdsii +from ..file.gdsii import lazy as gdsii_lazy from ..pattern import Pattern from ..library import Library, OverlayLibrary diff --git a/masque/test/test_gdsii_lazy_arrow.py b/masque/test/test_gdsii_lazy_arrow.py index 0984b20..0447921 100644 --- a/masque/test/test_gdsii_lazy_arrow.py +++ b/masque/test/test_gdsii_lazy_arrow.py @@ -13,8 +13,9 @@ from .. import PatternError from ..library import Library, OverlayLibrary from ..pattern import Pattern from ..repetition import Grid -from ..file import gdsii, gdsii_lazy_arrow -from ..file.gdsii_perf import write_fixture +from ..file import gdsii +from ..file.gdsii import lazy_arrow as gdsii_lazy_arrow +from ..file.gdsii.perf import write_fixture if not gdsii_lazy_arrow.is_available(): @@ -177,7 +178,7 @@ def test_gdsii_lazy_arrow_invalid_input_raises_klamath_error(tmp_path: Path) -> gds_file.write_bytes(b'not-a-gds') script = textwrap.dedent(f""" - from masque.file import gdsii_lazy_arrow + from masque.file.gdsii import lazy_arrow as gdsii_lazy_arrow try: gdsii_lazy_arrow.readfile({str(gds_file)!r}) except Exception as exc: diff --git a/masque/test/test_gdsii_perf.py b/masque/test/test_gdsii_perf.py index a595fe8..09b3a5a 100644 --- a/masque/test/test_gdsii_perf.py +++ b/masque/test/test_gdsii_perf.py @@ -3,7 +3,7 @@ import json from pathlib import Path from ..file import gdsii -from ..file.gdsii_perf import fixture_manifest, write_fixture +from ..file.gdsii.perf import fixture_manifest, write_fixture def test_gdsii_perf_fixture_smoke(tmp_path: Path) -> None: