Generic modeling and issues for querying

Hi all,

Lately I’ve been working a lot with lab test reports. Current CKM modeling for this relies on a generic model that applies to any kind and structure of result in this way:

  • COMPO.report-result // any result document

  • OBSERVATION.laboratory_test_result // results container, can be used as a panel

  • CLUSTER.laboratory_test_analyte // single result

This kind of generic model relies on specific structures to be set at runtime, and also to use specific codes to know which type of result is contained in the analytes (which remembers me of the way CDAs are modeled).

An example

For a lipids panel result, which contains analytes for cholesterol, triglyceride, HDL and LDL, we need systems to create that structure and use specific codes like:

  • COMPO
  • OBSERVATION
  • CLUSTER = cholesterol, LOINC::14647-2
  • CLUSTER = triglyceride, LOINC::14927-8
  • CLUSTER = HDL, LOINC::2085-9
  • CLUSTER = LDL, LOINC::39469-2

That is 4 occurrences of the same CLUSTER, and inside each CLUSTER, the same ELEMENTS (name, result, comment, etc).

Issues for querying

Now if we want to query that structure, we need to rely in the codes instead of in the structure, because the structure is set at runtime not at design time. So If we need the COMPOs that have cholesterol > 10 mmol/L we need a query like this:

SELECT …
FROM …, CLUSTER[CLUSTER.analyte] c

WHERE c/path_to_code = 14647-2 AND c/path_to_magnitude > 10 AND c/path_to_units = mmol/L

What’s the problem with that query?

If we have instances like this:

  • COMPO

  • OBSERVATION

  • CLUSTER = name=cholesterol, code=LOINC::14647-2, value=6.3 mmol/L

  • CLUSTER = name=triglyceride, code=LOINC::14927-8, value=12.3 mmol/L

  • CLUSTER = name=HDL, code=LOINC::2085-9, value=2.0 mmol/L

  • CLUSTER = name=LDL, code=LOINC::39469-2, value=1.5 mmol/L

c can be any of the 4 CLUSTERs set at runtime since all of them are occurrences of the same node defined in the archetype and the correspondent OPT. So when comparing the code, value and units that can match values from the other CLUSTERs, so we need a way to ensure those paths have the same instance parent, and that can’t be done with archetype paths.

So the query above might find the code 14647-2 in the first CLUSTER, but check the magnitude against the second CLUSTER that is > 10.

The issue goes away if each CLUSTER can have a specific nodeId that complies with the specification on the archetype but is really an instance nodeId.

Another solution might be to add some kind of extra expression to the AQL to say “these paths should be under the same parent instance”.

But the simplest would be just not to have generic models, so the “lipids panel” archetype would have 4 CLUSTERs each with it’s own nodeId, so when querying, the paths are pointing to different CLUSTERs and they contained ELEMENTs.

Not sure how others solve these cases, would like to hear if you use these generic models, how to query them without these issues, or if you just go with specific models.

Thanks.

Pablo,

I have also seen a need for queries that distinguish analyte level objects, within the new lab archetypes. The original reason was to be able to distribute pre-built panel templates (or even archetypes) to EMR (=PEP) locations in Brasil, but your need is generic.

This wiki page discusses the question; in this solution, you do create distinct archetype paths, and use normal queries. IN ADL2, this can be done with templtes, since templates are archetypes, and AQL works the same with them. The way to do it in ADL2 is shown by the examples here. If you load these archetypes you will see:

The point here is that you can just specialise the eixsting laboratory_test_analyte archetype into the specific analytes you want and then template the group to get a panel. On the basis that probably 100-200 analytes covers the vast majority of lab tests, I think this is sustainable.

I have not tried it in ADL1.4 / OET.

  • thomas

Thanks Thomas, that in fact seems to generate different nodeIDs for each analyte, thus avoids the querying issue.

BTW, to be generic is not a requirement on my side, just wanted to reuse what is published on the CKM, I can create specific archetypes per panel or analyte, but that approach seems to diverge from the editor’s modeling style. But my idea is the same as yours: try to distribute pre-built OPTs for specific panels.

I think I need to evaluate the cost of migrating to ADL2 since I see this as a blocker for 1.4 ADL and OPTs. Also I might need to adopt the workbench as modeling tools since there is no other tools available that can be installed easily or is open.

Thanks!

(attachments)

aiikmcihghimolnd.png
aiikmcihghimolnd.png

Thanks Thomas, that in fact seems to generate different nodeIDs for each analyte, thus avoids the querying issue.

right. The key is that it is done in specialisations - so the querying in the generic form based on the generic archetypes will still work, including with LOINC codes. I did not show how to include LOINC codes directly in the specialisations, but that could be done.

BTW, to be generic is not a requirement on my side, just wanted to reuse what is published on the CKM, I can create specific archetypes per panel or analyte, but that approach seems to diverge from the editor's modeling style. But my idea is the same as yours: try to distribute pre-built OPTs for specific panels.

I think I need to evaluate the cost of migrating to ADL2 since I see this as a blocker for 1.4 ADL and OPTs. Also I might need to adopt the workbench as modeling tools since there is no other tools available that can be installed easily or is open.

that will be a short term state of affairs - the new Archie tool can read all these archetypes, but the UI is rough for now (but probably good enough for a techie like you :wink:
Also, the soon-to-be-released Marand ADL-designer Mk2 will (I believe) have an ADL2 parser added at some stage, since it is AOM2 internally.

- thomas

This sort of thing simply feels wrong from a clinical point
of view.

Each of the test results deserves to stand on its own because
(as you show) it will need to be queried on its own.

It is only a matter of local convenience, and an arbitrary
decision, to group *display* of those under a panel.

IOW, the panel certainly is not a PRIMITIVE data type in the
domain concept model.

Panels are like folders. Whether to define inhabitants
thereof by LOINC, by arbitrary instance links, or by other
means, is an implementation detail.

Karsten

that is more or less the design concept of the current lab archetypes; I would just say that panels are not only a display concept, but also (usually) ordering-related. Regardless, any analyte can be displayed and queried on its own, in both the vanilla (generic) lab archetype model, or a variant that adds specific analyte specialisations as I have proposed.

openEHR data representation and querying are founded upon this fundamental principle - store how you like, query how you like.

- thomas

openEHR data representation and querying are founded upon this
fundamental principle - store how you like, query how you like.

OK, as long as "store how you like" does not impede
"query how you like", the principle seems reasonable.

Karsten

Solution is easy, just created specific structures for the results of some test that I needed to store and query so I have different node ids on each analyte. That will allow me to query, create some CDS rules and some fancy indicators for reports :slight_smile:

@Thomas I realized we have a similar issue with multiple occurrences of structured items.

For instance, an OPT:

CLUSTER 0..* at1234

  • ELEMENT at1235

  • ELEMENT at1236

Could have an instance:

CLUSTER at1234

  • ELEMENT at1235

  • ELEMENT at1236

CLUSTER at1234

  • ELEMENT at1235

  • ELEMENT at1236

Then querying for “SELECT … WHERE ../path_to_at1235/value > X AND …/path_to_1236/value = Y” will return data even if both ELEMENTs referenced by the paths are contained in different CLUSTER instances.

An AQL exercise would be how to get the CLUSTER which contains ELEMENTs that comply with conditions on more than one ELEMENT inside them and there are many occurrences of the same CLUSTER, so CLUSTER and children will have the same paths.

Not sure how to express that considering that depends on instances not on the model.

Maybe is something that should be handled by the CONTAINS operator? I believe it was Ian that said the CONTAINS should be evaluated against instances, not against the template. If that is the case, I think that will also solve the issue explained on my first message.

Any ideas?

Because archetypes and templates allow to use one or more instantiations depending on constraints, querying needs to be done on instantiations informed by the Template.

Gerard Freriks
+31 620347088
gfrer@luna.nl

Kattensingel 20
2801 CA Gouda
the Netherlands