core_lens.aoi#

AoI (Area of Interest) — primary entry point for core_lens.

Classes#

SeasonConfig

Date-range definitions for the three Indian crop seasons.

AoI

Area of Interest — the primary entry point for querying geospatial data.

Module Contents#

class core_lens.aoi.SeasonConfig#

Date-range definitions for the three Indian crop seasons.

Each season is a (MM-DD, MM-DD) inclusive range. Seasons that cross the calendar year-end (e.g. rabi: Nov → Mar) are handled by comparing the month-day portion of a date against each range, rolling over where necessary.

The library ships with agronomic defaults for the Indo-Gangetic plain. Override at AoI construction time to match a different agro-climatic zone:

aoi = AoI("data/", district="Dharwad", seasons=SeasonConfig(
    kharif=("06-01", "10-15"),
    rabi=("10-16", "02-28"),
    zaid=("03-01", "05-31"),
))
Variables:
  • kharif – Kharif (monsoon) season range as (start_MM-DD, end_MM-DD).

  • rabi – Rabi (winter) season range.

  • zaid – Zaid (summer) season range.

kharif: tuple[str, str] = ('07-01', '10-31')#
rabi: tuple[str, str] = ('11-01', '03-31')#
zaid: tuple[str, str] = ('04-01', '06-30')#
__post_init__() None#

Initialize after dataclass creation.

Validates that all configured seasons have valid MM-DD ranges.

Raises:

ValueError – If a season date format is invalid.

season_for(d: datetime.date) str#

Return the season name for a given date.

Parameters:

d (date) – The date to classify.

Returns:

"kharif", "rabi", or "zaid".

Return type:

str

class core_lens.aoi.AoI(data_root: str, *, bbox: tuple[float, float, float, float] | None = None, geometry: shapely.Geometry | None = None, seasons: SeasonConfig | None = None, storage_options: dict[str, Any] | None = None, validate_all: bool = False, **entity_kwargs: str | list[str])#

Area of Interest — the primary entry point for querying geospatial data.

An AoI is two things simultaneously:

  1. A geometry — the resolved boundary of the named administrative unit (or a raw bbox / Shapely polygon), stored as geometry.

  2. A collection of scoped entities — every registered entity pre-filtered to instances that fall within geometry. Accessed as attributes: aoi.mws, aoi.village, aoi.forest, etc.

AoI holds no data itself. Entity attributes are lazy View objects; no Parquet I/O occurs until a materialisation property (.static, .annual, .sub_annual) is accessed on a View.

Registration must happen before any AoI is constructed:

from core_lens import AoI
from core_lens.entities import MWSEntity, TehsilEntity

AoI.register(MWSEntity)
AoI.register(TehsilEntity)

Initialisation — exactly one boundary argument is required:

aoi = AoI("data/", tehsil="Pangi", district="Chamba", state="Himachal Pradesh")
aoi = AoI("data/", bbox=(minx, miny, maxx, maxy))
aoi = AoI("data/", geometry=some_shapely_polygon)
aoi = AoI("data/", village="Shiroor")
aoi = AoI("data/", mws_id="13_551")

Entity access:

aoi.mws        # View — all MWS within the AoI boundary
aoi.tehsil     # View — all tehsils within the AoI boundary
aoi.forest     # View — plugin entity (if registered)
Variables:
  • data_root – Resolved path to the data directory.

  • geometry – Shapely polygon representing the AoI boundary.

  • seasonsSeasonConfig in effect for this AoI.

seasons: SeasonConfig = None#
property geometry: shapely.Geometry#

The resolved boundary of this AoI as a Shapely geometry.

property current_season: str#

The season name for today’s date under the AoI’s SeasonConfig.

Returns:

"kharif", "rabi", or "zaid".

Return type:

str

property current_year: int#

The current calendar year.

Returns:

Current year as an integer.

Return type:

int

plot(overlay: Result | None = None) Any#

Render an interactive Lonboard map of the AoI and its entity layers.

Parameters:

overlay (Result | None, optional) – An optional Result to overlay on the map.

Returns:

A Lonboard Map object.

Return type:

Any

validate() None#

Eagerly validate every registered entity.

Instantiates and validates all entities in _REGISTRY that have not yet been accessed. Raises on the first failure.

This is equivalent to the old eager-validation behaviour and is useful for startup health-checks in long-running services:

aoi = AoI("data/", bbox=(...), validate_all=True)
# or:
aoi = AoI("data/", bbox=(...))
aoi.validate()  # explicit call, same effect
Raises:

EntityValidationError – If any registered entity fails validation.

__getattr__(name: str) core_lens.base.view.View#

Get view by entity name.

Resolves and caches a scoped view for a registered entity on first access.

Parameters:

name – The registered entity name (e.g. ‘mws’).

Returns:

The scoped View for the entity.

Raises:

AttributeError – If the entity is not registered.

classmethod register(entity_cls: type[core_lens.base.entity.BaseEntity]) None#

Register an entity class so it is available on all future AoI instances.

The entity name is derived from the class name by stripping a trailing "Entity" suffix and lower-casing the result (MWSEntity"mws", ForestEntity"forest").

For entities with absolute paths, validation (file existence, key cols, geometry col) runs immediately at registration time. For entities with relative paths, validation is deferred until an AoI is instantiated (when data_root is known).

Parameters:

entity_cls (type[BaseEntity]) – A concrete subclass of BaseEntity.

Raises:

EntityValidationError – If any validation check fails (absolute-path entities only at register time).

classmethod deregister(entity_cls: type[core_lens.base.entity.BaseEntity]) None#

Remove a previously registered entity.

Primarily useful in tests where a clean registry is needed between runs.

Parameters:

entity_cls (type[BaseEntity]) – The entity class to remove.

classmethod registered_entities() list[str]#

Return the names of all currently registered entities.

Returns:

A sorted list of entity name strings.

Return type:

list[str]