Skip to main content

sdc-gdr2fhir

Governed Data Records as HL7 FHIR R4 Bundles. A target mapper for sdc-mapper: the core validates the record, resolves every value against its model and reports each one; this package says which FHIR resource and element each value goes in and writes the Bundle. Outbound only. Apache 2.0.

Status: 4.0.0 in development. Models so far, from the FAIR Data Demo:

Model ct_id Resources Rules
NHANES Participant xy8upneajsb8vdcmnve01g6g Patient, Observation, QuestionnaireResponse 112
NHANES Medication epbdfmvxc3gbh5f66hhb3o2m Patient, MedicationStatement, QuestionnaireResponse 18

Use

from sdc_mapper import Engine, load_mapping
from sdc_gdr2fhir import FHIRMapper, mapping_path

result = Engine().map_record(xml, FHIRMapper(), load_mapping(mapping_path("xy8upneajsb8vdcmnve01g6g")))
result.files["Bundle.json"]     # a FHIR R4 Bundle of type collection
result.report                   # every value: lookup, declared or not representable; every Exceptional Value

Through sdc-mapper's CLI and MCP server the mapper is the target fhir.

The target

HL7 FHIR Release 4 (4.0.1), JSON. The specification is © HL7 and licensed under Creative Commons "No Rights Reserved" (CC0); its terms allow redistribution and implementation-related products, so long as no one claims HL7's endorsement and no altered specification is published as FHIR. HL7® and FHIR® are HL7's trademarks. This package carries the FHIR R4 JSON schema unmodified (see NOTICE) and ships no terminology: LOINC, SNOMED CT, ICD-10-CM and NCI Thesaurus codes appear only as the models bind them and the records carry them.

Every Bundle this package writes is valid against the FHIR R4 JSON schema, resource by resource and as a Bundle, or is not written. The schema checks structure, types, required members and code patterns; it does not check FHIR's invariants or terminology bindings. tests/ runs the HL7 FHIR validator (validator_cli.jar) too, where Java and the validator are installed (FHIR_VALIDATOR_JAR); it has not been run for this version.

Where values go

Each record is one Bundle of type collection, identified by the record's instance id (https://semanticdatacharter.com/ns/sdc4/instance). Entry ids and urn:uuid fullUrls are derived from the instance id, so the same record gives the same bytes.

  • Patient: the respondent sequence number as an identifier, and the administrative gender.
  • Observation: each blood pressure reading (the vital signs blood pressure panel, LOINC 85354-9, with systolic and diastolic as components, body site and status), the heart rate and each laboratory result, with the LOINC code the model binds and UCUM units; smoking status, with the model's LOINC code and the answer's LOINC answer code; each chronic condition indicator, with the SNOMED CT concept the model names as its subject and the Yes or No answer's LOINC answer code. A condition indicator is the answer to "has a doctor ever told you", so it is an Observation of the answer, not a Condition.
  • MedicationStatement: the NHANES generic drug code and name, the ICD-10-CM reasons, and the status from "taken in the past month" (Yes is active, No not-taken).
  • QuestionnaireResponse: every other survey answer, an item each, linkId the component's identifier and text its label; a Coding where the model binds each of the answer's values to its own code, else the answer as recorded.

Lookup or declared. Where the model binds the code FHIR needs (a laboratory result's LOINC code, a condition's SNOMED CT subject, an answer's LOINC answer code, an administrative gender, an observation status), the code written is the model's own and the value is a lookup; tools/build_mapping.py copies those bindings from the model into the mapping file, and the mapper checks at run time that the code it writes is one the model binds. Which resource and element a value goes in is declared, one mapping file per model.

For the 200 sample records of each model:

Model lookup declared not representable
NHANES Participant 9,093 (65.8% of the data values) 4,733 5,400 (provenance and audit)
NHANES Medication 0 1,591 (100% of the data values) 5,400 (provenance and audit)

The medication model binds its ICD-10-CM and drug code components to their code systems, not each value to a code, so its codes are written as the record holds them: declared.

Exceptional Values: every one preserved

FHIR is the target that can say what an Exceptional Value says. Where the data-absent-reason code system (http://terminology.hl7.org/CodeSystem/data-absent-reason) has the concept, an Observation's (or component's) value is replaced by dataAbsentReason, and any other element carries the data-absent-reason extension. The null flavors data-absent-reason has no concept for are written exactly from v3 NullFlavor (http://terminology.hl7.org/CodeSystem/v3-NullFlavor), as the iso21090-nullFlavor extension on the element or a v3 NullFlavor coding of dataAbsentReason (whose binding is extensible). v3 NullFlavor has no Asked and Refused; data-absent-reason does.

ISO 21090 Written as Class
UNK data-absent-reason unknown preserved
ASKU data-absent-reason asked-unknown preserved
NAV data-absent-reason temp-unknown preserved
NASK data-absent-reason not-asked preserved
ASKR data-absent-reason asked-declined preserved
MSK data-absent-reason masked preserved
NA data-absent-reason not-applicable preserved
NINF data-absent-reason negative-infinity preserved
PINF data-absent-reason positive-infinity preserved
NI, INV, DER, OTH, UNC, QS, TRC v3 NullFlavor, the same code preserved

A mapping file cannot change this table.

What FHIR cannot hold here

  • The record's provenance and audit. FHIR's Provenance and AuditEvent require a recorded instant with a time zone, and the FAIR Data Demo records' times carry none; the PROV and audit values are reported as not representable, with that reason.
  • Times without a time zone. FHIR's dateTime requires a time zone with a time; an observation's date and time is written as its date.
  • Validity windows and recording times (act, vtb, vte, tr), and the definitions each component is bound to beyond the codes written.

Tests

pip install -e ".[dev]"
python -m pytest

Every sample record is mapped and each resource validated against the FHIR R4 JSON schema; Bundles are byte-stable; lookups, Exceptional Values and refused mappings are exercised.

Metadata

Release files for sdc-gdr2fhir 4.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sdc-gdr2fhir 4.0.0
File Size Uploaded Provenance
sdc_gdr2fhir-4.0.0.tar.gz 319.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sdc-gdr2fhir 4.0.0
File Interpreter ABI Platform
sdc_gdr2fhir-4.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 641.2 kB

Release files / sdc_gdr2fhir-4.0.0.tar.gz

Download URL sdc_gdr2fhir-4.0.0.tar.gz
Size 319.0 kB
Tags Source
SHA-256 checksum
How to use checksums
c84d113a647e622a0721c611ac48f787b15c1ab32e494e351e2cbd399b8c5074
BLAKE2b-256 checksum
How to use checksums
92edd8f436544f627d008375ea8e384e903bc3e017ffb1e2bdb4af8b5f2eaade
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Release files / sdc_gdr2fhir-4.0.0-py3-none-any.whl

Download URL sdc_gdr2fhir-4.0.0-py3-none-any.whl
Size 322.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f078551b5c10a57bd3ebc4d02b6231c365aad6460a7e1886c08bae59b2e92309
BLAKE2b-256 checksum
How to use checksums
d214fafd18d233618510187628ecd755c14c0e39ed2dc49454d79450e7fcccf6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

Security for sdc-gdr2fhir 4.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for sdc_gdr2fhir-4.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page