0

I have custom Structure Definition based on Observation resource. Using HAPI for the validation. Is there a way to validate the value combination?

Ex:

"code": {
        "coding": [
            {
                "system": "http://loinc.org",
                "code": "76536-2",
                "display": "Mean Arterial Pressure, Cuff"
            }
        ]
    },

When this one is used, the unit of measure from the valueQuantity should have only corresponding values, not anything from the code valueset for unitofmeasure.

    "valueQuantity": {
      "value": 90,
      "unit": "mm Hg",
      "system": "http://unitsofmeasure.org",
      "code": "mm[Hg]"
    }

In other words, for Mean Arial Pressure LOINC code, valueQuantity.code should not allow kg, for example.

Kevin Rave
  • 13,876
  • 35
  • 109
  • 173
  • 1
    Side note - "mm Hg" is not a valid UCUM measure. What you actually need is "mm[Hg]". At present, there are two mechanisms. You can define an invariant that asserts constraints on Observation.value when Observation.code meets particular constraints, or you can leverage ObservationDefinition. However, the HAPI validator isn't yet set up to trigger against ObservationDefinition rules, so you'd have to add custom code to make that happen. – Lloyd McKenzie Sep 08 '21 at 19:48
  • You are right. I will update it. – Kevin Rave Sep 08 '21 at 19:52
  • @LloydMcKenzie Can you point me any documentation on ` invariant that asserts constraints on Observation.value` and `you can leverage ObservationDefinition`? – Kevin Rave Sep 08 '21 at 19:54
  • 1
    @nik Klassen provided an example of an invariant (though see my comment). ObservationDefinition is documented here: http://hl7.org/fhir/observationdefinition.html – Lloyd McKenzie Sep 09 '21 at 01:35

1 Answers1

1

I'm not a FHIRPath/clinical data expert but I think this should work for you

{
  "resourceType": "StructureDefinition",
  "url": "https://test.com/test",
  "type": "Observation",
  "status": "draft",
  "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Observation",
  "snapshot": {
    "element": [
      {
        "path": "Observation",
        "id": "Observation",
        "min": 0,
        "max": "*",
        "base": {
          "min": 0,
          "max": "*"
        },
        "constraint" : [{
          "severity" : "error",
          "expression": "code.coding.where(system = 'http://loinc.org' and code = '76536-2').exists() implies (value as Quantity).where(code='mm[Hg]' and system='http://unitsofmeasure.org').exists()"
        }]
      }
    ]
  }
}

The first part of the condition determines where you have an Observation with the appropriate code. If so it will require that your value has the right unit.

EDIT: To add some more information about what's going on here.

We are using a FHIRPath constraint to express this more complicated validation rule.

The .where(...) (docs) condition filters down a repeated/single field if it matches the condition, in this case that's the code/system combination that matches in LOINC code you care about.

.exists() (docs) returns true if the collection is non-empty.

implies (docs) evaluates the right-hand side condition only if the left-hand side is true.

And finally the (... as Quantity) operator (docs) is used to convert the value[x] field to a specific type, so more operations can be done on it.

Nik Klassen
  • 681
  • 8
  • 16
  • Do you have any documentation on this one? – Kevin Rave Sep 08 '21 at 21:43
  • 'unit' is a string. You'd want to constrain Quantity.code and system. That's where the computable values go. So replace ".unit" with ".where(code='mm[Hg' and system='http://unitsofmeasure.org')" – Lloyd McKenzie Sep 09 '21 at 01:29
  • Thanks for the suggestion Lloyd, I added that to the `expression`. I also added some information about the FHIRpath operators being used here. – Nik Klassen Sep 09 '21 at 12:59
  • Should this be added to Snapshot? Can this be done in differential? – Kevin Rave Sep 09 '21 at 17:02
  • I'm not familiar with the capabilities of HAPI. Server implementers aren't required to be able to understand a differential according to the spec, the Google Healthcare API (which I work on) only supports interpreting the snapshot field. If possible I would suggest you generate the StructureDefinition with tooling so you get both snapshot and differential filled in for you. – Nik Klassen Sep 09 '21 at 18:11
  • We use Google HealthCare API as well. But when creating a profile, we need to write differential, and thats where we generally put constraints. Is there a free tool that you have in mind that can be used to generate Snapshot / differential / profile? – Kevin Rave Sep 09 '21 at 18:46
  • Also, is there a way to specify OR condition. Because, there is going to be lot of combinations to check like the one you write above in `expression`. – Kevin Rave Sep 09 '21 at 19:03
  • Lloyd probably knows more about answering those questions. For more general advice I'd recommend reaching out on chat.fhir.org – Nik Klassen Sep 09 '21 at 19:30