Healthy Route Implementation Guide
0.2.0 - ci-build
Healthy Route Implementation Guide, published by Savannah Informatics. This guide is not an authorized publication; it is the continuous build for version 0.2.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/savannahghi/healthy-route-ig/ and changes regularly. See the Directory of published versions
| Official URL: https://fhir.optimalhealth.org/ig/healthy-route/StructureMap/HRExtractVitals | Version: 0.2.0 | |||
| Draft as of 2026-11-12 | Computable Name: HRExtractVitals | |||
/// url = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureMap/HRExtractVitals' /// version = '0.2.0' /// name = 'HRExtractVitals' /// status = 'draft' uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QR as source uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias Bundle as target uses "http://hl7.org/fhir/StructureDefinition/Observation" alias Observation as target group HRExtractVitals(source qr : QR, target bundle : Bundle) { qr -> bundle.type = 'transaction' "type"; qr.item as g where (linkId = 'bp-reading-1') -> bundle.entry as e, e.resource = create('Observation') as obs then { qr -> obs then Reading(qr, g, obs, e) "reading"; g.item as si where (linkId = 'bp-reading-1.8480-6') then { si.answer first as sa then { sa.value as sv -> obs then Systolic(qr, sv, obs) "systolic"; }; } "systolicItem"; g.item as di where (linkId = 'bp-reading-1.8462-4') then { di.answer first as da then { da.value as dv -> obs then Diastolic(qr, dv, obs) "diastolic"; }; } "diastolicItem"; g.item as ti where (linkId = 'bp-reading-1.time') then { ti.answer first as ta then { ta.value as tv -> obs.effective = tv "effective"; }; } "timeItem"; qr -> obs.extension as x then { qr -> x.url = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-reading-sequence' "url"; qr -> x.value = 1 "value"; } "sequence"; } "reading1"; qr.item as g where (linkId = 'bp-reading-2') -> bundle.entry as e, e.resource = create('Observation') as obs then { qr -> obs then Reading(qr, g, obs, e) "reading"; g.item as si where (linkId = 'bp-reading-2.8480-6') then { si.answer first as sa then { sa.value as sv -> obs then Systolic(qr, sv, obs) "systolic"; }; } "systolicItem"; g.item as di where (linkId = 'bp-reading-2.8462-4') then { di.answer first as da then { da.value as dv -> obs then Diastolic(qr, dv, obs) "diastolic"; }; } "diastolicItem"; g.item as ti where (linkId = 'bp-reading-2.time') then { ti.answer first as ta then { ta.value as tv -> obs.effective = tv "effective"; }; } "timeItem"; qr -> obs.extension as x then { qr -> x.url = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-reading-sequence' "url"; qr -> x.value = 2 "value"; } "sequence"; g.item as pi where (linkId = 'bp-reading-2.bp-position') then { pi.answer first as pa then { pa.value as pv -> obs.extension as x then { qr -> x.url = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-reading-position' "url"; pv -> x.value = create('CodeableConcept') as concept, concept.coding = pv "value"; } "extension"; }; } "position"; } "reading2"; qr.item as g where (linkId = 'bp-reading-3') -> bundle.entry as e, e.resource = create('Observation') as obs then { qr -> obs then Reading(qr, g, obs, e) "reading"; g.item as si where (linkId = 'bp-reading-3.8480-6') then { si.answer first as sa then { sa.value as sv -> obs then Systolic(qr, sv, obs) "systolic"; }; } "systolicItem"; g.item as di where (linkId = 'bp-reading-3.8462-4') then { di.answer first as da then { da.value as dv -> obs then Diastolic(qr, dv, obs) "diastolic"; }; } "diastolicItem"; g.item as ti where (linkId = 'bp-reading-3.time') then { ti.answer first as ta then { ta.value as tv -> obs.effective = tv "effective"; }; } "timeItem"; qr -> obs.extension as x then { qr -> x.url = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-reading-sequence' "url"; qr -> x.value = 3 "value"; } "sequence"; } "reading3"; qr.item as it where (linkId = 'retinal-capture-time') then { it.answer first as a -> bundle.entry as e, e.resource = create('Observation') as obs then { qr -> obs then Shared(qr, it, obs, e) "base"; qr -> obs.meta as m, m.profile = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-observation' "profile"; qr -> obs.category = create('CodeableConcept') as cv then { qr -> cv.coding = create('Coding') as cd then { qr -> cd.system = 'http://terminology.hl7.org/CodeSystem/observation-category' "categorySystem"; qr -> cd.code = 'procedure' "categoryCode"; qr -> cd.display = 'Procedure' "categoryDisplay"; } "categoryCoding"; } "category"; qr -> obs.code = create('CodeableConcept') as cv then { qr -> cv.coding = create('Coding') as cd then { qr -> cd.system = 'https://fhir.optimalhealth.org/ig/healthy-route/CodeSystem/hr-measurement' "codeSystem"; qr -> cd.code = 'retinal-capture-time' "codeCode"; qr -> cd.display = 'Time of retinal capture' "codeDisplay"; } "codeCoding"; } "code"; a.value as v -> obs.effective = v "effective"; a.value as v -> obs.value = v; } "obs"; } "captureTime"; qr -> evaluate(qr, id.replaceMatches('/_history/.*$', '').replaceMatches('^.*/', '')) as qid then { qr.item as g where (linkId = 'bp-mean') -> bundle.entry as e, e.resource = create('Observation') as obs then { qr -> obs then Reading(qr, g, obs, e) "reading"; qr -> obs then Derived(qr, obs) "derivedCategory"; g.item as si where (linkId = 'bp-mean.8480-6') then { si.answer first as sa then { sa.value as sv -> obs then Systolic(qr, sv, obs) "systolic"; }; } "systolicItem"; g.item as di where (linkId = 'bp-mean.8462-4') then { di.answer first as da then { da.value as dv -> obs then Diastolic(qr, dv, obs) "diastolic"; }; } "diastolicItem"; qr.item as r3 where (linkId = 'bp-reading-3') then { r3.item as ti where (linkId = 'bp-reading-3.time') then { ti.answer first as ta then { ta.value as tv -> obs.effective = tv "effective"; }; } "time"; } "reading3"; qr -> obs.method = create('CodeableConcept') as m, m.text = 'Mean of readings 2 and 3' "method"; qr -> obs.derivedFrom = create('Reference') as r, r.reference = append('Observation/', qid, '-bp-reading-2') "reading2Ref"; qr -> obs.derivedFrom = create('Reference') as r, r.reference = append('Observation/', qid, '-bp-reading-3') "reading3Ref"; } "mean"; qr.item as g where (linkId = 'bp-mean-all') -> bundle.entry as e, e.resource = create('Observation') as obs then { qr -> obs then Reading(qr, g, obs, e) "reading"; qr -> obs then Derived(qr, obs) "derivedCategory"; g.item as si where (linkId = 'bp-mean-all.8480-6') then { si.answer first as sa then { sa.value as sv -> obs then Systolic(qr, sv, obs) "systolic"; }; } "systolicItem"; g.item as di where (linkId = 'bp-mean-all.8462-4') then { di.answer first as da then { da.value as dv -> obs then Diastolic(qr, dv, obs) "diastolic"; }; } "diastolicItem"; qr.item as r3 where (linkId = 'bp-reading-3') then { r3.item as ti where (linkId = 'bp-reading-3.time') then { ti.answer first as ta then { ta.value as tv -> obs.effective = tv "effective"; }; } "time"; } "reading3"; qr -> obs.method = create('CodeableConcept') as m, m.text = 'Mean of readings 1, 2 and 3' "method"; qr -> obs.derivedFrom = create('Reference') as r, r.reference = append('Observation/', qid, '-bp-reading-1') "reading1Ref"; qr -> obs.derivedFrom = create('Reference') as r, r.reference = append('Observation/', qid, '-bp-reading-2') "reading2Ref"; qr -> obs.derivedFrom = create('Reference') as r, r.reference = append('Observation/', qid, '-bp-reading-3') "reading3Ref"; } "meanAll"; } "derived"; } // The category a value worked out on this form carries beside its FHIR one. group Derived(source qr : QR, target obs : Observation) { qr -> obs.category = create('CodeableConcept') as cv then { qr -> cv.coding = create('Coding') as cd then { qr -> cd.system = 'https://fhir.optimalhealth.org/ig/healthy-route/CodeSystem/hr-observation-category' "derivedSystem"; qr -> cd.code = 'derived' "derivedCode"; qr -> cd.display = 'Derived' "derivedDisplay"; } "derivedCoding"; } "category"; } // One reading on the core blood pressure profile: the panel code, the monitor // as a component, and the shared identity. The group item's linkId names it. group Reading(source qr : QR, source g, target obs : Observation, target e) { qr -> obs then Shared(qr, g, obs, e) "base"; qr -> obs.meta as m, m.profile = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-blood-pressure' "profile"; qr -> obs.category = create('CodeableConcept') as cv then { qr -> cv.coding = create('Coding') as cd then { qr -> cd.system = 'http://terminology.hl7.org/CodeSystem/observation-category' "categorySystem"; qr -> cd.code = 'vital-signs' "categoryCode"; qr -> cd.display = 'Vital Signs' "categoryDisplay"; } "categoryCoding"; } "category"; qr -> obs.code = create('CodeableConcept') as cv then { qr -> cv.coding = create('Coding') as cd then { qr -> cd.system = 'http://loinc.org' "codeSystem"; qr -> cd.code = '85354-9' "codeCode"; qr -> cd.display = 'Blood pressure panel with all children optional' "codeDisplay"; } "codeCoding"; } "code"; qr.item as d where (linkId = 'bp-device') then { d.answer first as da then { da.value as dv -> obs.extension as x then { qr -> x.url = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-reading-device' "url"; dv -> x.value = create('CodeableConcept') as concept, concept.coding = dv "value"; } "extension"; }; } "device"; } group Systolic(source qr : QR, source sv, target obs : Observation) { sv -> obs.component as comp then { qr -> comp.code = create('CodeableConcept') as cv then { qr -> cv.coding = create('Coding') as cd then { qr -> cd.system = 'http://loinc.org' "codeSystem"; qr -> cd.code = '8480-6' "codeCode"; qr -> cd.display = 'Systolic blood pressure' "codeDisplay"; } "codeCoding"; } "code"; sv -> comp.value = create('Quantity') as q then { sv -> q.value = sv "value"; qr -> q.system = 'http://unitsofmeasure.org' "system"; qr -> q.code = 'mm[Hg]' "unitCode"; qr -> q.unit = 'mmHg' "unit"; } "quantity"; } "component"; } group Diastolic(source qr : QR, source dv, target obs : Observation) { dv -> obs.component as comp then { qr -> comp.code = create('CodeableConcept') as cv then { qr -> cv.coding = create('Coding') as cd then { qr -> cd.system = 'http://loinc.org' "codeSystem"; qr -> cd.code = '8462-4' "codeCode"; qr -> cd.display = 'Diastolic blood pressure' "codeDisplay"; } "codeCoding"; } "code"; dv -> comp.value = create('Quantity') as q then { dv -> q.value = dv "value"; qr -> q.system = 'http://unitsofmeasure.org' "system"; qr -> q.code = 'mm[Hg]' "unitCode"; qr -> q.unit = 'mmHg' "unit"; } "quantity"; } "component"; } // Identity, tags, tenant, subject, encounter and performer. The profile is set // here for a measurement and overridden by Reading for a blood pressure. group Shared(source qr : QR, source it, target obs : Observation, target e) { qr -> evaluate(qr, id.replaceMatches('/_history/.*$', '').replaceMatches('^.*/', '')) as qid then { it.linkId as k -> append(qid, '-', k) as idText, obs.id = cast(idText, 'id') "id"; it.linkId as k -> e.fullUrl = append('Observation/', qid, '-', k) "fullUrl"; it.linkId as k -> e.request as rq then { qr -> rq.method = 'PUT' "method"; qr -> rq.url = append('Observation/', qid, '-', k) "url"; } "request"; } "ids"; qr.meta as qm then { qm.tag as t -> obs.meta as m, m.tag = t; } "tags"; qr.extension as x where (url = 'https://fhir.optimalhealth.org/ig/healthy-route/StructureDefinition/hr-tenant') -> obs.extension = x "tenant"; qr -> obs.status = 'final' "status"; qr.subject as s -> obs.subject = s; qr.encounter as en -> obs.encounter = en; qr.author as au -> obs.performer = au "performer"; }