DEV Community

vitagroup HIP for vitagroup HIP

Posted on • Edited on

Part 3: Storing a Blood pressure measurement

Series by Stefan Spiska, Senior Backend Developer, PEN, vitagroup HIP

Part 3 of the series "Vendor neutral interoperability with openEHR and HL7 FHIR"

Previous examples handled the management of non medical data in HIP.

Let’s jump to the management of medical data with the example of creating and and in a later part searching a blood pressure in HIP.

Let’s assume that a hospital has developed an app on the HIP where patients in follow up care can document their blood pressure measurements. The app sends this data as an HL7 FHIR Observation to HIP:

{
  "resourceType" : "Observation",
  "id" : "blood-pressure",
  "meta" : {
    "profile" : ["http://hl7.org/fhir/StructureDefinition/vitalsigns"]
  },
  "identifier" : [{
    "system" : "urn:ietf:rfc:3986",
    "value" : "urn:uuid:187e0c12-8dd2-67e2-99b2-bf273c878281"
  }],
  "status" : "final",
  "category" : [{
    "coding" : [{
      "system" : "http://terminology.hl7.org/CodeSystem/observation-category",
      "code" : "vital-signs",
      "display" : "Vital Signs"
    }]
  },
  {
    "coding" : [{
      "system" : "http://loinc.org",
      "code" : "85354-9",
      "display" : "Blood pressure panel with all children optional"
    }]
  }],
  "code" : {
    "coding" : [{
      "system" : "http://loinc.org",
      "code" : "85354-9",
      "display" : "Blood pressure panel with all children optional"
    }],
    "text" : "Blood pressure systolic & diastolic"
  },
 "subject" : {
    "reference" : "https://hip.org/Patient/patient-example-01"
  },


  "effectiveDateTime" : "2012-09-17"

  "component" : [{
    "code" : {
      "coding" : [{
        "system" : "http://loinc.org",
        "code" : "8480-6",
        "display" : "Systolic blood pressure"
      }
    },
    "valueQuantity" : {
      "value" : 107,
      "unit" : "mmHg",
      "system" : "http://unitsofmeasure.org",
      "code" : "mm[Hg]"
    }
  },
  {
    "code" : {
      "coding" : [{
        "system" : "http://loinc.org",
        "code" : "8462-4",
        "display" : "Diastolic blood pressure"
      }]
    },
    "valueQuantity" : {
      "value" : 60,
      "unit" : "mmHg",
      "system" : "http://unitsofmeasure.org",
      "code" : "mm[Hg]"
    },

}
Enter fullscreen mode Exit fullscreen mode

openEHR, FHIR – Semantic binding

HIP uses EHRbase for data storage which implements the openEHR standard. The biggest difference between openEHR and FHIR is how the semantic bindings are done.

If one looks at the FHIR definition we get a syntactic structure in the form of an OBSERVATION which contains a list of components which in this case contains a Quantity. But only when we look at the coding and see a LOINC code of 8462-4 then we know from a semantic standpoint that value Quantity represent the diastolic blood pressure.

In openEHR on the other side we have archetypes which represent a specific medical domain object like a
blood pressure:

Image description

The important part here is that this is a maximal data set created by medical professionals, ensuring consistency and completeness of clinical data across systems and use-cases.

Creating an openEHR Template

To integrate FHIR Observation data into HIP, one can use the openEHR Archetype Designer to create a Template (demo-mapping.ehrbase.org.v0).

  • The template acts as a structured clinical model, combining multiple openEHR Archetypes.
  • One can disable elements based on what data are needed (e.g., just systolic and diastolic values).
  • Since a template is a collection of constraints on archetypes, interoperability between different templates is ensured.

Image description

Mapping FHIR to openEHR Using PSPL

Similar to the HL7 v2 example in the previous part, one can use PSPL to define mappings between FHIR and openEHR.

For example now on can easily define the mappings for the component with code 8480-6 to the path /data[at0001]/events[at0006]/data[at0003]/items[at0004]/value in the archetype openEHR-EHR-OBSERVATION.blood_pressure.v2 which will contain a Dv_Quantity which represents the systolic blood pressure.

{
  "storageClass": "DvQuantity",
  "storagePath": "/content[openEHR-EHR-OBSERVATION.blood_pressure.v2]/data[at0001]/events[at0006]/data[at0003]/items[at0004]/value",
  "attributes": {
    "magnitude": {
      "type": "rw",
      "dataType": "Double",
      "sourcePath": "component[isList: true, where: 'code.coding[isList: true].code=\"8480-6\"'].valueQuantity.value"
    },
    "units": {
      "type": "rw",
      "dataType": "String",
      "sourcePath": "component[isList: true, where: 'code.coding[isList: true].code=\"8480-6\"'].valueQuantity.code"
    },
    "unitsSystem": {
      "type": "rw",
      "dataType": "String",
      "sourcePath": "component[isList: true, where: 'code.coding[isList: true].code=\"8480-6\"'].valueQuantity.system"
    },
    "unitsDisplayName": {
      "type": "rw",
      "dataType": "String",
      "sourcePath": "component[isList: true, where: 'code.coding[isList: true].code=\"8480-6\"'].valueQuantity.unit"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

By applying similar mappings for all components, the FHIR OBSERVATION can be transformed into an openEHR COMPOSITION (the root class of each document) based on the template.

{
  "_type": "COMPOSITION",
  "name": {
    "_type": "DV_TEXT",
    "value": "demo-mapping.ehrbase.org.v0"
  },
  "archetype_details": {
    "archetype_id": {
      "value": "openEHR-EHR-COMPOSITION.report.v1"
    },
    "template_id": {
      "value": "demo-mapping.ehrbase.org.v0"
    },
    "rm_version": "1.0.4"
  },
  "language": {
    "_type": "CODE_PHRASE",
    "terminology_id": {
      "_type": "TERMINOLOGY_ID",
      "value": "ISO_639-1"
    },
    "code_string": "en"
  },
  "territory": {
    "_type": "CODE_PHRASE",
    "terminology_id": {
      "_type": "TERMINOLOGY_ID",
      "value": "ISO_3166-1"
    },
    "code_string": "DE"
  },
  "category": {
    "_type": "DV_CODED_TEXT",
    "value": "event",
    "defining_code": {
      "_type": "CODE_PHRASE",
      "terminology_id": {
        "_type": "TERMINOLOGY_ID",
        "value": "openehr"
      },
      "code_string": "433"
    }
  },
  "composer": {
    "_type": "PARTY_IDENTIFIED",
    "name": "Max Mustermann"
  },
  "context": {
    "_type": "EVENT_CONTEXT",
    "start_time": {
      "_type": "DV_DATE_TIME",
      "value": "2012-09-17T00:00:00"
    },
    "setting": {
      "_type": "DV_CODED_TEXT",
      "value": "home",
      "defining_code": {
        "_type": "CODE_PHRASE",
        "terminology_id": {
          "_type": "TERMINOLOGY_ID",
          "value": "openehr"
        },
        "code_string": "225"
      }
    }
  },
  "content": [
    {
      "_type": "OBSERVATION",
      "name": {
        "_type": "DV_CODED_TEXT",
        "value": "Blood pressure panel with all children optional",
        "defining_code": {
          "_type": "CODE_PHRASE",
          "terminology_id": {
            "_type": "TERMINOLOGY_ID",
            "value": "http://loinc.org"
          },
          "code_string": "8480-6"
        }
      },
      "archetype_details": {
        "archetype_id": {
          "value": "openEHR-EHR-OBSERVATION.blood_pressure.v2"
        },
        "rm_version": "1.0.4"
      },
      "language": {
        "_type": "CODE_PHRASE",
        "terminology_id": {
          "_type": "TERMINOLOGY_ID",
          "value": "ISO_639-1"
        },
        "code_string": "en"
      },
      "encoding": {
        "_type": "CODE_PHRASE",
        "terminology_id": {
          "_type": "TERMINOLOGY_ID",
          "value": "IANA_character-sets"
        },
        "code_string": "ISO-10646-UTF-1"
      },
      "subject": {
        "_type": "PARTY_SELF"
      },
      "data": {
        "name": {
          "_type": "DV_TEXT",
          "value": "History"
        },
        "origin": {
          "_type": "DV_DATE_TIME",
          "value": "2012-09-17T00:00:00"
        },
        "events": [
          {
            "_type": "POINT_EVENT",
            "name": {
              "_type": "DV_TEXT",
              "value": "Any event"
            },
            "time": {
              "_type": "DV_DATE_TIME",
              "value": "2012-09-17T00:00:00"
            },
            "data": {
              "_type": "ITEM_TREE",
              "name": {
                "_type": "DV_TEXT",
                "value": "blood pressure"
              },
              "items": [
                {
                  "_type": "ELEMENT",
                  "name": {
                    "_type": "DV_TEXT",
                    "value": "Systolic"
                  },
                  "value": {
                    "_type": "DV_QUANTITY",
                    "units": "mm[Hg]",
                    "magnitude": 107
                  },
                  "archetype_node_id": "at0004"
                },
                {
                  "_type": "ELEMENT",
                  "name": {
                    "_type": "DV_TEXT",
                    "value": "Diastolic"
                  },
                  "value": {
                    "_type": "DV_QUANTITY",
                    "units": "mm[Hg]",
                    "magnitude": 60.0
                  },
                  "archetype_node_id": "at0005"
                }
              ],
              "archetype_node_id": "at0003"
            },
            "archetype_node_id": "at0006"
          }
        ],
        "archetype_node_id": "at0001"
      },
      "archetype_node_id": "openEHR-EHR-OBSERVATION.blood_pressure.v2"
    }
  ],
  "archetype_node_id": "openEHR-EHR-COMPOSITION.report.v1"
}
Enter fullscreen mode Exit fullscreen mode

Thus similar to the case of the ADT message in the previous part whenever a FHIR Observation is sent from the App, a Composition with template demo-mapping.ehrbase.org.v0 is created in EHRbase for the patient which is using the app.

Dealing with encounter

There is a small thing which remains. In FHIR the encounter for an observation is represented by a reference

{
...
"encounter":{
    "reference" : "https://hip.org//74aa52fc-6aff-46aa-9848-e37b01335411"
    }
}
Enter fullscreen mode Exit fullscreen mode

In openEhr, Compositions can be put into a virtual directory to represent logical ordering of things:

Image description

So the HIP-Bridge will for each encounter create a Folder and put the Composition in the folder representing the Encounter. We will see in the next part how to use this to quickly query for all Compositions in an Encounter.

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

If this article connected with you, consider tapping ❤️ or leaving a brief comment to share your thoughts!

Okay