Skip to content

API

Public Entry Point

Use EcosysEngine().run(request) with a validated SimulationRequest. This method delegates to integrate_on_grid(request), which uses exactly the explicit support in the request. EcosysEngine.run_default(...) builds a request with SimulationRequest.on_default_grid(...) and uses the same integrator. The engine uses the packaged canonical SQLite catalog of the default parameter set; an explicit ParameterCatalog can be supplied for controlled tests.

Parameter Sets

Three regional parameter sets from the original model are packaged. Select one by name when creating the engine or loading data:

from ecosys import EcosysEngine
from ecosys.data import load_model_data

engine = EcosysEngine()                          # default set: "valley"
engine = EcosysEngine(parameter_set="mountain")  # another packaged set
model = load_model_data(parameter_set="ticino_valais")
# For an existing custom database:
# model = load_model_data("my.sqlite", verify=True)

EcosysEngine.parameter_set and ModelData.parameter_set report the loaded set, or None for a database exported from an unregistered workbook. Passing both a catalog or path and a set name raises ValueError, as does an unknown name. The sets and their provenance are listed in Parameter Sets.

Databases are opened read-only and never created; a missing path raises FileNotFoundError. Every load checks the dataset metadata row and rejects unsupported schema versions with ecosys.data.DatasetValidationError. load_model_data(..., verify=True) or ecosys.data.validate_dataset(path) additionally runs SQLite's integrity and foreign-key checks, finite/non-negative value checks and a logical-digest comparison (python -m export_excel_data --validate my.sqlite does the same from the shell). After intentionally editing a database, call ecosys.data.validation.refresh_logical_digest(path): it records the new digest and clears the parameter_set label, since the file is no longer that set's registered export. A matching digest shows integrity and provenance, not scientific validity.

Loaded records are deeply immutable: quantities and arrays are read-only copies, so model.nuclides["cs_137"].half_life[...] = ... raises. The curve fields of PlantData are views of the authoritative lai_series, biomass_series and monthly_growth_half_lives that compilation reads. For a parameter study, model.with_overrides(nuclides=..., biomass_series=...) returns a new ModelData with whole fields replaced and re-validated; its overrides, metadata["base_logical_digest"] and metadata["base_parameter_set"] record what changed and from which dataset, and its parameter_set is None.

Inputs

  • DepositionEvent requires canonical nuclide IDs, Gregorian dates, integrated air activity in Bq s/m3 or an equivalent unit, wet deposition in Bq/m2, and rainfall in mm.
  • When the source is a constant air concentration over a known exposure period, construct the event with DepositionEvent.from_constant_air_concentration(...). The air_concentration must carry Bq/m3 and exposure_duration must carry time units; the result stores their product in Bq s/m3. For example, 300 * u.Bq / u.m**3 over 1 * u.day is equivalent to an integrated input of 7200 * u.Bq * u.hour / u.m**3, not 300 * u.Bq * u.hour / u.m**3.
  • PopulationCohorts requires ages in years and dimensionless population counts. Consumption has no free-form profile ID: it is selected from canonical age-indexed rates and interpolated by physical cohort age. initial_age is the age at output_start_date: one population ages on a single clock, so an event four years after the origin sees a one-year-old cohort at age five (cloud impulses use the age on the event date; interval pathways the age at each interval's end). Activity defaults to the canonical time_activity environment distribution; an explicit override must be a dimensionless quantity of shape batch + cohort + environment with exact canonical environment_ids that sums to one over the environment axis.
  • SimulationRequest.elapsed_times is a strictly increasing one-dimensional duration axis in equivalent Astropy time units measured from the explicit Gregorian output_start_date, which is required and never inferred from event dates. Fractional-day instants are preserved in request.output_datetimes; the output_dates property gives their containing Gregorian calendar dates. Each event's signed event_relative_days(event.date) is elapsed from its date. For a later event within the simulation window, shared support nodes before that event have zero event contribution. An event before a custom grid's output origin is rejected; prehistory is not inferred.
  • SimulationRequest.pathway_ids optionally selects exposure pathways. Ingestion is always included. cloud_external is an opt-in cloud-submersion impulse in the effective-dose total. Requesting skin as an effective-dose pathway still raises an unsupported-pathway error.
  • EcosysEngine.skin_tissue_dose(request) returns one SingleEventPathwayDose per event, with pathway ID skin_tissue. It follows the VBA's separate skin-organ branch, using the alpha/beta/gamma surface-dose coefficients, clothing fraction, dry/wet skin deposition, and finite retention time. Tissue doses are not included in effective-dose totals.

Time Support And Reports

SimulationRequest.elapsed_times is the low-level integration support, not just a list of report queries. It is a one-dimensional Astropy time quantity from output_start_date, accepts equivalent time units, starts at exactly zero, and is finite and strictly increasing. Its final point defines the custom run's finite horizon. Concentrations, animal states, and interval doses are evaluated on those support nodes; adding nodes may change numerical answers. run(request) uses that same explicit support.

For leading-batch workloads too large to retain as one result tree, EcosysEngine.iter_chunks(request, chunk_size=...) yields (batch_slice, SimulationResult) pairs. Batch dimensions are flattened in C order for the slice indices; each non-scalar chunk result has one leading chunk axis. Consume or persist each result before requesting the next chunk to keep memory bounded. The iterator does not concatenate chunks into a full in-memory result.

SimulationRequest.on_default_grid(...) and EcosysEngine.run_default(...) construct a deterministic, event-date-anchored VBA-style default support. For one event the explicit origin must equal the event date; for multiple events it must equal the earliest event date. The union uses absolute event dates and is clipped to the finite output horizon. This schedule choice does not imply VBA's numeric-unit conventions or its ration interpolation. For custom support, an event before the output origin is rejected, and each event within the finite run horizon must have an exact support node. Events after the horizon are outside that run's simulated window.

Each dose interval belongs to (t[i-1], t[i]]. At t[0] == 0, interval dose is zero except for the explicit deposition-day event impulses: cloud inhalation and, when requested, cloud_external submersion. A later event's impulses are assigned to the interval ending at its event node. Cumulative dose is the sum of interval doses and is neither an endpoint rate nor automatically annualized.

Every SimulationResult carries provenance, an immutable RunProvenance record: engine version, dataset schema/dataset/importer versions, logical digest, source-workbook sha256, parameter set, database file name, any with_overrides fields with the base digest and set, the support-grid kind, output origin, resolved pathway IDs, event nuclides and dates, and an input_digest over the complete request (raster inputs included). Chunked results carry the digest of the whole request and their batch_slice; ReportProjection.provenance exposes the projected result's record, and ecosys.reporting.serialize_run_provenance gives a JSON-compatible manifest.

Report selectors take a completed SimulationResult and explicit target dates and labels. exact is the default and requires an existing support node; at_or_after, nearest, and vba_activity are named alternatives. Nearest ties select the earlier point. In vba_activity mode, label 6Monate selects at or before its target, anniversary labels ending in Jahr or Jahre select at or after, and other labels use nearest. Selection returns requested and selected time metadata and never invokes the engine, changes integration support, or integrates dose. SimulationResult.time_grid_kind and SimulationResult.output_start_date identify the support convention and absolute origin. The support-grid policy and its open numerical-method questions are recorded in scientific-decisions.md (SD-18); the design history is in development-history.md (ยง2).

Shapes

Leading dimensions are batch or spatial dimensions. Semantic axes are trailing: time, cohorts, plants, animals, foods, and pathways. Validity masks retain only the leading batch shape and broadcast separately over semantic axes.

Outputs

The public result tree is typed and immutable. Every trajectory carries explicit time metadata and canonical entity IDs, and validates its unit and exact trailing shape. Records include:

  • SingleEventConcentrations: one event's deposition, soil, resuspension, plants, materials, and animal products on event-relative time;
  • MaterialConcentration (batch + time + material) and AnimalProductConcentration (batch + time + animal_product);
  • SingleEventPathwayDose (batch + time + cohort + pathway);
  • TotalPerCapitaDose (batch + time + cohort) and PopulationDose (per-capita plus batch + time collective);
  • AlignedEventContribution, which preserves per-event detail with event IDs and dates after alignment to absolute output dates;
  • SimulationResult, the complete tree returned by EcosysEngine.run(): superposed plants, materials, and animal_products, per-event contributions, TotalPerCapitaDose (batch + time + cohort), and PopulationDose (per-capita plus batch + time collective), plus the time_grid_kind and absolute output_start_date metadata.
  • SimulationResult.event_results retains one complete unaligned result tree per event; event_contributions contains the corresponding aligned dose trajectories.

EcosysEngine.run() returns the complete SimulationResult tree: every event is run independently on the shared absolute support, superposed, and aggregated against canonical population counts. Ingestion and the supported exposure pathways (cloud_inhalation, resuspension_inhalation, ground_external, and opt-in cloud_external) are available through compute_complete_single_event for single-event detail. Standalone kernel results use Bq/m2, Bq/m3, Bq/kg, or the engine's Sv unit as appropriate. Interval and cumulative dose are distinct fields. Per-capita dose uses the package-defined Sv unit (DOSE_UNIT in ecosys.domain.units). To obtain numeric mSv values, use .to_value(DOSE_UNIT) * 1000; Astropy does not supply a built-in u.mSv. Collective dose is interpreted as person-Sv, with population counts stored as dimensionless quantities. Cumulative dose is the sum of interval doses through its support node. A one-year report selection is a selected interval or cumulative value at that support node, not an annualized dose rate.

Errors

Invalid units, shapes, negative physical inputs, unknown canonical IDs, and unsupported scientific pathways raise explicit errors. The effective-dose skin pathway remains deferred; skin-tissue dose has a separate API.

GIS Adapter Contract

The engine accepts GIS-prepared arrays but does not import or perform GIS I/O. An adapter outside ecosys is responsible for providing:

  • Canonical plant, soil-type, and environment ID arrays with exact string IDs.
  • NumPy arrays whose leading dimensions are spatial batch axes.
  • Astropy quantities on every physical array, including deposition, rates, masses, concentrations, and durations.
  • Boolean validity masks separate from values. A valid zero is not invalid data.
  • Chunk slices only over leading batch axes. Time, cohort, plant, animal, and pathway axes remain trailing semantic axes.
  • Coordinate metadata that identifies the leading batch shape and maps each cell to external GIS coordinates.

Adapters must preserve array shape and unit metadata when concatenating chunks. They must not translate IDs by aliases, substring matching, or integer fallback. Use EcosysEngine.iter_chunks to stream simulation results over flattened leading batch dimensions. The separate ecosys.batching.execute_in_chunks helper splits a quantity array's first axis and concatenates its outputs. The adapter remains responsible for coordinate bookkeeping and GIS formats; see chunked execution.