Skip to content

Add MIABIS-on-FHIR 1.0.0 project support#327

Open
a-tuerk wants to merge 7 commits intosamply:developfrom
a-tuerk:feat/miabis-on-fhir-project
Open

Add MIABIS-on-FHIR 1.0.0 project support#327
a-tuerk wants to merge 7 commits intosamply:developfrom
a-tuerk:feat/miabis-on-fhir-project

Conversation

@a-tuerk
Copy link

@a-tuerk a-tuerk commented Feb 27, 2026

Summary

  • Adds a new miabis project backed by the MIABIS-on-FHIR 1.0.0
    Implementation Guide (hosted at https://fhir.miabis.bbmri-eric.eu/;
    canonical resource profile URLs use https://fhir.bbmri-eric.eu)
  • New project selectable via metadata.project = "miabis" in Beam tasks
  • Supports patient, diagnosis (Condition), and specimen groups with stratifiers
  • Search criteria: gender, donor_age, Custodian, diagnosis (ICD-10), sample_kind, storage_temperature, sampling_date
  • Additive change — all existing projects (bbmri, dktk, …) are unaffected

Key Differences from bbmri (de.bbmri.fhir)

Aspect bbmri miabis
Sample type CodeSystem SampleMaterialType miabis-detailed-samply-type-csSAMPLE_TYPE_WORKAROUNDS maps Sample Locator codes to MIABIS codes, both ORed into CQL
Storage temperature codes Lens canonical codes match data STORAGE_TEMPERATURE_WORKAROUNDS maps Lens codes (e.g. temperatureRoom) to MIABIS codes (e.g. RT), both ORed into CQL;
storage_temperature_uncharted intentionally unmapped
Storage temperature location Specimen.extension Specimen.processing[].extensionStorageTemperature() is a function (not a define) so Blaze evaluates it per-specimen in the stratifier
Custodian link valueReference valueIdentifier
Diagnosis ICD-10 + ICD-10-GM variants ICD-10 only (http://hl7.org/fhir/sid/icd-10)

Files Modified

  • src/projects/miabis/mod.rs — code list URIs, CQL snippets, SAMPLE_TYPE_WORKAROUNDS, STORAGE_TEMPERATURE_WORKAROUNDS, mandatory code lists
  • src/projects/miabis/template.cql — CQL template with SampleType(), StorageTemperature(), Custodian, DiagnosisCode()
  • src/projects/miabis/body.json — FHIR Measure definition
  • src/projects/mod.rs — new MiabisOnFhir enum variant wired into all getter methods; get_storage_temperature_workarounds() method; shared EMPTY_WORKAROUNDS for other projects
  • src/cql.rs — wires SAMPLE_TYPE_WORKAROUNDS and STORAGE_TEMPERATURE_WORKAROUNDS into CQL generation for ConditionType::In and ::Equals

Testing

Unit tests (cargo test test_miabis, no external services): two test functions covering the workaround mechanism — test_miabis_storage_temperature_workarounds (EQUALS with mapping, EQUALS with 1:1
mapping, IN with multiple mappings, unmapped code passthrough) and test_miabis_sample_type_workarounds (EQUALS, IN, 1:many mapping).

End-to-end test (dev/test_miabis_e2e.sh, requires Docker): self-contained script with test data in resources/test/miabis_e2e_bundle.json. Starts Blaze, loads the bundle, runs focus against a mock
Beam proxy, and verifies 14 counts in the MeasureReport. Found and fixed a real bug: StorageTemperature was a patient-level define, causing all specimens of a patient to inherit the first specimen's
temperature.

Extended E2E suite (10 scenarios, 1–25 donors, 1–5 collections, up to 59 specimens): 269 checks, 0 failures. Synthetic bundles generated via
a-tuerk/miabis_on_fhir_synth. The companion repo a-tuerk/miabis_on_fhir_bridgehead contains two
additional test scripts not part of this PR: test_miabis_branch.sh (5 targeted scenarios testing code translation and empty-AST behaviour) and run_e2e_suite.py (10 synthetic-bundle scenarios, 269 counts
verified).

Andreas Tuerk and others added 7 commits February 27, 2026 09:39
Adds a new `miabis` project backed by the MIABIS-on-FHIR 1.0.0
Implementation Guide (hosted at https://fhir.bbmri-eric.eu).

Key differences from the existing `bbmri` (de.bbmri.fhir) project:
- Sample type uses `miabis-detailed-samply-type-cs` CodeSystem
- Storage temperature is in `Specimen.processing[].extension` (not
  `Specimen.extension`)
- Custodian link is via `valueIdentifier` (not `valueReference`)
- Diagnosis uses ICD-10 only (`http://hl7.org/fhir/sid/icd-10`),
  no German ICD-10-GM variant and no SampleDiagnosis extension

Includes:
- `src/projects/miabis/mod.rs` – code lists, CQL snippets, sample type
  workarounds mapping canonical Sample Locator codes to MIABIS codes
- `src/projects/miabis/template.cql` – CQL template with SampleType,
  StorageTemperature, Custodian, DiagnosisCode functions
- `src/projects/miabis/body.json` – Measure definition with patient,
  diagnosis, and specimen groups + stratifiers
- `src/projects/mod.rs` – wires in the new `MiabisOnFhir` project
  variant (project name string: `"miabis"`)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The IG is hosted at https://fhir.miabis.bbmri-eric.eu/; the canonical
resource profile URLs (used in the code) still correctly reference
https://fhir.bbmri-eric.eu.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Five unit tests in cql::test covering the MIABIS-specific CQL fragments:
- test_miabis_empty: mandatory code systems always declared
- test_miabis_gender: patient-level snippet
- test_miabis_diagnosis: ICD-10 only (no GM variants)
- test_miabis_sample_kind: canonical code + TissueFixed workaround
- test_miabis_storage_temperature: nested Specimen.processing[].extension path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug fix: StorageTemperature was defined as a patient-level define, causing
Blaze to use the first specimen's temperature for all specimens of the same
patient in the stratifier. Changed to a function with a FHIR.Specimen
parameter (consistent with SampleType) so Blaze evaluates it per-specimen.

E2E test (dev/test_miabis_e2e.sh):
- Starts a local Blaze instance via Docker
- Loads a minimal MIABIS-on-FHIR 1.0.0 test bundle
  (resources/test/miabis_e2e_bundle.json: 2 patients, 2 conditions,
  3 specimens covering blood-plasma/tissue-ffpe/whole-blood and LN/RT)
- Sends an AST task with metadata.project = "miabis" via a mock Beam proxy
- Verifies all 14 expected counts in the returned MeasureReport

The E2E test also caught the StorageTemperature bug before this commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Lens sends canonical temperature codes (e.g. temperatureRoom, temperatureLN)
but MIABIS-on-FHIR 1.0.0 stores native codes (RT, LN, -18to-35, …).

Add STORAGE_TEMPERATURE_WORKAROUNDS in miabis/mod.rs, expose it via
Project::get_storage_temperature_workarounds(), and wire it into the CQL
generator alongside the existing sample-type workaround.

"storage_temperature_uncharted" is intentionally left unmapped; queries for it
return zero results on MIABIS nodes, which is correct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ture criteria

Previously both SAMPLE_TYPE_WORKAROUNDS and STORAGE_TEMPERATURE_WORKAROUNDS
were applied to every In/Equals criterion regardless of criterion key. Any
criterion value that coincidentally matched a workaround map key would silently
gain extra OR clauses. Guard both lookups on condition_key_trans so the maps
are only consulted for the criteria they are defined for.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, not Czech BBMRI-cz

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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