Link multiple Compositions to a single Visit

Hello Guys,

I am new to openEHR.

For a SINGLE Visit, a patient can have multiple compositions from different templates (Vital Signs, Problem Diagnosis, Body Temperature, Lab Order etc…)

How can I link these multiple compositions to the Visit.

Example use case: Generate a report that returns lab orders for a specific problem diagnosis in a single visit. How can i achieve this in openEHR???

Thanks for your help

3 Likes

Hi,

This is not totally correct: you are referring to archetypes as templates. All those clinical concepts you mention could be inside the same template and you can have just one composition for that template.

On the other hand, what would be different templates in a single visit are:

  • visit documentation
  • medication prescription
  • lab order
    . imaginology order
  • referral to a specialist
  • any other “document” would be represented as a single template and have a single composition associated.

Then, if you need to link all those compositions, you have two options:

  1. Use the LINK class from the openEHR RM
  2. Use the FOLDER class from the openEHR RM

LINK is basically that, a link :slight_smile:

FOLDER is a container for COMPOSITIONs and other structures that have something in common, for instance belong to the same visit. Currently the FOLDER can also hold a data structure, so there you can store stuff like a visit ID.

Hope that helps!

2 Likes

@pablo Thanks.
Thanks for the explanation.
The use of Folder class seems to be a viable option for me since I would like store the visit ID. Could you help share any resource to help me understand how to use it?

1 Like

Hi Ohia,

The folder description is found here: Common Information Model

Basically it’s a list of compositions and/or subfolders. You could make one folder for each visit.

If you like more specific advice, could you please share more details of your project and your usecase? Especially why you want to link the different compositions.

P.s. you might also be interested in the process component of openEHR (trial status) CDS, Guidelines and Planning Overview It offers advanced workflow modelling but may be too complicated for what your trying to achieve.

See other explanations here. One thing to keep in mind is that a single Contribution (openEHR term for a version change set) may contain version updates to various things, including medication list, care plan as well as observations etc made during the visit. Here’s an explanation and diagram. And more technical details here.

1 Like

@joostholslag here is our Outpatient use case.

  1. Operations Assistant Schedules an Appointment for a patient (A patient can also schedule an appointment)
  2. A nurse will create a VISIT and capture Reason for encounter and History of Presenting Illness.
  3. The nurse will capture Patient’s Vital Signs, allergies & current medication and also conduct a Nursing Observation.
  4. A doctor will evaluate the patient while recording information such as Past Medical history, Surgical History, Problem/Diagnosis, Procedures, Treatment Plan or referrals etc.
  5. The doctor may prescribe medication or order a lab test or imaging.

Hope this helps clarify our use case

Hi Ohia,

You can make a POST request like this:

ehrbase-test-system.com/ehrbase/rest/openehr/v1/ehr/7b3074c9-4c95-48cf-a2cd-64fde424a7aa/directory

(see EHR API for reference).

With the following payload:

{
      "_type": "FOLDER",
      "name": {
        "_type": "DV_TEXT",
        "value": "Episode 1234568"
      },
      "archetype_node_id": "openEHR-EHR-FOLDER.generic.v1",
      "details": {
        "_type": "ITEM_TREE",
        "name": {
          "_type": "DV_TEXT",
          "value": "Tree"
        },
        "archetype_node_id": "at0003",
        "items": [
          {
            "_type": "ELEMENT",
            "name": {
              "_type": "DV_TEXT",
              "value": "text"
            },
            "archetype_node_id": "at0004",
            "value": {
              "_type": "DV_TEXT",
              "value": "Here could be a description of the case"
            }
          }
        ]
      },
    	"items": [
        {
      		"id": {
      			"_type": "HIER_OBJECT_ID",
      			"value": "d936409e-901f-4994-8d33-ed104d460458"
      		},
      		"namespace": "my.system.id",
      		"type": "VERSIONED_COMPOSITION"
      	},{ 
          "id": {
      			"_type": "HIER_OBJECT_ID",
      			"value": "d936409e-901f-4994-8d33-ed104d460456"
      		},
      		"namespace": "my.system.id",
      		"type": "VERSIONED_COMPOSITION"
              }
      ]
    }
}

The name can contain the name of your folder. You can also add any valid openEHR reference model elements under “details”. For now, this does not refer to an actual archetype “openEHR-EHR-FOLDER.generic.v1” but is more like a placeholder. In the future, an archetype can be used to clearly define the content of the “details” section which might contain any metadata that is of relevance for the folder (in our example, this is a free text description).

You place the actual compositions inside the items tree

{
“id”: {
“_type”: “HIER_OBJECT_ID”,
“value”: “d936409e-901f-4994-8d33-ed104d460456”
},
“namespace”: “my.system.id”,
“type”: “VERSIONED_COMPOSITION”
}

You can then obtain the directory again using the following GET request:

ehrbase-test-system.com/ehrbase/rest/openehr/v1/ehr/7b3074c9-4c95-48cf-a2cd-64fde424a7aa/directory

While this might look a bit verbose, you can use functionality inside our openEHR SDK to make your life easier:

https://ehrbase.readthedocs.io/en/latest/04_sdk/02_reference/01_client_module/06_directory/index.html

UUID ehr = openEhrClient.ehrEndpoint().createEhr();

FolderDAO root = openEhrClient.folder(ehr, "");

FolderDAO visit = root.getSubFolder("case1/visit1");

EhrbaseBloodPressureSimpleDeV0Composition bloodPressureSimpleDeV01 = TestData.buildEhrbaseBloodPressureSimpleDeV0();
visit.addCompositionEntity(bloodPressureSimpleDeV01);

EhrbaseBloodPressureSimpleDeV0Composition bloodPressureSimpleDeV02 = TestData.buildEhrbaseBloodPressureSimpleDeV0();
visit.addCompositionEntity(bloodPressureSimpleDeV02);

List<EhrbaseBloodPressureSimpleDeV0Composition> actual = visit.find(EhrbaseBloodPressureSimpleDeV0Composition.class);
assertThat(actual).size().isEqualTo(2);

Hope this helps to get you started!

3 Likes

Hi Ohia,

Thank you for your explanation. This helps a lot! Am I correct your usecase is a medical specialist consultation in a hospital/clinic?

What I’m still looking for is, why do you want to link multiple compositions to a single visit? E.g. do you want to later easily find all the data related to that visit, or do you want when recording during the visit to see all the data in one ‘form’?

There are multiple ways to achieve these things and they heavily interrelate with UX design requirements, not just the different backend tech options (contribution, folder, link, DV_EHR_URI, mega composition).
That’s why I’m really interested in (even) more details on your use case.

Hi @joostholslag Thanks for the response.
Yes, our use case is an Outpatient Clinic.
The use case is more or less driven by the UI/UX requirements.

We do not want to see all the data in one form. Quite the opposite.

For example, we want to create and capture the followings templates in different pages during the VISIT and should be able to query (AQL) a lab order that relates to the Acute Visit Template.

  1. Reason for encounter and History of Presenting Illness allergies & current medication Template
  2. Vital Signs, Anthropometry and Nursing Observation Template
  3. Acute Visit Template ( containing information such as Past Medical history, Surgical History, Problem/Diagnosis, Procedures, Treatment Plan or referrals. etc etc)
  4. prescription Order Template
  5. lab test Order Template
  6. imaging Order Template
3 Likes

This helps with my understanding, thanks for the clarification.
FOLDER per visit may work for your usecase. You can put the ‘visit id’ under ‘details’ as birger described.
Let us know if this know if you can make it work please. I’m curious for your experience. Don’t hesitate to ask for more help if you need it, openEHR can be difficult to get started on:) and your questions can help newcomers after you.

P.s. cool to see openEHR is being used in Nigeria!

1 Like

This is actually a very nice use case. All the Compositions (from as many forms as you like) should /could be committed in the same Contribution. However, in current openEHR systems, not much/any querying is built around Contribution, because it’s a low level versioning concept (= ‘change-set’ in most versioning systems).

Contribution UML model for reference.

Currently Contribution can be found in the REST API only by UID, but it would be easy enough to find it by date/time of the Contribution commit object. If the means of selection the ‘visit’ is the common one, i.e. a visual list of last N visits (or visits in last 3, 12 months, or whatever) then this method of picking and resolving is actually pretty easy, with no need for Folders. However - not ever Contribution might be a visit, so a bit of checking on Contribution contents might be needed to distinguish visits from other kinds of updates.

Only problem is that today, there is no GET Contribution by time method in the REST API. But that could easily be fixed and in the very short term, you could fake it by displaying last N Contribution dates with UID hidden behind, and then a selection of a date selects the corresponding UID, and then you use the current REST GET call.

This is not an argument against using FOLDERs - you might want to store a lot more meta-data per visit, in which case, FOLDERs are probably what you want. The above is just some suggestions on short term solutions.

Can a single contribution have multiple committers/editors. That is what Ohia requires. I can’t find it in the spec whether it’s allowed. I’d say the way Ohia describes it: first the nurse makes some changes, than de doctor makes some changes, should be multiple contributions. And then the contribution no longer is a good way to see which compositions relate to a single visit right?
I think folders is good enough for now, long term this should be solved by task planning I guess?

1 Like

It can; each thing committed in a Contribution is a VERSION containing data, which will be a COMPOSITION (or PARTY-like thing, in the demographic model). Each of those VERSIONs can have its own committer - since each has an independent AUDIT_DETAILS object.

That might also be the optimal approach - it depends on whether you want to consider the nurse activities as more or less self-standing and meaningful - e.g. establish presenting complaint, check some vital signs, meds, takes blood etc - this could easily be committed as a Contribution on its own. Even if the doc were called away and the main visit never happens, all this info is probably useful. The main visit could then generate its own Contribution.

The rule for Contributions is the same for any versioning system: ideally, the contributoin, which is the delta (unit of change) to the information base always leaves the info base (patient record, for us) in a new coherent state. Example: a visit that updates the care plan with a note about changing asthma medication and also updates the medication list with a new Instruction for the new medication should be committed as a single Contribution; if say only the Care Plan change is committed in a Contribution, then the result state post commit is an EHR that has a Care Plan with the new medication, but a meds list with only the old.

In practical reality, I suspect not much computing gets done in openEHR that makes any assumption about proper use of Contributions. In my opinion, systems should be a lot more careful, because Contribution is the unit of rollback.

1 Like

Hi Tom,

we indeed use Contribution mainly as the transaction container which will enable a roll-back once something fails. Hence, I don’t think the contribution should be used for representing encounter information or episodes of care, i.e. any clinically relevant data, or even try to group data together. With folders, this is much clearer and closer to what happens in analoge systems (making a shared understanding more likely).

3 Likes

Hi Birger,

I remember raising this point, but it was not in a written medium I think. I remember asking the transactional semantics of Contribution (specifically atomicity) , as in should a commit fail in case something in the Contribution is invalid, such as one composition out of N compositions failing validation. The answer I got at the time (I think from Tom, or maybe Heath) was that Contribution did not have any transaction semantics specified.

I always thought that it should, and Ocean’s implementation actually follows that approach. So this may be a good opportunity to suggest that we put this into the spec, i.e. clarify the atomicity of a Contribution’s commit operation: atomic, or not?

Tangent comment, I know, but you made a good point and I didn’t want to miss the opportunity.

2 Likes

It really should, and the explanation of Contribution implies this, but doesn’t require it, mainly because commit atomicity is at a DB/file system level, whereas the change control / versioning model described in the specs is at an interface/API level.

However, when interrogating an openEHR EHR through any public API, Contribution should be the reliable unit of commit and rollback. Normally, achieving that means making something equivalent the unit of commit in the concrete back-end - DB transaction, Github like change-set or whatever.

2 Likes

Which was part of the explanation I got at the time, but I omitted that from my post.
I think it’s OK to use the term atomicity without necessarily using its implementation level meaning. I don’t mind inventing something such as ‘should succeed or fail wholly as a single unit’ if we don’t want to imply a lower level concept, but we should clarify the failure scenario for uses of APIs.

So I think Contribution’s definition should require the behaviour we seem to agree on. I’d even say this is actually a good candidate to add to conformance specs…

4 Likes

At least in our implementation in EHRServer, the CONTRIBUTION is atomic, any failure on any COMPOSITION makes the whole CONTRIBUTION to be rejected.

I’m not sure how well specified is that part in our specs, but or my it was the most reasonable behavior, since the result of the CONTRIBUTION commit is for the whole CONTRIBUTION not for the individual items in it. So the result plays an important part in the interpretation of this specific behavior.

1 Like

Much-needed discussion! I want to contribute by adding a few other options on how this can be done. I feel like the directory approach explained very well by @birger.haarbrandt here is the “official” way to do this. However, I am going to be heavily critiquing the directory approach since I think it has many issues. These issues have also been brought up in more detail here by @pablo and @thomas.beale.

My main issues with the directory approach

  1. There can only be one directory per EHR: So every time you need to update it, you need to retrieve it, update parts that you want, and then post it back. I don’t like doing this since it increases the burden on applications to update the folders correctly. And giving full access to every app to update the root folder is just waiting for things to go wrong. And it’s a nightmare to implement Access Control policies on Directories and Folders based on the content.
  2. If you want to filter an AQL to a specific folder, you can’t do it in AQL directly (yet): You’ll need to get the directory first, run through all the compositions in a tree search, then use a MATCHES clause and include all the composition IDs there. I don’t like this too mostly because the directories can grow extremely large sometimes and having to get all the composition IDs manually only to feed it into an AQL doesn’t feel “well-integrated”. It’ll be easier to just store the directory information in an external database since it’ll at least solve problem 1.

Alternatives that solve both the above problems while still only using existing openEHR APIs

I’m all for the changes proposed here. But until that’s widely implemented and there’s support for executing AQLs on folders, this is what I’m doing:

1. Using other context
Include an archetype in the other_context part of a Composition to record the encounter information - You can probably use an existing archetype to store the Encounter/Visit identifier within this archetype.

It solves problem 1 since visit information is stored in the same transaction as the composition and problem 2 since you can now easily query this using AQL.

2. Somehow stuff the visit identifier in the composition. Somewhere. :grimacing:
Although the above approach works, I wanted to find a solution to this, WITHOUT changing any of our existing templates. That’s when I kinda started misusing the health_care_facility attribute which is part of the Compositions class in the RM. So we’ll do something like (in ECIS flat):

"opdvisitpdj.v0/context/_health_care_facility|name": "Medblocks Hospital",
"opdvisitpdj.v0/context/_health_care_facility|id": "b9ee9eae-84be-4a4f-9018-2014d8c5341a",
"opdvisitpdj.v0/context/_health_care_facility|id_scheme": "Encounter",
"opdvisitpdj.v0/context/_health_care_facility|id_namespace": "FHIR"

and query like:

SELECT c/context/health_care_facility FROM COMPOSITION c WHERE c/context/health_care_facility/external_ref/id/value='b9ee9eae-84be-4a4f-9018-2014d8c5341a

I know that I’m probably misusing the intent of the “health_care_facility” attribute in the composition. But it solves both my above-mentioned issues and works without having to change any templates to include special archetypes. And I’ve never really stored useful information in the health_care_facility anyway.

Maybe consider adding another attribute to the COMPOSITION class to uniformly record the visit information? Since it feels much better integrated with the system and the visit identifier is mostly just another context data point.

I welcome suggestions and corrections if I am wrong in taking this approach.

1 Like

Small clarification: we keep a log of the full CONTRIBUTION in the server even if the commit failed, that way we can keep track of successful and failed commits to check what was wrong with the rejected ones. So the server admin could actually access those failed CONTRIBUTIONS.

This is a design decision I did when I was implementing this part in EHRServer, not part of the openEHR specs.