Bits & Flames bitsandflames/fyron

FHIR Builder

fyron.fhir.builder creates FHIR JSON resources and bundles from explicit Python inputs. It is for clinical data science workflows where extracted observations, conditions, imaging measurements, generated summaries, model endpoints, and provenance need to become inspectable FHIR JSON.

Fyron uses plain dictionaries instead of generated model classes. That keeps resources easy to print, diff, validate, write to disk, and post through FHIRRestClient.

If your extracted findings already live in a reviewed CSV or DataFrame, use FHIR Mapping on top of these builders.

Choose Your Builder Path

Single Resource

Build one `Observation`, `Condition`, `DocumentReference`, or `DiagnosticReport` for a small write-back task.

LLM Evidence

Package extracted facts with the source report, model endpoint, generated summary, and `Provenance`.

Imaging Measurements

Write BOA, radiomics, or model-derived measurements linked to a study and series UID.

Server Upload

Use `transaction` bundles when submitting to a FHIR server; use `collection` bundles for local review.

Version Policy

FHIR R4 is the default and stable target:

python
version = "R4"

FHIR R6 can be selected with version="R6", but Fyron marks the output as experimental. Use R6 only for prototypes or when your implementation guide explicitly expects it.

Fyron validates structure, required fields for the resources it builds, transaction metadata, and local references. It does not replace your server validator, the official HL7 validator, or implementation-guide profile validation.

Imports

python
from fyron.fhir.builder import (
    build_bundle,
    build_condition,
    build_document_reference,
    build_imaging_measurement_bundle,
    build_llm_extraction_bundle,
    build_observation,
    build_observation_component,
    codeable_concept,
    loinc,
    icd10,
    summarize_fhir_bundle,
    validate_fhir_bundle,
    validate_fhir_references,
    write_fhir_json,
)

Resource Anatomy

FHIR partWhy it matters in Fyron workflows
subjectUsually the patient reference, for example Patient/123.
codeThe clinical meaning of the resource. Prefer LOINC, SNOMED CT, ICD-10, DICOM, or a local code system.
value[x]Observation value, such as valueQuantity, valueString, valueBoolean, or valueCodeableConcept.
componentMulti-part observations, for example systolic and diastolic blood pressure.
derivedFromEvidence link from an extracted observation to a source document or imaging study.
evidence.detailEvidence link from a condition to a source report.
resultDiagnosticReport references to grouped observations.
Provenance.targetResources generated by a model, extractor, or analysis workflow.

Minimal Observation

python
from fyron.fhir.builder import build_bundle, build_observation, loinc, summarize_fhir_bundle, write_fhir_json

observation = build_observation(
    subject="Patient/123",
    code=loinc("33747-0", "Status"),
    value="no evidence of progression",
    value_type="string",
    observation_id="obs-status-001",
)

bundle = build_bundle([observation], bundle_type="collection")
summary = summarize_fhir_bundle(bundle)
write_fhir_json(bundle, "outputs/fhir/evidence_bundle.json")

Generated shape:

json
{
  "resourceType": "Observation",
  "id": "obs-status-001",
  "status": "final",
  "subject": {"reference": "Patient/123"},
  "code": {"coding": [{"code": "33747-0", "system": "http://loinc.org", "display": "Status"}]},
  "valueString": "no evidence of progression"
}

Multi-Component Observation

Use components for values that belong together clinically.

python
from fyron.fhir.builder import build_observation, build_observation_component, loinc

blood_pressure = build_observation(
    subject="Patient/123",
    code=loinc("85354-9", "Blood pressure panel"),
    components=[
        build_observation_component(code=loinc("8480-6", "Systolic blood pressure"), value=124, unit="mm[Hg]"),
        build_observation_component(code=loinc("8462-4", "Diastolic blood pressure"), value=77, unit="mm[Hg]"),
    ],
)

If a value was expected but unavailable, use data_absent_reason instead of inventing a placeholder.

python
missing_marker = build_observation(
    subject="Patient/123",
    code="PD-L1 tumor proportion score",
    data_absent_reason="not measured",
)

LLM Extracted Evidence

This pattern keeps a model-extracted result auditable: the source report is a DocumentReference, extracted observations use derivedFrom, extracted conditions use evidence.detail, the generated summary is a DiagnosticReport, and Provenance links everything to the model.

python
from fyron.fhir.builder import build_condition, build_llm_extraction_bundle, build_observation, icd10, loinc

hemoglobin = build_observation(
    subject="Patient/123",
    code=loinc("718-7", "Hemoglobin"),
    value=13.4,
    unit="g/dL",
    observation_id="hgb-001",
)

condition = build_condition(
    subject="Patient/123",
    code={"coding": [icd10("C34", "Malignant neoplasm of bronchus and lung")]},
    condition_id="condition-lung-cancer",
)

bundle = build_llm_extraction_bundle(
    subject="Patient/123",
    source_report_url="https://reports.example.org/report-001.pdf",
    observations=[hemoglobin],
    conditions=[condition],
    summary_text="LLM-generated summary for clinical review.",
    model_name="Fyron LLM extractor",
    model_endpoint_url="https://models.example.org/fyron/extract",
    model_version="2026.06",
    prompt_version="report-extraction-v1",
    id_prefix="report-001",
    bundle_type="collection",
)

Imaging Measurements

Use this pattern for quantitative values derived from an imaging study and a specific series.

python
from fyron.fhir.builder import build_imaging_measurement_bundle, codeable_concept

bundle = build_imaging_measurement_bundle(
    subject="Patient/123",
    study_instance_uid="1.2.840.113619.2.55.3.604688654.123",
    series_instance_uid="1.2.840.113619.2.55.3.604688654.123.4",
    series_description="CT abdomen portal venous",
    measurements=[
        {
            "id": "l3-sma",
            "code": codeable_concept(text="L3 skeletal muscle area"),
            "value": 123.4,
            "unit": "cm2",
            "body_site": codeable_concept(text="L3"),
            "method": codeable_concept(text="BOA/Fyron segmentation workflow"),
        },
        {
            "id": "vat-volume",
            "code": codeable_concept(text="Visceral adipose tissue volume"),
            "value": 820.5,
            "unit": "ml",
            "body_site": codeable_concept(text="Abdomen"),
        },
        {
            "id": "vat-sat-ratio",
            "code": codeable_concept(text="VAT/SAT ratio"),
            "value": 0.74,
            "unit": "ratio",
        },
    ],
    model_name="Fyron imaging measurement model",
    model_endpoint_url="https://models.example.org/fyron/imaging",
    id_prefix="study-001",
    bundle_type="collection",
)

The resulting observations point back to the ImagingStudy, include a series UID extension, and are grouped by a DiagnosticReport.

Bundle Anatomy

Bundle typeUseEntry request
collectionLocal evidence package, review artifact, JSON export.No entry.request.
transactionServer write-back through the FHIR base URL.Adds entry.request.method and entry.request.url.
python
transaction = build_bundle(
    [entry["resource"] for entry in bundle["entry"]],
    bundle_type="transaction",
    transaction_method="PUT",
)

Use transaction_method="POST" for server-assigned IDs. Use transaction_method="PUT" when resources already have stable IDs. Conditional create is available for POST:

python
transaction = build_bundle(
    [observation],
    bundle_type="transaction",
    if_none_exist={"Observation": "identifier=obs-status-001"},
)

Inspect Before Writing

python
from fyron.fhir.builder import summarize_fhir_bundle, validate_fhir_bundle, validate_fhir_references

reference_report = validate_fhir_references(bundle)
summary = summarize_fhir_bundle(bundle)
validate_fhir_bundle(bundle)

print(reference_report["valid"])
print(summary["resource_types"])

summarize_fhir_bundle() returns entry counts, resource-type counts, transaction methods, version tags, and local-reference status.

Posting To A FHIR Server

FHIRRestClient can post individual resources or transaction bundles using the same authenticated session as REST extraction.

python
from fyron import FHIRRestClient
from fyron.fhir.builder import build_bundle

client = FHIRRestClient("https://fhir.example.org/fhir")

transaction = build_bundle(
    [entry["resource"] for entry in bundle["entry"]],
    bundle_type="transaction",
)

result = client.submit_bundle(transaction)
print(result.status_code, result.location)

create_resource, update_resource, and submit_bundle return FHIRWriteResult objects with status code, location, resource type, resource id, and response JSON when available.

Validation Levels

LevelToolWhat it checks
Fyron structural validationvalidate_fhir_resource, validate_fhir_bundleRequired fields for Fyron-supported resources, bundle type, transaction request metadata, local references.
Server validationTarget FHIR serverCapability statement, resource acceptance, server-side profiles, authorization.
Profile validationHL7 validator or implementation guide toolingFull conformance to R4/R6 profiles, terminology bindings, slicing, extensions.

Function Parameters

Resource Builders

FunctionRequired inputsOptional inputsReturns
build_observation(...)subject, codevalue, value_type, unit, components, data_absent_reason, derived_from, performer, encounter, method, body_site, interpretation, note, versionObservation dict
build_observation_component(...)codevalue, unit, value_type, data_absent_reason, interpretationObservation component dict
build_condition(...)subject, codeclinical/verification status, onset, recorded date, evidence, versionCondition dict
build_document_reference(...)subject plus attachment valuestitle, content type, date, description, type, versionDocumentReference dict
build_diagnostic_report(...)subject, coderesults, imaging study refs, conclusion, presented form, versionDiagnosticReport dict
build_imaging_study_reference(...)subject, study_instance_uidseries UID/description, modality, started, versionImagingStudy dict
build_model_device(...) / build_endpoint(...)model or endpoint identityversion, endpoint link, manufacturerDevice/Endpoint dict
build_provenance(...)targetsagent, entity, recorded, activity, prompt versionProvenance dict

Workflow Builders And Helpers

FunctionRequired inputsOptional inputsReturns
build_llm_extraction_bundle(...)subject, source report URL, model name, bundle typeobservations, conditions, summary, endpoint, model/prompt version, id_prefix, FHIR versionBundle dict
build_imaging_measurement_bundle(...)subject, study UID, measurements, bundle typeseries UID, model info, id_prefix, versionBundle dict
build_bundle(...)resources, bundle typebundle id, transaction method, conditional create, versionBundle dict
write_fhir_json(...) / read_fhir_json(...)payload/pathnonepath or payload dict
summarize_fhir_resource(...) / summarize_fhir_bundle(...)resource/bundlenonesummary dict
validate_fhir_resource(...) / validate_fhir_bundle(...)resource/bundleversionvalidated dict or raises
validate_fhir_references(...)bundlenonereference report dict

Common Pitfalls

  • Do not post collection bundles to a FHIR server as transactions.
  • Use id_prefix when packaging multiple reports or imaging studies in one workflow.
  • Do not encode missing values as fake measurements; use data_absent_reason.
  • Local references such as Observation/obs-1 must resolve inside the bundle if they point to generated resources.
  • R6 output is explicitly experimental.
  • Fyron validation is a safety check, not regulatory-grade FHIR conformance.
  • FHIR for REST queries and extraction.
  • LLM for model-assisted extraction.
  • Imaging and BOA for imaging-derived measurements.
  • Audit & Provenance for analysis manifests outside FHIR.