Read background database timing from database metadata - #219
Merged
TimoDiepers merged 24 commits intoAug 24, 2026
Merged
Conversation
…ime-explicit `_resolve_database_dates` now raises a ValueError naming the scenario filter and the values actually declared for its keys when the filter matches no database, instead of quietly falling back to a plain (non-time-explicit) LCA. The "no representative_time metadata anywhere" log is now accurate for that case only. Reworded the three "database is not marked as dynamic" / "remove one of the two databases from database_dates" error messages to also credit representative_time metadata as a source of timing, since database_dates may never have been passed. Documented the ValueError cases in _resolve_database_dates's docstring, and added tests covering the new typo error and TimexLCAInputs.validate_scenario, which had no direct test coverage.
The tutorials taught the old, mandatory database_dates mapping. They now record each background database's representative_time once with set_database_metadata and let TimexLCA read it, matching the new default behaviour. Notebook 4 (import_model_from_excel) could not be re-executed in this environment: bw2io is not installed in .venv, unrelated to this change; its stored outputs are left as-is and its source cells are updated.
The prior update to notebooks/tutorials/4_import_model_from_excel.ipynb was round-tripped through notebook tooling that re-serialized the whole file with different indentation and no trailing newline, turning a four-cell content change into a ~2100-line diff. Restore the file to the original's formatting (4-space indent, alphabetical keys, trailing newline) while keeping only the intended edits to cells 21, 22, 23, and 27.
The eight remaining notebooks (two self-contained advanced examples plus six premise/ecoinvent notebooks) taught the old, mandatory database_dates mapping. They now rely on the representative_time metadata bw_timex reads automatically, matching the new default behaviour from Tasks 1-6. - background_temporal_distributions.ipynb and uncertainty_with_datapackages.ipynb were re-executed against their own self-contained databases. - The six premise/ecoinvent notebooks had only their source cells edited; stored outputs are unchanged except where they printed a now-obsolete database_dates dict. - The electric-vehicle notebooks now call set_database_metadata on their own "without EOL" background copies, using the same representative_time as the premise vintage they were copied from. - exercise_ev_vs_petrol_solutions.ipynb's project holds two IAM pathways, so its markdown now shows the scenario argument needed to pick one.
Make the premise_version example in database_metadata.py's docstring and background_database_metadata.md's callout self-consistent: both showed 2.4.9.1 alongside representative_time, but the callout says premise only writes that key from the version after 2.4.9.2 onwards. Bumped the example version to 2.4.9.3. Added a CHANGES.md bullet for the reworded database_dates-specific error messages and the new ValueError on a scenario filter that matches no database, which Task 5's changelog entries had missed.
A database that declares no scenario keys survives every `scenario`
filter, so the resolved mapping stayed non-empty and masked a filter
that matched none of the actual scenario databases (e.g. a typo'd
pathway value with an unrelated hand-built vintage also in the
project). Raise based on whether any surviving database positively
declares one of the filtered keys, not on whether the resolved
mapping is empty.
Also treat `database_dates={}` as an explicit (invalid) mapping
rather than falling through to metadata resolution, and hoist the
`DatabaseMetadataInputs` import in database_metadata.py to module
scope now that there's no cycle to avoid.
The quickstart cheat-sheet listed scenario before database_dates; the real signature order is (demand, method, database_dates, scenario, use_global_lci_cache). Reword the "every database with representative_time is pulled in" note: it's not only a setup-time cost, it's a results concern too, since everything in database_dates_static becomes a temporal-market interpolation candidate.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #219 +/- ##
==========================================
+ Coverage 78.51% 79.78% +1.26%
==========================================
Files 10 12 +2
Lines 2472 2642 +170
==========================================
+ Hits 1941 2108 +167
- Misses 531 534 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…books premise only writes representative_time metadata from 2.4.9.2 onwards (current release is 2.4.9.1), so notebooks claiming premise databases already know their point in time now say so and point to set_database_metadata for earlier versions.
…notebooks The scenario argument filters on the same premise >= 2.4.9.2 metadata as representative_time, so it needs the same version qualifier. Several notebooks also only mentioned set_database_metadata as the escape hatch for pre-2.4.9.2 premise, without pointing out that database_dates works as a full mapping/override too.
This was referenced Aug 22, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #217. Supersedes #218.
TimexLCAused to learn what a background database represents in one way only: thedatabase_datesmapping, hand-written at every call site. The information already exists in the database — a premise export knows the year it was built for — but it lived only in the database name, so every study re-typed it, and a typo either raised or, worse, mapped a vintage to the wrong year.premise PR #303 (on
master, released after 2.4.9.2) closes the gap on the producing side: exported databases now carry what they represent in their Brightway metadata. This PR makesbw_timexread it.What changed
Timing is read from database metadata by default. Every registered database carrying
representative_timeis mapped to its point in time. ISO strings,datetimes and"dynamic"are all accepted; databases holding the functional unit default to"dynamic".set_database_metadatarecords it for databases that don't bring it themselves:Dates are stored as ISO strings, since Brightway serializes database metadata to JSON.
TimexLCA(scenario={...})selects one scenario when a project holds several. Any metadata key works —iam_model,pathway,system_model,ecoinvent_version,premise_version, or one you set yourself. Databases that don't declare the filtered key (your foreground, a hand-built vintage) are never filtered out.A project holding several scenarios stays unambiguous —
bw_timexrefuses to guess, and names only the keys that actually differ:A filter key no database declares, and a filter that matches nothing, are errors too — never a silent non-time-explicit run.
database_datesis unchanged and exclusive. When passed, it is the whole mapping and metadata is not read at all, so existing scripts behave exactly as before — a legacy call in a project that also holds ten premise vintages must not silently pull those ten in.Multi-scenario databases (premise superstructure and scenario-array exports) are recognised and skipped: there is no single technosphere per point in time to pick. They remain usable by naming them in
database_dates.Also in here
Three user-facing error messages named
database_dateswhen the timing may now have come from metadata (validation.py,timeline_builder.py,edge_extractor.py); they now name both sources.Docs and notebooks
New page What a database represents covering the metadata, the setter, scenario selection, and
database_datesas the explicit override — including the note that metadata resolution pulls in every registered database carryingrepresentative_time, which costs setup time and lets those databases take part in temporal-market interpolation. The quickstart and walkthrough steps 1–2 teach the new default. All twelve notebooks are updated;paper_case_study.ipynbis deliberately untouched.Testing
338 passed, 0 failed.
tests/test_database_metadata.pycovers resolution, ISO/datetime/"dynamic"values,database_datesexclusivity, scenario filtering, the ambiguity and empty-filter errors, the multi-scenario skip, andset_database_metadataround-tripping throughbd.databases.flush(), plus an end-to-end check that the metadata path and thedatabase_datespath give the same score.Note for reviewers
The design and implementation plan are committed under
docs/superpowers/. One deliberate compatibility wrinkle:scenariosits at positional slot 4, ahead ofuse_global_lci_cache, soTimexLCA(demand, method, dates, False)now raises rather than disabling the cache. It fails loudly, never silently.