core-lens 0.1.dev142__tar.gz → 0.1.dev143__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/PKG-INFO +1 -1
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/_version.py +2 -2
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/aoi.py +29 -42
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_aoi.py +4 -2
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/ISSUE_TEMPLATE/blank-proposal.yaml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/ISSUE_TEMPLATE/bug-report.yaml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/ISSUE_TEMPLATE/feature-request.yaml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/pull_request_template.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/workflows/ci.yml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/workflows/gh-pages.yml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/workflows/pre-release.yml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.github/workflows/release.yml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.gitignore +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.gitmessage +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.pre-commit-config.yaml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/.python-version +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/CONTRIBUTING.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/LICENSE +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/README.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/SKILLS.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/README.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_aoi.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_export.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_polars_utils.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_result.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_schema.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_season.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_spatial.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/bench_view.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/benchmarks/run_all.sh +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/Makefile +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/make.bat +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/concepts.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/conf.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/export.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/index.rst +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/intro.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/logging.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/plots.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/plugins.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/queries.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/quickstart.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/docs/source/stats.md +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/examples/demo_mws.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/examples/demo_tehsil.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/hooks/mypy.sh +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/hooks/no-parquet-outside-fixtures.sh +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/hooks/pytest.sh +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/pyproject.toml +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/__init__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/__main__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/base/__init__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/base/entity.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/base/namespaces/__init__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/base/namespaces/plot.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/base/namespaces/stats.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/base/result.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/base/view.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/entities/__init__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/entities/mws.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/entities/tehsil.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/entities/waterbody.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/export/__init__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/export/formats.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/py.typed +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/schema/__init__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/schema/detection.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/schema/profile.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/utils/__init__.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/utils/paths.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/utils/polars_utils.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/utils/season.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/src/core_lens/utils/spatial.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/fixtures/generate_fixtures.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/conftest.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_entities.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_entity.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_export.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_main.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_plot.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_polars_utils.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_profile.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_result.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_schema_detection.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_schema_profile.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_season.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_season_config.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_spatial.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_stats.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/tests/unit/test_view.py +0 -0
- {core_lens-0.1.dev142 → core_lens-0.1.dev143}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-lens
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.dev143
|
|
4
4
|
Summary: Query, analyse, and visualise CoreStack's microwatershed and Earth science data through a clean, composable Python API.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ApoorvaKashyap/core-lens
|
|
6
6
|
Project-URL: Issues, https://github.com/ApoorvaKashyap/core-lens/issues
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1, '
|
|
21
|
+
__version__ = version = '0.1.dev143'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 'dev143')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -383,19 +383,16 @@ class AoI:
|
|
|
383
383
|
# Entity instances are created lazily on first access via _get_entity().
|
|
384
384
|
self._entity_instances: dict[str, BaseEntity] = {}
|
|
385
385
|
|
|
386
|
-
# Initialise boundary
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
# to the normal spatial_filter path for every entity.
|
|
390
|
-
self._boundary_entity_name: str | None = None
|
|
391
|
-
self._boundary_keys: pl.DataFrame | None = None
|
|
386
|
+
# Initialise boundary kwargs and lazily computed geometry.
|
|
387
|
+
self._boundary_kwargs: dict[str, str | list[str]] | None = None
|
|
388
|
+
self._geometry: shapely.Geometry | None = None
|
|
392
389
|
|
|
393
390
|
if geometry is not None:
|
|
394
|
-
self.
|
|
391
|
+
self._geometry = geometry
|
|
395
392
|
elif bbox is not None:
|
|
396
|
-
self.
|
|
393
|
+
self._geometry = _bbox_to_polygon(bbox)
|
|
397
394
|
else:
|
|
398
|
-
self.
|
|
395
|
+
self._boundary_kwargs = entity_kwargs
|
|
399
396
|
|
|
400
397
|
# Entity views are created lazily on demand in __getattr__.
|
|
401
398
|
self._scoped: dict[str, "View"] = {}
|
|
@@ -406,6 +403,17 @@ class AoI:
|
|
|
406
403
|
if validate_all:
|
|
407
404
|
self.validate()
|
|
408
405
|
|
|
406
|
+
@property
|
|
407
|
+
def geometry(self) -> "shapely.Geometry":
|
|
408
|
+
"""The resolved boundary of this AoI as a Shapely geometry."""
|
|
409
|
+
if self._geometry is None:
|
|
410
|
+
if self._boundary_kwargs is not None:
|
|
411
|
+
self._geometry = self._resolve_named_boundary(self._boundary_kwargs)
|
|
412
|
+
else:
|
|
413
|
+
# Should not happen if initialization was correct
|
|
414
|
+
raise ValueError("No boundary defined.")
|
|
415
|
+
return self._geometry
|
|
416
|
+
|
|
409
417
|
@property
|
|
410
418
|
def current_season(self) -> str:
|
|
411
419
|
"""The season name for today's date under the AoI's SeasonConfig.
|
|
@@ -538,23 +546,20 @@ class AoI:
|
|
|
538
546
|
if name in _REGISTRY:
|
|
539
547
|
if name not in self._scoped:
|
|
540
548
|
entity = self._get_entity(name)
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
#
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
self.
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
keys=self._boundary_keys,
|
|
553
|
-
entity=entity,
|
|
554
|
-
entity_name=name,
|
|
555
|
-
)
|
|
549
|
+
|
|
550
|
+
if self._boundary_kwargs is not None:
|
|
551
|
+
schema = entity.schema_profile
|
|
552
|
+
# If this entity has all the filter columns natively, filter directly
|
|
553
|
+
if all(
|
|
554
|
+
k in schema.key_cols or k in schema.extra_static_cols
|
|
555
|
+
for k in self._boundary_kwargs
|
|
556
|
+
):
|
|
557
|
+
view = entity.where(**self._boundary_kwargs)
|
|
558
|
+
else:
|
|
559
|
+
view = entity.spatial_filter(geometry=self.geometry)
|
|
556
560
|
else:
|
|
557
561
|
view = entity.spatial_filter(geometry=self.geometry)
|
|
562
|
+
|
|
558
563
|
view._season_config = self.seasons
|
|
559
564
|
self._scoped[name] = view
|
|
560
565
|
return self._scoped[name]
|
|
@@ -608,24 +613,6 @@ class AoI:
|
|
|
608
613
|
# Reconstruct the boundary geometry from cached WKB bytes (fast).
|
|
609
614
|
geometry: shapely.Geometry = shapely.from_wkb(geom_wkb)
|
|
610
615
|
|
|
611
|
-
# Reconstruct _boundary_keys DataFrame from cached key_rows.
|
|
612
|
-
# We need the key column names — get them from the boundary entity.
|
|
613
|
-
boundary_entity_cls = _REGISTRY.get(boundary_entity_name)
|
|
614
|
-
if boundary_entity_cls is not None:
|
|
615
|
-
key_cols = boundary_entity_cls().key_cols
|
|
616
|
-
self._boundary_entity_name = boundary_entity_name
|
|
617
|
-
self._boundary_keys = pl.DataFrame(
|
|
618
|
-
{col: [row[i] for row in key_rows] for i, col in enumerate(key_cols)}
|
|
619
|
-
)
|
|
620
|
-
else:
|
|
621
|
-
# Registry changed since cache was populated — defensive fallback.
|
|
622
|
-
logger.warning(
|
|
623
|
-
"Boundary cache returned entity name '{}' not found in current registry.",
|
|
624
|
-
boundary_entity_name,
|
|
625
|
-
)
|
|
626
|
-
self._boundary_entity_name = None
|
|
627
|
-
self._boundary_keys = None
|
|
628
|
-
|
|
629
616
|
return geometry
|
|
630
617
|
|
|
631
618
|
@classmethod
|
|
@@ -389,13 +389,15 @@ class TestAoIResolveGeometry:
|
|
|
389
389
|
assert getattr(aoi.geometry, "equals", lambda x: False)(union)
|
|
390
390
|
|
|
391
391
|
with pytest.raises(ValueError, match="No rows matched the filters"):
|
|
392
|
-
AoI(data_root=str(tmp_path), mws_id="999")
|
|
392
|
+
bad_aoi = AoI(data_root=str(tmp_path), mws_id="999")
|
|
393
|
+
_ = bad_aoi.geometry
|
|
393
394
|
|
|
394
395
|
with pytest.raises(
|
|
395
396
|
EntityValidationError,
|
|
396
397
|
match="No registered entity can satisfy the filters",
|
|
397
398
|
):
|
|
398
|
-
AoI(data_root=str(tmp_path), unknown_key="1")
|
|
399
|
+
invalid_aoi = AoI(data_root=str(tmp_path), unknown_key="1")
|
|
400
|
+
_ = invalid_aoi.geometry
|
|
399
401
|
|
|
400
402
|
# Test fallback match by entity name
|
|
401
403
|
aoi_fallback = AoI(data_root=str(tmp_path), mws="1")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|