Provenance and Reproducibility¶
See Reproducibility for how these fit
together. agribound._cache and agribound._repro are internal modules;
their functions are documented because the cache keys and seeding define what
a run reuses.
Provenance records¶
provenance ¶
Run provenance: what was run, with which inputs, versions and resources.
:class:RunRecorder collects a JSON-serialisable record of one pipeline run
(configuration and its hash, seed, package versions, platform, device, step
timings, peak memory, engine metadata, facts and warnings). The pipeline writes
it next to the output as <output_path>.provenance.json
(:func:provenance_path) and uses :func:reuse_mismatch (the
:func:config_hash, the study-area fingerprint and the results versions of
:mod:agribound._results) to decide whether an existing output can be reused.
RunRecorder ¶
Collect provenance for one pipeline run.
Use as a context manager; the block's wall time and outcome
("success" or "failed" with the error) are recorded on exit.
While the block runs, every WARNING (or higher) logged by an
agribound logger (agribound.*, in any thread of the process) is
added to the record's warnings as well, e.g. an engine's note that
the input resolution is outside its training range. Identical messages
are kept once, and at most :data:MAX_RECORDED_WARNINGS are stored
(warnings_not_recorded counts the rest).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgriboundConfig
|
Configuration of the run. Its hash and dictionary are captured when the recorder is created, before any stage can modify it. |
required |
run_id
|
str or None
|
Run identifier; a new one from :func: |
None
|
Examples:
>>> with RunRecorder(config) as rec:
... with rec.step("composite"):
... raster = build_composite(config)
... rec.set("raster_path", raster)
>>> write_provenance(config.output_path, rec.to_dict())
Source code in agribound/provenance.py
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | |
step ¶
Time a pipeline step.
Yields the step's record (a dict) so callers can attach details.
A failing step is recorded with status="failed" and the error is
re-raised.
Source code in agribound/provenance.py
set ¶
add_warning ¶
Record a warning (a message already recorded is not added again).
Inside the with block, WARNING records of the agribound
loggers are recorded automatically, so a caller that also logs the
message does not create a duplicate.
Source code in agribound/provenance.py
record_engine_meta ¶
Merge engine metadata (gdf.attrs["engine_meta"]) into the record.
Source code in agribound/provenance.py
to_dict ¶
Return the provenance record as a JSON-serialisable dictionary.
Source code in agribound/provenance.py
to_jsonable ¶
Recursively convert value to JSON-serialisable builtins.
NumPy scalars/arrays, tuples, sets, paths, datetimes and objects with
to_dict/isoformat are converted; non-finite floats become
None; anything else becomes str(value).
Source code in agribound/provenance.py
canonical_config ¶
Return the configuration fields that define the result (see :data:HASH_EXCLUDED_FIELDS).
Source code in agribound/provenance.py
config_hash ¶
Return the SHA-1 hex digest of the canonical YAML of config.
Fields listed in :data:HASH_EXCLUDED_FIELDS (output location and format,
caching/provenance switches, credentials, request tuning and execution
resources) are excluded, so configurations that differ only in these
fields hash identically. This includes device, which can change the
polygons slightly (see :data:HASH_EXCLUDED_FIELDS).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgriboundConfig or dict
|
Configuration. |
required |
Returns:
| Type | Description |
|---|---|
str
|
40-character hexadecimal digest. |
Source code in agribound/provenance.py
provenance_path ¶
write_provenance ¶
Write record as JSON next to output_path (atomic replace).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_path
|
str or Path
|
Output vector path the record describes. |
required |
record
|
dict
|
Provenance record (converted with :func: |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Path of the written sidecar. |
Source code in agribound/provenance.py
read_provenance ¶
Read the provenance sidecar of output_path.
Returns:
| Type | Description |
|---|---|
dict or None
|
The record, or None if the sidecar is missing or not valid JSON. |
Source code in agribound/provenance.py
reuse_facts ¶
Return the facts that :func:reuse_mismatch checks besides :func:config_hash.
aoi_fingerprint is :func:agribound._cache.aoi_fingerprint: the
study-area geometry (read from the file, bbox: string or WKT), the ID
string of a GEE asset (so no Earth Engine access is needed; the asset's
features are not covered), or the local raster's resolved path, size and
modification time when there is no study area. It is left out when the
study area cannot be read (the composite stage then reports the error).
results_versions is :func:agribound._results.results_versions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgriboundConfig
|
Configuration of the run. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
|
Source code in agribound/provenance.py
reuse_mismatch ¶
Return why the output that record describes cannot be reused for config.
The output of a successful run is reused only when:
- its
config_hashequals :func:config_hashof config; - its
facts["results_versions"]equal :func:agribound._results.results_versionsof config (a missing fact or component counts as version 1, i.e. agribound <= 1.0.0), so an output of a component whose results have changed since is not reused; - its
facts["aoi_fingerprint"]equals :func:agribound._cache.aoi_fingerprintof config when the study area is a file (a file whose geometry changed at the same path is not reused) or, without a study area, for the local raster (compared by resolved path, size and modification time). Abbox:, WKT or GEE asset study area is covered by the configuration hash already.
A record without aoi_fingerprint (agribound <= 1.0.0) is accepted,
with a WARNING that the study-area file (or local raster) could not be
verified; so is a record whose fingerprint cannot be compared because
the file cannot be read now.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
dict
|
Provenance record of a successful run (:func: |
required |
config
|
AgriboundConfig
|
Configuration of the new run. |
required |
output
|
(str, Path or None)
|
The existing output, named in the warnings. |
None
|
Returns:
| Type | Description |
|---|---|
str or None
|
None when the output can be reused, else the reason as a clause
( |
Source code in agribound/provenance.py
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
Cache keys¶
_cache ¶
Content-addressed cache keys for intermediate files.
Every module that writes an intermediate artefact (composites, window
composites, embeddings, engine inputs/outputs, fine-tuning data, LULC rasters)
names it with :func:cache_path, so that runs over different study areas,
years, date ranges or compositing settings never reuse each other's files,
even when they share one cache directory.
The key is a 12-character SHA-1 prefix over :data:CACHE_SCHEMA_VERSION, a
fingerprint of the study area (:func:aoi_fingerprint), the source, year and
date range, the compositing and export settings, source-specific options and
any extra parts supplied by the caller (for example a model name).
CACHE_SCHEMA_VERSION
module-attribute
¶
Bump when radiometry or export semantics change, to invalidate old caches.
gee_asset_fingerprint ¶
Return the 12-hex fingerprint of a GEE asset ID, as used by :func:aoi_fingerprint.
The asset is not read: the fingerprint depends on the ID string only.
Source code in agribound/_cache.py
aoi_fingerprint ¶
Return a 12-hex SHA-1 fingerprint of the configured study area.
- GEE asset IDs are fingerprinted by the asset ID string (the asset is not
downloaded; :func:
gee_asset_fingerprint). Cached files therefore do not change when the asset's features change under the same ID; the local copy of the asset kept by :func:agribound.io.vector.read_config_study_areahas the same key. - Files,
"bbox:..."strings and WKT are read, reprojected to EPSG:4326, unioned, snapped to a 1e-7 degree grid, normalised, and the 2-D WKB is hashed. Results are memoised per path and modification time. - An empty study area (
source="local"without clipping) is fingerprinted by the local raster's resolved path, size and modification time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgriboundConfig
|
Configuration providing |
required |
Returns:
| Type | Description |
|---|---|
str
|
12 hexadecimal characters. |
Source code in agribound/_cache.py
cache_key ¶
Return a 12-hex cache key for config and optional extra parts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgriboundConfig
|
Pipeline configuration. |
required |
*parts
|
object
|
Additional values (model names, window labels, parameters) that
distinguish the artefact. They are hashed as |
()
|
include_temporal
|
bool
|
When False, |
True
|
Returns:
| Type | Description |
|---|---|
str
|
12 hexadecimal characters. |
Notes
Hashed fields: :data:CACHE_SCHEMA_VERSION, :func:aoi_fingerprint,
source, year and date_range (if include_temporal),
composite_method, cloud_cover_max, export_crs,
s2_cloud_mask, naip_resolution_m; cloud_score_threshold when
Cloud Score+ masking is selected; tessera_version/tessera_variant
for embedding sources; google_embedding_backend for Google embeddings;
the USGS service URL, state and year-fallback flag for USGS NAIP Plus; and
the local raster's path, size and modification time for local sources.
Source code in agribound/_cache.py
cache_path ¶
cache_path(config: Any, stem: str, suffix: str, *parts: object, include_temporal: bool = True) -> Path
Return config.get_working_dir() / f"{stem}_{key}{suffix}".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgriboundConfig
|
Pipeline configuration. |
required |
stem
|
str
|
Human-readable file name prefix (may contain sub-directories). |
required |
suffix
|
str
|
File suffix including the dot (e.g. |
required |
*parts
|
object
|
Extra key parts (see :func: |
()
|
include_temporal
|
bool
|
See :func: |
True
|
Returns:
| Type | Description |
|---|---|
Path
|
Path inside the working directory; its parent directory exists. |
Source code in agribound/_cache.py
clear_fingerprint_cache ¶
Seeding and versions¶
_repro ¶
Reproducibility helpers: seeding, seeded generators, version capture, run IDs.
seed_everything ¶
Seed Python, NumPy, torch (CPU, CUDA, MPS) and Lightning.
Also sets PYTHONHASHSEED (inherited by subprocesses; it cannot change
string hashing of the running interpreter). torch and Lightning are
seeded only if they are installed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int
|
Seed in |
required |
deterministic
|
bool
|
Also request deterministic torch kernels
( |
False
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If seed is out of range. |
Source code in agribound/_repro.py
get_rng ¶
Return a NumPy generator seeded from config.seed and salt.
The same seed and salt give the same stream in every process (the salt is
hashed with SHA-256, not Python's randomised hash).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
AgriboundConfig or int
|
Configuration (its |
required |
*salt
|
object
|
Values that separate independent streams (e.g. |
()
|
Returns:
| Type | Description |
|---|---|
Generator
|
|
Source code in agribound/_repro.py
collect_versions ¶
Return versions of Python, agribound, GDAL and known installed packages.
Package versions are read from distribution metadata, so nothing heavy is imported. Packages that are not installed are omitted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
extra
|
iterable of str
|
Additional distribution names to include. |
()
|
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Name -> version. |
Source code in agribound/_repro.py
new_run_id ¶
Return a new run ID such as "20260926T170102Z-3f2a9c" (UTC time + 6 hex).