Skip to content

Ingest obs4REF under its own source type - #898

Open
lewisjared wants to merge 10 commits into
mainfrom
cmip7-fetch
Open

Ingest obs4REF under its own source type#898
lewisjared wants to merge 10 commits into
mainfrom
cmip7-fetch

Conversation

@lewisjared

@lewisjared lewisjared commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Ingests the obs4REF collection under its own obs4ref source type instead of folding it into obs4MIPs at ingest time. The catalog now records which datasets came from the registry and which from the ESGF archive.

The diagnostics are unchanged and still declare obs4MIPs requirements. The solver folds the obs4REF catalog into the obs4MIPs one just before matching, so a dataset held by both is taken from obs4MIPs and obs4REF fills in the rest. Publishing a dataset to obs4MIPs therefore takes over from the registry copy with no change to the REF.

Worth a close look:

  • obs_dataset_key decides when two rows are the same dataset by stripping the collection prefix and the version off the instance_id. That is the whole basis of the tie break.
  • The parser no longer rejects or warns on a mismatched activity_id. obs4REF republishes obs4MIPs files unchanged, so the file attribute cannot tell the collections apart. The adapter now sets activity_id from the source type and only warns when the paths look misfiled.
  • check_unsolvable_diagnostics runs the solver from ref doctor, which is a heavier check than the others in that module.

Data ingested with --source-type obs4mips in earlier releases still solves. ref doctor flags it under misfiled-obs4ref and recommends a re-ingest, and superseded-obs4ref lists registry copies that obs4MIPs has since published.

Summary by CodeRabbit

  • New Features

    • Added dedicated obs4REF ingestion, keeping obs4REF and obs4MIPs datasets distinct.
    • obs4REF data can fill gaps when solving obs4MIPs requirements, while obs4MIPs copies take precedence.
    • Added three ref doctor checks for misfiled, superseded, and unsolvable data.
    • Added support for generating obs4REF catalogues.
  • Bug Fixes

    • Corrected observation dataset identifiers and source types across supported diagnostics and examples.
  • Documentation

    • Updated setup, ingestion, deployment, and troubleshooting guidance for obs4REF workflows.

The obs4REF collection was ingested as obs4MIPs, so the catalog could not show
which datasets came from the registry and which from the archive.

Ingests it as obs4ref instead. The solver folds the obs4REF catalog into the
obs4MIPs one before matching, so diagnostics keep asking for obs4MIPs and a
dataset held by both is taken from obs4MIPs.
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 9e0b4e47-12d2-46c6-aff8-079b78850ccb

📥 Commits

Reviewing files that changed from the base of the PR and between 33fdce3 and 4a79440.

📒 Files selected for processing (5)
  • changelog/898.feature.md
  • docs/getting-started/02-download-datasets.md
  • docs/getting-started/03-ingest.md
  • packages/climate-ref/src/climate_ref/doctor/checks/data.py
  • packages/climate-ref/src/climate_ref/solver.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/getting-started/03-ingest.md
  • changelog/898.feature.md
  • packages/climate-ref/src/climate_ref/doctor/checks/data.py
  • packages/climate-ref/src/climate_ref/solver.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change adds a dedicated obs4ref source type, separates obs4REF catalogues, adds obs4REF fallback for obs4MIPs requirements, and adds three ref doctor checks. Documentation, diagnostic requests, catalogue identifiers, and regression fixtures now use obs4REF identifiers.

Changes

obs4REF source support

Layer / File(s) Summary
Separate obs4REF ingestion
packages/climate-ref/src/climate_ref/datasets/..., packages/climate-ref/src/climate_ref/conftest_plugin.py, packages/climate-ref/conftest.py
The adapters, fixtures, seeded databases, and catalogue generator now distinguish obs4REF from obs4MIPs.
obs4REF solver fallback
packages/climate-ref/src/climate_ref/solver.py, packages/climate-ref/tests/unit/test_solver.py
The solver adds missing obs4REF datasets to the obs4MIPs catalogue by shared dataset keys. Existing obs4MIPs rows remain authoritative.
Doctor diagnostics
packages/climate-ref/src/climate_ref/doctor/..., packages/climate-ref/tests/unit/test_doctor.py
ref doctor recognises obs4REF data for obs4MIPs requirements and adds checks for misfiled data, superseded datasets, and unsolvable diagnostics.
Source-type migration
docs/..., packages/climate-ref-example/..., packages/climate-ref-ilamb/..., packages/climate-ref-pmp/..., changelog/898.feature.md
Commands, registry requests, catalogue identifiers, and regression fixtures now use obs4ref and obs4REF.

Sequence Diagram(s)

sequenceDiagram
  participant Ingest
  participant Catalogues
  participant Solver
  participant Doctor
  Ingest->>Catalogues: register obs4MIPs and obs4REF datasets
  Solver->>Catalogues: merge missing obs4REF datasets into obs4MIPs requirements
  Catalogues-->>Solver: provide source datasets for solving
  Doctor->>Solver: evaluate diagnostics against ingested catalogues
  Solver-->>Doctor: return executions or unsolvable requirements
Loading

Merge Risk: 🟡 Moderate · up to 4a794

This change separates obs4REF data from obs4MIPs, but several updated catalog fixtures still contain stale integrity hashes, so required catalog checks will fail until the metadata and baseline manifests are regenerated or the failure is explicitly accepted.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description gives a detailed and relevant summary of the implementation and compatibility behaviour, but it omits the required Checklist section and confirmations for tests, documentation, and the… Add the required Checklist section and confirm whether tests were added, documentation was added where applicable, and a changelog item was added to changelog/. Include checked items such as - [x] where applicable.
Docstring Coverage ⚠️ Warning Docstring coverage is 43.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 78 functions across 21 files. (3 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: ingesting obs4REF under its own source type.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description gives a detailed and relevant summary of the implementation and compatibility behaviour, but it omits the required Checklist section and confirmations for tests, documentation, and the changelog.

Full details: Docstring Coverage

Explanation

Docstring coverage is 43.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 78 functions across 21 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cmip7-fetch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.92035% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../climate-ref/src/climate_ref/doctor/checks/data.py 90.62% 3 Missing and 3 partials ⚠️
...ages/climate-ref/src/climate_ref/doctor/context.py 66.66% 1 Missing and 1 partial ⚠️
Flag Coverage Δ
core 93.67% <92.92%> (-0.11%) ⬇️
providers 87.70% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...te-ref-core/src/climate_ref_core/reference_data.py 93.51% <ø> (ø)
...s/climate-ref-core/src/climate_ref_core/summary.py 98.80% <100.00%> (ø)
...ple/src/climate_ref_example/surface_temperature.py 100.00% <ø> (ø)
...limate-ref-ilamb/src/climate_ref_ilamb/standard.py 88.02% <ø> (ø)
...te-ref-pmp/src/climate_ref_pmp/diagnostics/enso.py 79.26% <ø> (ø)
...c/climate_ref_pmp/diagnostics/variability_modes.py 89.28% <ø> (ø)
...s/climate-ref/src/climate_ref/datasets/obs4mips.py 87.77% <100.00%> (-12.23%) ⬇️
packages/climate-ref/src/climate_ref/solver.py 99.05% <100.00%> (+0.08%) ⬆️
...ages/climate-ref/src/climate_ref/doctor/context.py 95.23% <66.66%> (-4.77%) ⬇️
.../climate-ref/src/climate_ref/doctor/checks/data.py 93.54% <90.62%> (-4.28%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…naliseable

The misfiled check flagged any dataset an obs4REF registry carries, so a
CERES-EBAF, GPCP, HadISST or TropFlux copy correctly fetched from ESGF was
reported as needing a re-ingest. It now looks only at the directory layout the
registry actually produces.

The merged obs4MIPs catalog dropped its adapter and database, so an
unfinalised dataset could no longer be finalised. It now carries them through,
and ref doctor solves against the same catalogs the solver would use.
Shares one helper for unwrapping a catalog, hoists the solver imports in the
doctor checks now that there is no cycle to dodge, and merges the catalogs once
per unsolvable-diagnostics run rather than once per diagnostic explained.
Also promotes normalize_requirement_sets, which the doctor checks now use.
Carrying the obs4MIPs adapter through the merge made the catalog reloadable,
and a reload would go back to that adapter alone and drop every obs4REF row
just merged in. The merge now carries no adapter, so it cannot reload.
@lewisjared
lewisjared marked this pull request as ready for review September 2, 2026 07:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: c9b4051d-2e9f-4628-b415-2d9956b54af1

📥 Commits

Reviewing files that changed from the base of the PR and between 5ccd511 and 4c495b7.

⛔ Files ignored due to path filters (2)
  • tests/test-data/esgf-catalog/obs4mips_catalog.parquet is excluded by !**/*.parquet
  • tests/test-data/esgf-catalog/obs4ref_catalog.parquet is excluded by !**/*.parquet
📒 Files selected for processing (66)
  • changelog/898.feature.md
  • docs/development.md
  • docs/getting-started/02-download-datasets.md
  • docs/getting-started/03-ingest.md
  • docs/getting-started/quickstart.md
  • docs/how-to-guides/diagnose-a-deployment.md
  • docs/how-to-guides/docker_deployment.md
  • packages/climate-ref-core/src/climate_ref_core/reference_data.py
  • packages/climate-ref-core/src/climate_ref_core/summary.py
  • packages/climate-ref-core/tests/unit/test_datasets.py
  • packages/climate-ref-core/tests/unit/test_datasets/dataset_collection_obs4mips_hash.yml
  • packages/climate-ref-core/tests/unit/test_reference_data.py
  • packages/climate-ref-core/tests/unit/test_summary.py
  • packages/climate-ref-example/src/climate_ref_example/surface_temperature.py
  • packages/climate-ref-example/tests/test-data/global-sst-bias/cmip7/catalog.yaml
  • packages/climate-ref-example/tests/test-data/global-sst-bias/default/catalog.yaml
  • packages/climate-ref-ilamb/src/climate_ref_ilamb/standard.py
  • packages/climate-ref-ilamb/tests/test-data/burntfractionall-gfed/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/burntfractionall-gfed/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/csoil-hwsd2/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/csoil-hwsd2/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/gpp-wecann/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/gpp-wecann/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/mrro-lora/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/mrro-lora/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/nbp-hoffman/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/nbp-hoffman/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/snc-esacci/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/snc-esacci/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/so-woa2023-surface/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/so-woa2023-surface/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/thetao-woa2023-surface/cmip6/catalog.yaml
  • packages/climate-ref-ilamb/tests/test-data/thetao-woa2023-surface/cmip7/catalog.yaml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_amoc_rapid_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_burntfractionall_gfed_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_csoil_hwsd2_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_gpp_wecann_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_mrro_lora_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_nbp_hoffman_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_snc_esacci_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_so_woa2023_surface_.yml
  • packages/climate-ref-ilamb/tests/unit/test_solve_regression/test_solve_regression_thetao_woa2023_surface_.yml
  • packages/climate-ref-pmp/conftest.py
  • packages/climate-ref-pmp/src/climate_ref_pmp/diagnostics/enso.py
  • packages/climate-ref-pmp/src/climate_ref_pmp/diagnostics/variability_modes.py
  • packages/climate-ref-pmp/tests/test-data/enso_proc/cmip6/catalog.yaml
  • packages/climate-ref-pmp/tests/test-data/enso_proc/cmip7/catalog.yaml
  • packages/climate-ref-pmp/tests/test-data/enso_tel/cmip6/catalog.yaml
  • packages/climate-ref-pmp/tests/test-data/enso_tel/cmip7/catalog.yaml
  • packages/climate-ref-pmp/tests/test-data/extratropical-modes-of-variability-npgo/cmip6/catalog.yaml
  • packages/climate-ref-pmp/tests/test-data/extratropical-modes-of-variability-npgo/cmip7/catalog.yaml
  • packages/climate-ref-pmp/tests/test-data/extratropical-modes-of-variability-pdo/cmip6/catalog.yaml
  • packages/climate-ref-pmp/tests/test-data/extratropical-modes-of-variability-pdo/cmip7/catalog.yaml
  • packages/climate-ref/conftest.py
  • packages/climate-ref/src/climate_ref/conftest_plugin.py
  • packages/climate-ref/src/climate_ref/datasets/obs4mips.py
  • packages/climate-ref/src/climate_ref/doctor/checks/data.py
  • packages/climate-ref/src/climate_ref/doctor/context.py
  • packages/climate-ref/src/climate_ref/solver.py
  • packages/climate-ref/tests/unit/datasets/test_obs4mips/obs4mips_catalog_db.yml
  • packages/climate-ref/tests/unit/datasets/test_obs4ref.py
  • packages/climate-ref/tests/unit/test_doctor.py
  • packages/climate-ref/tests/unit/test_doctor_registry.py
  • packages/climate-ref/tests/unit/test_solver.py
  • packages/climate-ref/tests/unit/test_solver/test_solve_metrics.yml
  • scripts/generate_esgf_catalog.py
💤 Files with no reviewable changes (1)
  • packages/climate-ref/tests/unit/datasets/test_obs4mips/obs4mips_catalog_db.yml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread packages/climate-ref/src/climate_ref/conftest_plugin.py
Comment thread packages/climate-ref/src/climate_ref/datasets/obs4mips.py Outdated
Comment thread packages/climate-ref/src/climate_ref/doctor/checks/data.py
Tested against a real deployment on Gus, where 81 datasets are affected. One
finding listing all of them wrapped into an unreadable blob, and the remedy
told the reader to retract 'each of the rows above'. Findings sharing a remedy
are already grouped under it once, so one per dataset reads as a list.
Tested against a real deployment on Gus. pmp/enso_tel groups its reference
requirement by activity_id, and the adapter now stamps that from the source
type, so the reference data split into an obs4MIPs group and an obs4REF group
and every model solved twice against half its references. 892 extra executions
across the deployment.

The merged rows stand in for obs4MIPs data, so they now carry that activity_id.
Their instance_id still names obs4REF, so the provenance is not lost.

Also catches the ValueError a diagnostic with no data requirements raises, and
adds obs4REF to the aggregate test fixture so it can exercise the fallback.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 4c4844fb-e7f0-4f4e-b471-c1fd67a6d810

📥 Commits

Reviewing files that changed from the base of the PR and between 4c495b7 and 74ec7c1.

📒 Files selected for processing (5)
  • packages/climate-ref/src/climate_ref/conftest_plugin.py
  • packages/climate-ref/src/climate_ref/doctor/checks/data.py
  • packages/climate-ref/src/climate_ref/solver.py
  • packages/climate-ref/tests/unit/test_doctor.py
  • packages/climate-ref/tests/unit/test_solver.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/climate-ref/src/climate_ref/conftest_plugin.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread packages/climate-ref/src/climate_ref/solver.py Outdated
…alog

A deployment that fetched only the obs4REF registry is the ordinary case, and
it took the branch that returned the obs4REF catalog untouched. Those rows kept
an obs4REF activity_id, so a requirement grouping by it split or rejected them.
Normalisation now happens on the one path every added row takes.

Also normalises path separators before matching a collection directory.
@lewisjared

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Mid-upgrade the re-ingested obs4REF row and the old misfiled obs4mips row sit
side by side, and every one was reported as superseded. That told the user to
retract exactly the row misfiled-obs4ref asks them to keep. Only a genuine
obs4MIPs publication counts as one now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant