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
DepositionEventrequires canonical nuclide IDs, Gregorian dates, integrated air activity inBq s/m3or an equivalent unit, wet deposition inBq/m2, and rainfall inmm.- When the source is a constant air concentration over a known exposure period,
construct the event with
DepositionEvent.from_constant_air_concentration(...). Theair_concentrationmust carryBq/m3andexposure_durationmust carry time units; the result stores their product inBq s/m3. For example,300 * u.Bq / u.m**3over1 * u.dayis equivalent to an integrated input of7200 * u.Bq * u.hour / u.m**3, not300 * u.Bq * u.hour / u.m**3. PopulationCohortsrequires 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_ageis the age atoutput_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 canonicaltime_activityenvironment distribution; an explicit override must be a dimensionless quantity of shapebatch + cohort + environmentwith exact canonicalenvironment_idsthat sums to one over the environment axis.SimulationRequest.elapsed_timesis a strictly increasing one-dimensional duration axis in equivalent Astropy time units measured from the explicit Gregorianoutput_start_date, which is required and never inferred from event dates. Fractional-day instants are preserved inrequest.output_datetimes; theoutput_datesproperty gives their containing Gregorian calendar dates. Each event's signedevent_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_idsoptionally selects exposure pathways. Ingestion is always included.cloud_externalis an opt-in cloud-submersion impulse in the effective-dose total. Requestingskinas an effective-dose pathway still raises an unsupported-pathway error.EcosysEngine.skin_tissue_dose(request)returns oneSingleEventPathwayDoseper event, with pathway IDskin_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) andAnimalProductConcentration(batch + time + animal_product);SingleEventPathwayDose(batch + time + cohort + pathway);TotalPerCapitaDose(batch + time + cohort) andPopulationDose(per-capita plusbatch + timecollective);AlignedEventContribution, which preserves per-event detail with event IDs and dates after alignment to absolute output dates;SimulationResult, the complete tree returned byEcosysEngine.run(): superposedplants,materials, andanimal_products, per-event contributions,TotalPerCapitaDose(batch + time + cohort), andPopulationDose(per-capita plusbatch + timecollective), plus thetime_grid_kindand absoluteoutput_start_datemetadata.SimulationResult.event_resultsretains one complete unaligned result tree per event;event_contributionscontains 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.