core_lens.base.view#

Lazy, immutable view of a scoped entity pending materialisation.

Classes#

Season

Season enum.

View

Lazy, immutable snapshot of a scoped entity pending materialisation.

Module Contents#

class core_lens.base.view.Season(*args, **kwds)#

Bases: enum.Enum

Season enum.

Enumerates standard agronomic seasons used across Core Lens for temporal filtering.

KHARIF = 'kharif'#
RABI = 'rabi'#
ZAID = 'zaid'#
CURRENT = 'current'#
class core_lens.base.view.View(keys: polars.DataFrame | polars.LazyFrame, entity: core_lens.base.entity.BaseEntity, entity_name: str, time_filter: dict[str, Any] | None = None, join_spec: dict[str, Any] | None = None, season_config: core_lens.aoi.SeasonConfig | None = None)#

Lazy, immutable snapshot of a scoped entity pending materialisation.

A View is produced by the filter methods on BaseEntity (where(), spatial_filter(), spatial_join()). It records what to load without touching any Parquet file. Data is only scanned when one of the three materialisation properties is accessed, and is materialised when .df() is called on the returned Result.

View is immutable. Every method that would mutate state instead returns a new View with the updated field, leaving the original untouched. This makes it safe to branch a view and materialise it in different ways:

view = aoi.mws.where(tehsil="Pangi")
annual = view.between("2010-01-01", "2023-12-31").annual
static = view.static
Variables:
  • keys – A pl.LazyFrame containing the resolved key column(s) for all entity instances that passed the spatial/attribute filters. This is the index slice — no data columns, only IDs.

  • entity – Reference to the parent BaseEntity that produced this view. Used during materialisation to resolve file paths and schema.

  • entity_name – Human-readable name for the entity (e.g. "mws"). Used to namespace joined columns and populate entity_name.

  • time_filter – A dict encoding the pending time constraint set by between(), or None if no time filter has been applied. The materialisation step reads this dict to build predicate pushdown expressions.

  • join_spec – A dict encoding a deferred spatial_join() request, or None. Evaluated during materialisation after the primary scan is complete.

keys#
entity#
entity_name#
time_filter = None#
join_spec = None#
where(**kwargs: Any) View#

Return a new View further filtered by attributes.

Each keyword argument is interpreted as column=value applied to the static file’s attribute columns. Multiple arguments are AND-ed.

Parameters:

**kwargs (Any) – Arbitrary column–value pairs to filter on.

Returns:

A new lazy View with the narrowed keys.

Return type:

View

spatial_filter(geometry: shapely.Geometry | None = None, bbox: tuple[float, float, float, float] | None = None, relationship: str = 'centroid', threshold: float = 0.5) View#

Return a new View further filtered by geometry.

Uses the in-memory bbox index for a fast rectangular pre-filter, then refines with a Shapely STRtree exact-relationship check.

Parameters:
  • geometry (shapely.Geometry | None, optional) – A Shapely geometry representing the spatial extent.

  • bbox (tuple[float, float, float, float] | None, optional) – Bounding box as (minx, miny, maxx, maxy) in WGS-84.

  • relationship (str, optional) – "centroid" (default) or "area" mode.

  • threshold (float, optional) – Area coverage threshold for "area" mode. Default 0.5.

Returns:

A new lazy View scoped to the given spatial extent.

Return type:

View

Raises:

ValueError – If neither geometry nor bbox is provided.

spatial_join(other: core_lens.base.entity.BaseEntity, agg: dict[str, str]) View#

Return a new View with a cross-entity join pending.

The join is recorded in the View’s join_spec and computed only at materialisation time (.static, .annual, or .sub_annual).

Parameters:
  • other (BaseEntity) – The secondary BaseEntity whose columns will be joined and aggregated onto self.

  • agg (dict[str, str]) – Mapping of {column: aggregation} specifying which columns from other to bring in and how to aggregate them.

Returns:

A new lazy View with the join spec recorded.

Return type:

View

between(start: str | None = None, end: str | None = None, *, season: Season | None = None, year: int | tuple[int, int] | None = None) View#

Return a new View with a pending time filter applied.

Two mutually exclusive modes are supported:

Date range mode — pass start and end as ISO-8601 strings:

view.between("2010-01-01", "2023-12-31")

Season mode — pass season as a keyword argument. year is optional and may be a single year or an inclusive (from, to) tuple:

from core_lens.base.view import Season

view.between(season=Season.KHARIF)
view.between(season=Season.KHARIF, year=2020)
view.between(season=Season.KHARIF, year=(2018, 2023))
view.between(season=Season.CURRENT)

The returned View carries the filter in time_filter but does not execute any I/O. The filter is applied during materialisation via predicate pushdown on the Parquet scan.

Parameters:
  • start (str | None, optional) – Start of the date range (ISO-8601). Required in date range mode; must be None in season mode.

  • end (str | None, optional) – End of the date range (ISO-8601). Required in date range mode; must be None in season mode.

  • season (Season | None, optional) – A Season enum value. Activates season mode.

  • year (int | tuple[int, int] | None, optional) – Year or inclusive year range to restrict the season filter. Only valid in season mode. "current" season ignores this.

Returns:

A new View with time_filter set.

Return type:

View

Raises:

ValueError – If the arguments are inconsistent (e.g. mixing date range and season arguments, omitting required args, or supplying year with season="current").

property static: core_lens.base.result.Result#

Resolve the static GeoParquet file scan and return a Result.

The result always has has_geometry=True because the static file is a GeoParquet carrying geometry for every entity instance.

Returns:

A Result with resolution="static" and has_geometry=True.

Return type:

Result

Raises:

AttributeError – If the entity has no static_path (should not happen in practice since static_path is mandatory).

property annual: core_lens.base.result.Result#

Resolve the annual Parquet file scan and return a Result.

Returns:

A Result with resolution="annual" and has_geometry=False.

Return type:

Result

Raises:

AttributeError – If the entity has no annual_path.

property sub_annual: core_lens.base.result.Result#

Resolve the sub_annual Parquet file scan and return a Result.

Returns:

A Result with resolution="sub_annual" and has_geometry=False.

Return type:

Result

Raises:

AttributeError – If the entity has no sub_annual_path.