[arrow] add lazy arrow reader
This commit is contained in:
parent
e009417eed
commit
c83846afb3
5 changed files with 1237 additions and 16 deletions
|
|
@ -187,6 +187,18 @@ def test_gdsii_arrow_matches_gdsii_readfile(tmp_path: Path) -> None:
|
|||
assert _library_summary(canonical_lib) == _library_summary(arrow_lib)
|
||||
|
||||
|
||||
def test_gdsii_arrow_readfile_arrow_returns_native_payload(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'many_cells_native.gds'
|
||||
manifest = write_fixture(gds_file, preset='many_cells', scale=0.001)
|
||||
|
||||
libarr, info = gdsii_arrow.readfile_arrow(gds_file)
|
||||
|
||||
assert info['name'] == manifest.library_name
|
||||
assert libarr['lib_name'].as_py() == manifest.library_name
|
||||
assert len(libarr['cells']) == manifest.cells
|
||||
assert 0 < len(libarr['layers']) <= manifest.layers
|
||||
|
||||
|
||||
def test_gdsii_arrow_reads_small_perf_fixture(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'many_cells_smoke.gds'
|
||||
manifest = write_fixture(gds_file, preset='many_cells', scale=0.001)
|
||||
|
|
|
|||
174
masque/test/test_gdsii_lazy_arrow.py
Normal file
174
masque/test/test_gdsii_lazy_arrow.py
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
from pathlib import Path
|
||||
|
||||
import numpy
|
||||
import pytest
|
||||
|
||||
pytest.importorskip('pyarrow')
|
||||
|
||||
from ..library import Library
|
||||
from ..pattern import Pattern
|
||||
from ..repetition import Grid
|
||||
from ..file import gdsii, gdsii_lazy_arrow
|
||||
from ..file.gdsii_perf import write_fixture
|
||||
|
||||
|
||||
if not gdsii_lazy_arrow.is_available():
|
||||
pytest.skip('klamath_rs_ext shared library is not available', allow_module_level=True)
|
||||
|
||||
|
||||
def _make_small_library() -> Library:
|
||||
lib = Library()
|
||||
|
||||
leaf = Pattern()
|
||||
leaf.polygon((1, 0), vertices=[[0, 0], [10, 0], [10, 5], [0, 5]])
|
||||
lib['leaf'] = leaf
|
||||
|
||||
mid = Pattern()
|
||||
mid.ref('leaf', offset=(10, 20))
|
||||
mid.ref('leaf', offset=(40, 0), repetition=Grid(a_vector=(12, 0), a_count=2, b_vector=(0, 9), b_count=2))
|
||||
lib['mid'] = mid
|
||||
|
||||
top = Pattern()
|
||||
top.ref('mid', offset=(100, 200))
|
||||
lib['top'] = top
|
||||
return lib
|
||||
|
||||
|
||||
def test_gdsii_lazy_arrow_loads_perf_fixture(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'many_cells_lazy.gds'
|
||||
manifest = write_fixture(gds_file, preset='many_cells', scale=0.001)
|
||||
|
||||
lib, info = gdsii_lazy_arrow.readfile(gds_file)
|
||||
|
||||
assert info['name'] == manifest.library_name
|
||||
assert len(lib) == manifest.cells
|
||||
assert lib.top() == 'TOP'
|
||||
assert 'TOP' in lib.child_graph(dangling='ignore')
|
||||
|
||||
|
||||
def test_gdsii_lazy_arrow_local_and_global_refs(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'refs.gds'
|
||||
src = _make_small_library()
|
||||
gdsii.writefile(src, gds_file, meters_per_unit=1e-9, library_name='lazy-refs')
|
||||
|
||||
lib, _ = gdsii_lazy_arrow.readfile(gds_file)
|
||||
|
||||
local = lib.find_refs_local('leaf')
|
||||
assert set(local) == {'mid'}
|
||||
assert sum(arr.shape[0] for arr in local['mid']) == 5
|
||||
|
||||
global_refs = lib.find_refs_global('leaf')
|
||||
assert {path for path in global_refs} == {('top', 'mid', 'leaf')}
|
||||
assert global_refs[('top', 'mid', 'leaf')].shape[0] == 5
|
||||
|
||||
|
||||
def test_gdsii_lazy_arrow_untouched_write_is_copy_through(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'copy_source.gds'
|
||||
src = _make_small_library()
|
||||
gdsii.writefile(src, gds_file, meters_per_unit=1e-9, library_name='copy-through')
|
||||
|
||||
lib, info = gdsii_lazy_arrow.readfile(gds_file)
|
||||
out_file = tmp_path / 'copy_out.gds'
|
||||
gdsii_lazy_arrow.writefile(
|
||||
lib,
|
||||
out_file,
|
||||
meters_per_unit=info['meters_per_unit'],
|
||||
logical_units_per_unit=info['logical_units_per_unit'],
|
||||
library_name=info['name'],
|
||||
)
|
||||
|
||||
assert out_file.read_bytes() == gds_file.read_bytes()
|
||||
|
||||
|
||||
def test_gdsii_lazy_overlay_merge_and_write(tmp_path: Path) -> None:
|
||||
base_a = Library()
|
||||
leaf_a = Pattern()
|
||||
leaf_a.polygon((1, 0), vertices=[[0, 0], [8, 0], [8, 8], [0, 8]])
|
||||
base_a['leaf'] = leaf_a
|
||||
top_a = Pattern()
|
||||
top_a.ref('leaf', offset=(0, 0))
|
||||
base_a['top_a'] = top_a
|
||||
|
||||
base_b = Library()
|
||||
leaf_b = Pattern()
|
||||
leaf_b.polygon((2, 0), vertices=[[0, 0], [5, 0], [5, 5], [0, 5]])
|
||||
base_b['leaf'] = leaf_b
|
||||
top_b = Pattern()
|
||||
top_b.ref('leaf', offset=(20, 30))
|
||||
base_b['top_b'] = top_b
|
||||
|
||||
gds_a = tmp_path / 'a.gds'
|
||||
gds_b = tmp_path / 'b.gds'
|
||||
gdsii.writefile(base_a, gds_a, meters_per_unit=1e-9, library_name='overlay')
|
||||
gdsii.writefile(base_b, gds_b, meters_per_unit=1e-9, library_name='overlay')
|
||||
|
||||
lib_a, _ = gdsii_lazy_arrow.readfile(gds_a)
|
||||
lib_b, _ = gdsii_lazy_arrow.readfile(gds_b)
|
||||
|
||||
overlay = gdsii_lazy_arrow.OverlayLibrary()
|
||||
overlay.add_source(lib_a)
|
||||
rename_map = overlay.add_source(lib_b, rename_theirs=lambda lib, name: lib.get_name(name))
|
||||
renamed_leaf = rename_map['leaf']
|
||||
|
||||
assert rename_map == {'leaf': renamed_leaf}
|
||||
assert renamed_leaf != 'leaf'
|
||||
assert len(lib_a._cache) == 0
|
||||
assert len(lib_b._cache) == 0
|
||||
|
||||
overlay.move_references('leaf', renamed_leaf)
|
||||
|
||||
out_file = tmp_path / 'overlay_out.gds'
|
||||
gdsii_lazy_arrow.writefile(overlay, out_file)
|
||||
|
||||
roundtrip, _ = gdsii.readfile(out_file)
|
||||
assert set(roundtrip.keys()) == {'leaf', renamed_leaf, 'top_a', 'top_b'}
|
||||
assert 'top_b' in roundtrip
|
||||
assert list(roundtrip['top_b'].refs.keys()) == [renamed_leaf]
|
||||
|
||||
|
||||
def test_gdsii_writer_accepts_overlay_library(tmp_path: Path) -> None:
|
||||
gds_file = tmp_path / 'overlay_source.gds'
|
||||
src = _make_small_library()
|
||||
gdsii.writefile(src, gds_file, meters_per_unit=1e-9, library_name='overlay-src')
|
||||
|
||||
lib, info = gdsii_lazy_arrow.readfile(gds_file)
|
||||
|
||||
overlay = gdsii_lazy_arrow.OverlayLibrary()
|
||||
overlay.add_source(lib)
|
||||
overlay.rename('leaf', 'leaf_copy', move_references=True)
|
||||
|
||||
out_file = tmp_path / 'overlay_via_eager_writer.gds'
|
||||
gdsii.writefile(
|
||||
overlay,
|
||||
out_file,
|
||||
meters_per_unit=info['meters_per_unit'],
|
||||
logical_units_per_unit=info['logical_units_per_unit'],
|
||||
library_name=info['name'],
|
||||
)
|
||||
|
||||
roundtrip, _ = gdsii.readfile(out_file)
|
||||
assert set(roundtrip.keys()) == {'leaf_copy', 'mid', 'top'}
|
||||
assert list(roundtrip['mid'].refs.keys()) == ['leaf_copy']
|
||||
|
||||
|
||||
def test_svg_writer_uses_detached_materialized_copy(tmp_path: Path) -> None:
|
||||
pytest.importorskip('svgwrite')
|
||||
from ..file import svg
|
||||
from ..shapes import Path as MPath
|
||||
|
||||
gds_file = tmp_path / 'svg_source.gds'
|
||||
src = _make_small_library()
|
||||
src['top'].path((3, 0), vertices=[[0, 0], [0, 20]], width=4)
|
||||
gdsii.writefile(src, gds_file, meters_per_unit=1e-9, library_name='svg-src')
|
||||
|
||||
lib, _ = gdsii_lazy_arrow.readfile(gds_file)
|
||||
top_pat = lib['top']
|
||||
assert list(top_pat.refs.keys()) == ['mid']
|
||||
assert any(isinstance(shape, MPath) for shape in top_pat.shapes[(3, 0)])
|
||||
|
||||
svg_path = tmp_path / 'lazy.svg'
|
||||
svg.writefile(lib, 'top', str(svg_path))
|
||||
|
||||
assert svg_path.exists()
|
||||
assert list(top_pat.refs.keys()) == ['mid']
|
||||
assert any(isinstance(shape, MPath) for shape in top_pat.shapes[(3, 0)])
|
||||
Loading…
Add table
Add a link
Reference in a new issue