FHIR IG analytics| Package | silfhirprofileig |
| Resource Type | StructureMap |
| Id | StructureMap-ExtractCNPIPainAssessment.json |
| FHIR Version | R5 |
| Source | https://build.fhir.org/ig/savannahghi/sil_fhir_profile_ig/StructureMap-ExtractCNPIPainAssessment.html |
| URL | https://fhir.slade360.co.ke/fhir/StructureMap/ExtractCNPIPainAssessment |
| Version | 0.1.0 |
| Status | active |
| Date | 2026-09-11T12:18:36+00:00 |
| Name | ExtractCNPIPainAssessment |
| Title | Checklist of Nonverbal Pain Indicators Extraction |
| Description | The LOINC CNPI panel out as one Observation carrying the total, with the with-movement and at-rest scores and all twelve observed behaviours as components, and whether any pain behaviour was seen at all as its interpretation. Each score prefers what the form submitted and otherwise counts the behaviours itself, and a score only extracts when all six of its behaviours have been answered. |
No resources found
No resources found
Note: links and images are rebased to the (stated) source
Generated Narrative: StructureMap ExtractCNPIPainAssessment
/// url = 'https://fhir.slade360.co.ke/fhir/StructureMap/ExtractCNPIPainAssessment' /// name = 'ExtractCNPIPainAssessment' /// title = 'Checklist of Nonverbal Pain Indicators Extraction' /// status = 'active' /// description = 'The LOINC CNPI panel out as one Observation carrying the total, with the with-movement and at-rest scores and all twelve observed behaviours as components, and whether any pain behaviour was seen at all as its interpretation. Each score prefers what the form submitted and otherwise counts the behaviours itself, and a score only extracts when all six of its behaviours have been answered.' 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 ExtractCNPIPainAssessment(source qr : QR, target bundle : Bundle) { qr -> bundle.type = 'transaction' "setBundleType"; // Unlike Braden and Morse, LOINC nests this one: the six behaviours watched for // during movement sit under /99288-3 and the six watched for at rest under // /99296-6, each group ending in its own score, with the total on its own at the // top. The response itself is still the anchor for the Observation. qr where (item.item.answer.value.ofType(Coding).exists()) -> bundle.entry as entry, entry.resource = create('Observation') as obs then { qr -> obs, entry then BuildObsBase(qr, obs, entry) "base"; qr -> obs then SetSurveyCategory(qr, obs) "category"; qr -> obs.code as code then { qr -> code.coding as coding then { qr -> coding.system = 'http://loinc.org' "codeSystem"; qr -> coding.code = '99304-8' "codeCode"; qr -> coding.display = 'Total score [CNPI]' "codeDisplay"; } "codeCoding"; } "code"; // The submitted total wins; otherwise count the behaviours. // No weight lookup is needed here and none should be invented: every one of // the twelve behaviours is worth one if it was seen and nothing if it was // not, so the score is a count of LA33-6 "Yes" answers. Feldt scores the // instrument exactly that way. // Guarded on all twelve behaviours being answered. A CNPI of 4 out of the six // that were watched for reads as a patient in less distress than a CNPI of 4 // out of twelve, and nothing in the resource would say which it was. qr where (item.item.answer.value.ofType(Coding).count() = 12) then { qr -> obs.value = evaluate(qr, iif(item.where(linkId = '/99304-8').answer.value.exists(), item.where(linkId = '/99304-8').answer.value.truncate(), item.item.answer.value.ofType(Coding).where(code = 'LA33-6').count())) "totalValue"; } "totalRule"; qr where (item.where(linkId = '/99288-3').item.answer.value.ofType(Coding).count() = 6) -> obs.component as comp then { qr -> comp.code as code then { qr -> code.coding as coding then { qr -> coding.system = 'http://loinc.org' "codeSystem"; qr -> coding.code = '99295-8' "codeCode"; qr -> coding.display = 'With movement score [CNPI]' "codeDisplay"; } "codeCoding"; } "movementScoreCode"; qr -> comp.value = evaluate(qr, iif(item.where(linkId = '/99288-3').item.where(linkId = '/99288-3/99295-8').answer.value.exists(), item.where(linkId = '/99288-3').item.where(linkId = '/99288-3/99295-8').answer.value.truncate(), item.where(linkId = '/99288-3').item.answer.value.ofType(Coding).where(code = 'LA33-6').count())) "movementScoreValue"; } "movementScoreRule"; qr where (item.where(linkId = '/99296-6').item.answer.value.ofType(Coding).count() = 6) -> obs.component as comp then { qr -> comp.code as code then { qr -> code.coding as coding then { qr -> coding.system = 'http://loinc.org' "codeSystem"; qr -> coding.code = '99303-0' "codeCode"; qr -> coding.display = 'At rest score [CNPI]' "codeDisplay"; } "codeCoding"; } "restScoreCode"; qr -> comp.value = evaluate(qr, iif(item.where(linkId = '/99296-6').item.where(linkId = '/99296-6/99303-0').answer.value.exists(), item.where(linkId = '/99296-6').item.where(linkId = '/99296-6/99303-0').answer.value.truncate(), item.where(linkId = '/99296-6').item.answer.value.ofType(Coding).where(code = 'LA33-6').count())) "restScoreValue"; } "restScoreRule"; // ── The six behaviours watched for during movement ─────────────────────── qr.item as g where (linkId = '/99288-3') then { g.item as it where ((linkId = '/99288-3/99289-1') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99289-1' "codeCode"; it -> coding.display = 'Nonverbal vocal complaints during movement' "codeDisplay"; } "codeCoding"; } "vocalMovementCode"; it -> comp then SetComponentCodedValue(it, comp) "vocalMovementValue"; } "vocalMovementRule"; g.item as it where ((linkId = '/99288-3/99290-9') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99290-9' "codeCode"; it -> coding.display = 'Facial grimaces or winces during movement' "codeDisplay"; } "codeCoding"; } "grimaceMovementCode"; it -> comp then SetComponentCodedValue(it, comp) "grimaceMovementValue"; } "grimaceMovementRule"; g.item as it where ((linkId = '/99288-3/99291-7') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99291-7' "codeCode"; it -> coding.display = 'Bracing during movement' "codeDisplay"; } "codeCoding"; } "bracingMovementCode"; it -> comp then SetComponentCodedValue(it, comp) "bracingMovementValue"; } "bracingMovementRule"; g.item as it where ((linkId = '/99288-3/99292-5') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99292-5' "codeCode"; it -> coding.display = 'Rubbing during movement' "codeDisplay"; } "codeCoding"; } "rubbingMovementCode"; it -> comp then SetComponentCodedValue(it, comp) "rubbingMovementValue"; } "rubbingMovementRule"; g.item as it where ((linkId = '/99288-3/99293-3') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99293-3' "codeCode"; it -> coding.display = 'Restlessness during movement' "codeDisplay"; } "codeCoding"; } "restlessMovementCode"; it -> comp then SetComponentCodedValue(it, comp) "restlessMovementValue"; } "restlessMovementRule"; g.item as it where ((linkId = '/99288-3/99294-1') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99294-1' "codeCode"; it -> coding.display = 'Verbal complaints during movement' "codeDisplay"; } "codeCoding"; } "verbalMovementCode"; it -> comp then SetComponentCodedValue(it, comp) "verbalMovementValue"; } "verbalMovementRule"; } "movementBehaviours"; // ── The same six watched for again at rest ─────────────────────────────── qr.item as g where (linkId = '/99296-6') then { g.item as it where ((linkId = '/99296-6/99297-4') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99297-4' "codeCode"; it -> coding.display = 'Nonverbal vocal complaints while at rest' "codeDisplay"; } "codeCoding"; } "vocalRestCode"; it -> comp then SetComponentCodedValue(it, comp) "vocalRestValue"; } "vocalRestRule"; g.item as it where ((linkId = '/99296-6/99298-2') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99298-2' "codeCode"; it -> coding.display = 'Facial grimaces or winces while at rest' "codeDisplay"; } "codeCoding"; } "grimaceRestCode"; it -> comp then SetComponentCodedValue(it, comp) "grimaceRestValue"; } "grimaceRestRule"; g.item as it where ((linkId = '/99296-6/99299-0') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99299-0' "codeCode"; it -> coding.display = 'Bracing while at rest' "codeDisplay"; } "codeCoding"; } "bracingRestCode"; it -> comp then SetComponentCodedValue(it, comp) "bracingRestValue"; } "bracingRestRule"; g.item as it where ((linkId = '/99296-6/99300-6') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99300-6' "codeCode"; it -> coding.display = 'Restlessness while at rest' "codeDisplay"; } "codeCoding"; } "restlessRestCode"; it -> comp then SetComponentCodedValue(it, comp) "restlessRestValue"; } "restlessRestRule"; g.item as it where ((linkId = '/99296-6/99301-4') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99301-4' "codeCode"; it -> coding.display = 'Rubbing while at rest' "codeDisplay"; } "codeCoding"; } "rubbingRestCode"; it -> comp then SetComponentCodedValue(it, comp) "rubbingRestValue"; } "rubbingRestRule"; g.item as it where ((linkId = '/99296-6/99302-2') and answer.value.exists()) -> obs.component as comp then { it -> comp.code as code then { it -> code.coding as coding then { it -> coding.system = 'http://loinc.org' "codeSystem"; it -> coding.code = '99302-2' "codeCode"; it -> coding.display = 'Verbal complaints while at rest' "codeDisplay"; } "codeCoding"; } "verbalRestCode"; it -> comp then SetComponentCodedValue(it, comp) "verbalRestValue"; } "verbalRestRule"; } "restBehaviours"; qr -> obs then AddCNPIInterpretation(obs, obs) "interpretation"; } "cnpiRule"; } // ───────────────────────────────────────────────────────────────────────────── // The band // CNPI publishes no tiers. Feldt validated it as a count of pain behaviours in a // patient who cannot say they are in pain, and the guidance that comes with it is // that any behaviour seen is worth investigating -- not that four is twice as bad // as two. So this is two states, not a scale: none observed, or some observed. // Inventing cut-points to make it read like Braden and Morse would be putting // numbers in a clinician's hands that nobody published. // It is an Observation.interpretation and not a RiskAssessment. Pain behaviour // seen at the bedside is a finding about the patient now, and RiskAssessment // models the likelihood of a future outcome. Braden and Morse do predict one -- // a pressure injury, a fall -- and keep their RiskAssessments; this does not. // N and A come from SGHIObservationInterpretation, the value set this IG binds // Observation.interpretation to, and they carry the two states exactly. Nothing // needed minting: unlike a severity scale, present-or-absent is what the // normality axis is for. // ───────────────────────────────────────────────────────────────────────────── group AddCNPIInterpretation(source obs : Observation, target tgt : Observation) { obs where (value.ofType(integer) = 0) -> tgt.interpretation as interp then { obs -> interp.coding as coding then { obs -> coding.system = 'http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation' "interpSystem"; obs -> coding.code = 'N' "interpCode"; obs -> coding.display = 'Normal' "interpDisplay"; } "interpCoding"; obs -> interp.text = 'No pain behaviours observed' "interpText"; } "cnpiNone"; obs where (value.ofType(integer) >= 1) -> tgt.interpretation as interp then { obs -> interp.coding as coding then { obs -> coding.system = 'http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation' "interpSystem"; obs -> coding.code = 'A' "interpCode"; obs -> coding.display = 'Abnormal' "interpDisplay"; } "interpCoding"; obs -> interp.text = 'Pain behaviours observed - further assessment indicated' "interpText"; } "cnpiPresent"; } // ───────────────────────────────────────────────────────────────────────────── // Shared scaffolding. Repeated in each map rather than imported: the transform // engine resolves `imports` against whatever StructureMaps happen to be on the // server, and a form that stops extracting because a shared map was not // uploaded is a worse failure than a duplicated group. // ───────────────────────────────────────────────────────────────────────────── // Two notes on what the publisher's StructureMap validator says about this file. // Source parameters below are left untyped on purpose. Writing `: Element` makes // the validator compare QuestionnaireResponse.item against the literal 'Element' // and report them as incompatible with each other, which is noise, not a finding. // Untyped, it says only that it cannot check the paths. // `evaluate(context, expression)` is flagged as "takes 1 parameter but 2 were // found". Leave it. The FML parser in the same jar refuses the one-argument form // outright -- it wants a parameter, a comma, then the FHIRPath -- so the publisher // is objecting to what its own compiler emits. Two arguments is the only form that // compiles, and it is what the R5 transform engine executes. group BuildObsBase(source qr : QR, target obs : Observation, target entry) { qr -> obs.id = uuid() then SetObservationFullUrl(obs, entry) "idAndFullUrl"; qr -> entry.request as request then { qr -> request.method = 'POST' "requestMethod"; qr -> request.url = 'Observation' "requestUrl"; } "entryRequest"; qr -> obs.status = 'final' "status"; qr.subject as s -> obs.subject = s; qr.encounter as e -> obs.encounter = e; qr.authored as t -> obs.effective = t "effective"; qr.source as src -> obs.performer = src "performerFromSource"; qr where (source.exists().not()) then { qr.author as a -> obs.performer = a "performerFromAuthor"; } "performerFallback"; // A stored response's id already reads "QuestionnaireResponse/<id>", so it is a // relative reference as it stands. The hasValue() guard is what stops an // unsaved response -- one posted straight to $extract rather than saved first -- // from writing "QuestionnaireResponse/null" into the record. qr.id as qid where ($this.hasValue()) -> obs.derivedFrom = create('Reference') as ref, ref.reference = qid "linkQuestionnaireResponse"; } group SetComponentCodedValue(source it, target comp) { it.answer first as a then { a.value as cv -> comp.value = create('CodeableConcept') as cc then { cv -> cc.coding = cv "valueCoding"; cv.display as d -> cc.text = d "valueText"; } "codedValue"; } "componentAnswer"; } group SetSurveyCategory(source qr : QR, target obs : Observation) { qr -> obs.category as cat then { qr -> cat.coding as coding then { qr -> coding.system = 'http://terminology.hl7.org/CodeSystem/observation-category' "categorySystem"; qr -> coding.code = 'survey' "categoryCode"; qr -> coding.display = 'Survey' "categoryDisplay"; } "categoryCoding"; } "category"; } group SetObservationFullUrl(source obs : Observation, target entry) { obs.id as id -> entry.fullUrl = append('https://fhir.slade360.co.ke/fhir/Observation/', id) "assignFullUrl"; }
{
"resourceType": "StructureMap",
"id": "ExtractCNPIPainAssessment",
"text": {
"status": "generated",
"div": "<!-- snip (see above) -->"
},
"url": "https://fhir.slade360.co.ke/fhir/StructureMap/ExtractCNPIPainAssessment",
"version": "0.1.0",
"name": "ExtractCNPIPainAssessment",
"title": "Checklist of Nonverbal Pain Indicators Extraction",
"status": "active",
"date": "2026-09-11T12:18:36+00:00",
"publisher": "Kathurima Kimathi",
"contact": [
{
"name": "Kathurima Kimathi",
"telecom": [
{
"system": "url",
"value": "https://www.linkedin.com/in/kathurima-kimathi/"
},
{
"system": "email",
"value": "kathurimakimathi415@gmail.com"
}
]
},
{
"name": "Oscar John",
"telecom": [
{
"system": "email",
"value": "oscarjohnotieno@gmail.com",
"use": "work"
}
]
},
{
"name": "Kennedy Omondi",
"telecom": [
{
"system": "email",
"value": "kennankole@gmail.com",
"use": "work"
}
]
}
],
"description": "The LOINC CNPI panel out as one Observation carrying the total, with the with-movement and at-rest scores and all twelve observed behaviours as components, and whether any pain behaviour was seen at all as its interpretation. Each score prefers what the form submitted and otherwise counts the behaviours itself, and a score only extracts when all six of its behaviours have been answered.",
"structure": [
{
"url": "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse",
"mode": "source",
"alias": "QR"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/Bundle",
"mode": "target",
"alias": "Bundle"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/Observation",
"mode": "target",
"alias": "Observation"
}
],
"group": [
{
"name": "ExtractCNPIPainAssessment",
"input": [
{
"name": "qr",
"type": "QR",
"mode": "source"
},
{
"name": "bundle",
"type": "Bundle",
"mode": "target"
}
],
"rule": [
{
"name": "setBundleType",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "bundle",
"element": "type",
"transform": "copy",
"parameter": [
{
"valueString": "transaction"
}
]
}
]
},
{
"name": "cnpiRule",
"source": [
{
"context": "qr",
"condition": "item.item.answer.value.ofType(Coding).exists()"
}
],
"target": [
{
"context": "bundle",
"element": "entry",
"variable": "entry"
},
{
"context": "entry",
"element": "resource",
"variable": "obs",
"transform": "create",
"parameter": [
{
"valueString": "Observation"
}
]
}
],
"rule": [
{
"name": "base",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs"
},
{
"context": "entry"
}
],
"dependent": [
{
"name": "BuildObsBase",
"parameter": [
{
"valueId": "qr"
},
{
"valueId": "obs"
},
{
"valueId": "entry"
}
]
}
]
},
{
"name": "category",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs"
}
],
"dependent": [
{
"name": "SetSurveyCategory",
"parameter": [
{
"valueId": "qr"
},
{
"valueId": "obs"
}
]
}
]
},
{
"name": "code",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99304-8"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Total score [CNPI]"
}
]
}
]
}
]
}
]
},
{
"name": "totalRule",
"source": [
{
"context": "qr",
"condition": "item.item.answer.value.ofType(Coding).count() = 12"
}
],
"rule": [
{
"name": "totalValue",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs",
"element": "value",
"transform": "evaluate",
"parameter": [
{
"valueId": "qr"
},
{
"valueString": "iif(item.where(linkId = '/99304-8').answer.value.exists(), item.where(linkId = '/99304-8').answer.value.truncate(), item.item.answer.value.ofType(Coding).where(code = 'LA33-6').count())"
}
]
}
]
}
],
"documentation": "The submitted total wins; otherwise count the behaviours.\r\nNo weight lookup is needed here and none should be invented: every one of\r\nthe twelve behaviours is worth one if it was seen and nothing if it was\r\nnot, so the score is a count of LA33-6 \"Yes\" answers. Feldt scores the\r\ninstrument exactly that way.\r\nGuarded on all twelve behaviours being answered. A CNPI of 4 out of the six\r\nthat were watched for reads as a patient in less distress than a CNPI of 4\r\nout of twelve, and nothing in the resource would say which it was."
},
{
"name": "movementScoreRule",
"source": [
{
"context": "qr",
"condition": "item.where(linkId = '/99288-3').item.answer.value.ofType(Coding).count() = 6"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "movementScoreCode",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99295-8"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "With movement score [CNPI]"
}
]
}
]
}
]
}
]
},
{
"name": "movementScoreValue",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "comp",
"element": "value",
"transform": "evaluate",
"parameter": [
{
"valueId": "qr"
},
{
"valueString": "iif(item.where(linkId = '/99288-3').item.where(linkId = '/99288-3/99295-8').answer.value.exists(), item.where(linkId = '/99288-3').item.where(linkId = '/99288-3/99295-8').answer.value.truncate(), item.where(linkId = '/99288-3').item.answer.value.ofType(Coding).where(code = 'LA33-6').count())"
}
]
}
]
}
]
},
{
"name": "restScoreRule",
"source": [
{
"context": "qr",
"condition": "item.where(linkId = '/99296-6').item.answer.value.ofType(Coding).count() = 6"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "restScoreCode",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99303-0"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "At rest score [CNPI]"
}
]
}
]
}
]
}
]
},
{
"name": "restScoreValue",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "comp",
"element": "value",
"transform": "evaluate",
"parameter": [
{
"valueId": "qr"
},
{
"valueString": "iif(item.where(linkId = '/99296-6').item.where(linkId = '/99296-6/99303-0').answer.value.exists(), item.where(linkId = '/99296-6').item.where(linkId = '/99296-6/99303-0').answer.value.truncate(), item.where(linkId = '/99296-6').item.answer.value.ofType(Coding).where(code = 'LA33-6').count())"
}
]
}
]
}
]
},
{
"name": "movementBehaviours",
"source": [
{
"context": "qr",
"element": "item",
"variable": "g",
"condition": "linkId = '/99288-3'"
}
],
"rule": [
{
"name": "vocalMovementRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99288-3/99289-1') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "vocalMovementCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99289-1"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Nonverbal vocal complaints during movement"
}
]
}
]
}
]
}
]
},
{
"name": "vocalMovementValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "grimaceMovementRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99288-3/99290-9') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "grimaceMovementCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99290-9"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Facial grimaces or winces during movement"
}
]
}
]
}
]
}
]
},
{
"name": "grimaceMovementValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "bracingMovementRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99288-3/99291-7') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "bracingMovementCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99291-7"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Bracing during movement"
}
]
}
]
}
]
}
]
},
{
"name": "bracingMovementValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "rubbingMovementRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99288-3/99292-5') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "rubbingMovementCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99292-5"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Rubbing during movement"
}
]
}
]
}
]
}
]
},
{
"name": "rubbingMovementValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "restlessMovementRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99288-3/99293-3') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "restlessMovementCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99293-3"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Restlessness during movement"
}
]
}
]
}
]
}
]
},
{
"name": "restlessMovementValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "verbalMovementRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99288-3/99294-1') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "verbalMovementCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99294-1"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Verbal complaints during movement"
}
]
}
]
}
]
}
]
},
{
"name": "verbalMovementValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
}
],
"documentation": "── The six behaviours watched for during movement ───────────────────────"
},
{
"name": "restBehaviours",
"source": [
{
"context": "qr",
"element": "item",
"variable": "g",
"condition": "linkId = '/99296-6'"
}
],
"rule": [
{
"name": "vocalRestRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99296-6/99297-4') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "vocalRestCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99297-4"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Nonverbal vocal complaints while at rest"
}
]
}
]
}
]
}
]
},
{
"name": "vocalRestValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "grimaceRestRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99296-6/99298-2') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "grimaceRestCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99298-2"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Facial grimaces or winces while at rest"
}
]
}
]
}
]
}
]
},
{
"name": "grimaceRestValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "bracingRestRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99296-6/99299-0') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "bracingRestCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99299-0"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Bracing while at rest"
}
]
}
]
}
]
}
]
},
{
"name": "bracingRestValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "restlessRestRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99296-6/99300-6') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "restlessRestCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99300-6"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Restlessness while at rest"
}
]
}
]
}
]
}
]
},
{
"name": "restlessRestValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "rubbingRestRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99296-6/99301-4') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "rubbingRestCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99301-4"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Rubbing while at rest"
}
]
}
]
}
]
}
]
},
{
"name": "rubbingRestValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
},
{
"name": "verbalRestRule",
"source": [
{
"context": "g",
"element": "item",
"variable": "it",
"condition": "(linkId = '/99296-6/99302-2') and answer.value.exists()"
}
],
"target": [
{
"context": "obs",
"element": "component",
"variable": "comp"
}
],
"rule": [
{
"name": "verbalRestCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp",
"element": "code",
"variable": "code"
}
],
"rule": [
{
"name": "codeCoding",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "code",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "codeSystem",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://loinc.org"
}
]
}
]
},
{
"name": "codeCode",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "99302-2"
}
]
}
]
},
{
"name": "codeDisplay",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Verbal complaints while at rest"
}
]
}
]
}
]
}
]
},
{
"name": "verbalRestValue",
"source": [
{
"context": "it"
}
],
"target": [
{
"context": "comp"
}
],
"dependent": [
{
"name": "SetComponentCodedValue",
"parameter": [
{
"valueId": "it"
},
{
"valueId": "comp"
}
]
}
]
}
]
}
],
"documentation": "── The same six watched for again at rest ───────────────────────────────"
},
{
"name": "interpretation",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs"
}
],
"dependent": [
{
"name": "AddCNPIInterpretation",
"parameter": [
{
"valueId": "obs"
},
{
"valueId": "obs"
}
]
}
]
}
],
"documentation": "Unlike Braden and Morse, LOINC nests this one: the six behaviours watched for\r\nduring movement sit under /99288-3 and the six watched for at rest under\r\n/99296-6, each group ending in its own score, with the total on its own at the\r\ntop. The response itself is still the anchor for the Observation."
}
]
},
{
"name": "AddCNPIInterpretation",
"documentation": "─────────────────────────────────────────────────────────────────────────────\r\nThe band\r\nCNPI publishes no tiers. Feldt validated it as a count of pain behaviours in a\r\npatient who cannot say they are in pain, and the guidance that comes with it is\r\nthat any behaviour seen is worth investigating -- not that four is twice as bad\r\nas two. So this is two states, not a scale: none observed, or some observed.\r\nInventing cut-points to make it read like Braden and Morse would be putting\r\nnumbers in a clinician's hands that nobody published.\r\nIt is an Observation.interpretation and not a RiskAssessment. Pain behaviour\r\nseen at the bedside is a finding about the patient now, and RiskAssessment\r\nmodels the likelihood of a future outcome. Braden and Morse do predict one --\r\na pressure injury, a fall -- and keep their RiskAssessments; this does not.\r\nN and A come from SGHIObservationInterpretation, the value set this IG binds\r\nObservation.interpretation to, and they carry the two states exactly. Nothing\r\nneeded minting: unlike a severity scale, present-or-absent is what the\r\nnormality axis is for.\r\n─────────────────────────────────────────────────────────────────────────────",
"input": [
{
"name": "obs",
"type": "Observation",
"mode": "source"
},
{
"name": "tgt",
"type": "Observation",
"mode": "target"
}
],
"rule": [
{
"name": "cnpiNone",
"source": [
{
"context": "obs",
"condition": "value.ofType(integer) = 0"
}
],
"target": [
{
"context": "tgt",
"element": "interpretation",
"variable": "interp"
}
],
"rule": [
{
"name": "interpCoding",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "interp",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "interpSystem",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"
}
]
}
]
},
{
"name": "interpCode",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "N"
}
]
}
]
},
{
"name": "interpDisplay",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Normal"
}
]
}
]
}
]
},
{
"name": "interpText",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "interp",
"element": "text",
"transform": "copy",
"parameter": [
{
"valueString": "No pain behaviours observed"
}
]
}
]
}
]
},
{
"name": "cnpiPresent",
"source": [
{
"context": "obs",
"condition": "value.ofType(integer) >= 1"
}
],
"target": [
{
"context": "tgt",
"element": "interpretation",
"variable": "interp"
}
],
"rule": [
{
"name": "interpCoding",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "interp",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "interpSystem",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"
}
]
}
]
},
{
"name": "interpCode",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "A"
}
]
}
]
},
{
"name": "interpDisplay",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Abnormal"
}
]
}
]
}
]
},
{
"name": "interpText",
"source": [
{
"context": "obs"
}
],
"target": [
{
"context": "interp",
"element": "text",
"transform": "copy",
"parameter": [
{
"valueString": "Pain behaviours observed - further assessment indicated"
}
]
}
]
}
]
}
]
},
{
"name": "BuildObsBase",
"documentation": "─────────────────────────────────────────────────────────────────────────────\r\nShared scaffolding. Repeated in each map rather than imported: the transform\r\nengine resolves `imports` against whatever StructureMaps happen to be on the\r\nserver, and a form that stops extracting because a shared map was not\r\nuploaded is a worse failure than a duplicated group.\r\n─────────────────────────────────────────────────────────────────────────────\r\nTwo notes on what the publisher's StructureMap validator says about this file.\r\nSource parameters below are left untyped on purpose. Writing `: Element` makes\r\nthe validator compare QuestionnaireResponse.item against the literal 'Element'\r\nand report them as incompatible with each other, which is noise, not a finding.\r\nUntyped, it says only that it cannot check the paths.\r\n`evaluate(context, expression)` is flagged as \"takes 1 parameter but 2 were\r\nfound\". Leave it. The FML parser in the same jar refuses the one-argument form\r\noutright -- it wants a parameter, a comma, then the FHIRPath -- so the publisher\r\nis objecting to what its own compiler emits. Two arguments is the only form that\r\ncompiles, and it is what the R5 transform engine executes.",
"input": [
{
"name": "qr",
"type": "QR",
"mode": "source"
},
{
"name": "obs",
"type": "Observation",
"mode": "target"
},
{
"name": "entry",
"mode": "target"
}
],
"rule": [
{
"name": "idAndFullUrl",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs",
"element": "id",
"transform": "uuid"
}
],
"dependent": [
{
"name": "SetObservationFullUrl",
"parameter": [
{
"valueId": "obs"
},
{
"valueId": "entry"
}
]
}
]
},
{
"name": "entryRequest",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "entry",
"element": "request",
"variable": "request"
}
],
"rule": [
{
"name": "requestMethod",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "request",
"element": "method",
"transform": "copy",
"parameter": [
{
"valueString": "POST"
}
]
}
]
},
{
"name": "requestUrl",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "request",
"element": "url",
"transform": "copy",
"parameter": [
{
"valueString": "Observation"
}
]
}
]
}
]
},
{
"name": "status",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs",
"element": "status",
"transform": "copy",
"parameter": [
{
"valueString": "final"
}
]
}
]
},
{
"name": "subject",
"source": [
{
"context": "qr",
"element": "subject",
"variable": "s"
}
],
"target": [
{
"context": "obs",
"element": "subject",
"transform": "copy",
"parameter": [
{
"valueId": "s"
}
]
}
]
},
{
"name": "encounter",
"source": [
{
"context": "qr",
"element": "encounter",
"variable": "e"
}
],
"target": [
{
"context": "obs",
"element": "encounter",
"transform": "copy",
"parameter": [
{
"valueId": "e"
}
]
}
]
},
{
"name": "effective",
"source": [
{
"context": "qr",
"element": "authored",
"variable": "t"
}
],
"target": [
{
"context": "obs",
"element": "effective",
"transform": "copy",
"parameter": [
{
"valueId": "t"
}
]
}
]
},
{
"name": "performerFromSource",
"source": [
{
"context": "qr",
"element": "source",
"variable": "src"
}
],
"target": [
{
"context": "obs",
"element": "performer",
"transform": "copy",
"parameter": [
{
"valueId": "src"
}
]
}
]
},
{
"name": "performerFallback",
"source": [
{
"context": "qr",
"condition": "source.exists().not()"
}
],
"rule": [
{
"name": "performerFromAuthor",
"source": [
{
"context": "qr",
"element": "author",
"variable": "a"
}
],
"target": [
{
"context": "obs",
"element": "performer",
"transform": "copy",
"parameter": [
{
"valueId": "a"
}
]
}
]
}
]
},
{
"name": "linkQuestionnaireResponse",
"source": [
{
"context": "qr",
"element": "id",
"variable": "qid",
"condition": "$this.hasValue()"
}
],
"target": [
{
"context": "obs",
"element": "derivedFrom",
"variable": "ref",
"transform": "create",
"parameter": [
{
"valueString": "Reference"
}
]
},
{
"context": "ref",
"element": "reference",
"transform": "copy",
"parameter": [
{
"valueId": "qid"
}
]
}
],
"documentation": "A stored response's id already reads \"QuestionnaireResponse/<id>\", so it is a\r\nrelative reference as it stands. The hasValue() guard is what stops an\r\nunsaved response -- one posted straight to $extract rather than saved first --\r\nfrom writing \"QuestionnaireResponse/null\" into the record."
}
]
},
{
"name": "SetComponentCodedValue",
"input": [
{
"name": "it",
"mode": "source"
},
{
"name": "comp",
"mode": "target"
}
],
"rule": [
{
"name": "componentAnswer",
"source": [
{
"context": "it",
"element": "answer",
"listMode": "first",
"variable": "a"
}
],
"rule": [
{
"name": "codedValue",
"source": [
{
"context": "a",
"element": "value",
"variable": "cv"
}
],
"target": [
{
"context": "comp",
"element": "value",
"variable": "cc",
"transform": "create",
"parameter": [
{
"valueString": "CodeableConcept"
}
]
}
],
"rule": [
{
"name": "valueCoding",
"source": [
{
"context": "cv"
}
],
"target": [
{
"context": "cc",
"element": "coding",
"transform": "copy",
"parameter": [
{
"valueId": "cv"
}
]
}
]
},
{
"name": "valueText",
"source": [
{
"context": "cv",
"element": "display",
"variable": "d"
}
],
"target": [
{
"context": "cc",
"element": "text",
"transform": "copy",
"parameter": [
{
"valueId": "d"
}
]
}
]
}
]
}
]
}
]
},
{
"name": "SetSurveyCategory",
"input": [
{
"name": "qr",
"type": "QR",
"mode": "source"
},
{
"name": "obs",
"type": "Observation",
"mode": "target"
}
],
"rule": [
{
"name": "category",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "obs",
"element": "category",
"variable": "cat"
}
],
"rule": [
{
"name": "categoryCoding",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "cat",
"element": "coding",
"variable": "coding"
}
],
"rule": [
{
"name": "categorySystem",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "system",
"transform": "copy",
"parameter": [
{
"valueString": "http://terminology.hl7.org/CodeSystem/observation-category"
}
]
}
]
},
{
"name": "categoryCode",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "code",
"transform": "copy",
"parameter": [
{
"valueString": "survey"
}
]
}
]
},
{
"name": "categoryDisplay",
"source": [
{
"context": "qr"
}
],
"target": [
{
"context": "coding",
"element": "display",
"transform": "copy",
"parameter": [
{
"valueString": "Survey"
}
]
}
]
}
]
}
]
}
]
},
{
"name": "SetObservationFullUrl",
"input": [
{
"name": "obs",
"type": "Observation",
"mode": "source"
},
{
"name": "entry",
"mode": "target"
}
],
"rule": [
{
"name": "assignFullUrl",
"source": [
{
"context": "obs",
"element": "id",
"variable": "id"
}
],
"target": [
{
"context": "entry",
"element": "fullUrl",
"transform": "append",
"parameter": [
{
"valueString": "https://fhir.slade360.co.ke/fhir/Observation/"
},
{
"valueId": "id"
}
]
}
]
}
]
}
]
}