Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 15 Next »

The HSPC Sandbox is taking steps toward supporting FHIR profile storage, retrieval and validation.  Along with this effort comes the storage/hosting of the terminology necessary to accommodate the profiling features.  In this blog post I will outline the upcoming features related to profiles, along with some examples of how these features can be useful in the development of SMART on FHIR apps.  The efforts are currently focused on support for FHIR STU3, and all examples and documentation are using this FHIR version. 

Each example request on this page can be made using the client of your choice (curl, Postmaninsomnia are a few good ones). If you're using postman, you can download all example calls as a collection here: HSPC Reference API - Validation.postman_collection.json.

This post covers the following:

HSPC Sandbox as a FHIR Terminology Service

Terminology is at the heart of all FHIR resources.  Because of this, we've dedicated a sandbox in the HSPC Sandbox Reference API to the storage and retrieval of terminology. This sandbox conforms the FHIR specification of a Terminology Service, and can be used by clients to "...make use of codes and value sets without having to become experts in the fine details of code system, value set and concept map resources, and the underlying code systems and terminological principles." (source).  The HSPC Sandbox Terminology Service contains more than 631,310 concepts and relationships, broken down as follows:

  • SNOMED CT International RF2 (336,893 concepts)
  • LOINC 1.61 (111,803 concepts)
  • HL7 v2 & HL7 v3 codes backing FHIR v3.0.1

These concepts are surfaced through the ValueSet (1,176 instances) and CodeSystem (942 resources) resources, which are then referenced by StructureDefinition (346) resources, defining the data structure of base FHIR resources along with all profiled resources.

At the time of this blog post, the latest version of the HSPC FHIR Terminology Service is available at the following URL:

https://api-v5-stu3.hspconsortium.org/stu3/open

All examples use this base URL.

Use Cases

ValueSet Expansion

It's possible to list all members of a particular value set using the $expand operation.  To illustrate this, let's take a very simple value set defined by http://hl7.org/fhir/administrative-gender.  This is the Administrative Gender value set used to define the gender of the base FHIR Patient resource.  The resource itself is available making the following call:

GET https://api-v5-stu3.hspconsortium.org/stu/open/ValueSet/administrative-gender

Response:

{
    "resourceType": "ValueSet",
    "id": "administrative-gender",
    "meta": {
        "versionId": "1",
        "lastUpdated": "2017-11-07T09:55:13.000+00:00",
        "profile": [
            "http://hl7.org/fhir/StructureDefinition/shareablevalueset"
        ]
    },
    "extension": [
        {
            "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-ballot-status",
            "valueString": "Informative"
        },
        {
            "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm",
            "valueInteger": 5
        },
        {
            "url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg",
            "valueCode": "pc"
        }
    ],
    "url": "http://hl7.org/fhir/ValueSet/administrative-gender",
    "identifier": [
        {
            "system": "urn:ietf:rfc:3986",
            "value": "urn:oid:2.16.840.1.113883.4.642.3.1"
        }
    ],
    "version": "3.0.1",
    "name": "AdministrativeGender",
    "status": "draft",
    "experimental": false,
    "date": "2017-04-17T17:38:22-04:00",
    "publisher": "HL7 (FHIR Project)",
    "contact": [
        {
            "telecom": [
                {
                    "system": "url",
                    "value": "http://hl7.org/fhir"
                },
                {
                    "system": "email",
                    "value": "fhir@lists.hl7.org"
                }
            ]
        }
    ],
    "description": "The gender of a person used for administrative purposes.",
    "immutable": true,
    "compose": {
        "include": [
            {
                "system": "http://hl7.org/fhir/administrative-gender"
            }
        ]
    }
}

Notice that we get the definition of the value set, but not the actual members of the value set.  To get those, we can use the $expand operator:

GET https://api-v5-stu3.hspconsortium.org/stu3/open/ValueSet/administrative-gender/$expand

Response:

{
    "resourceType": "ValueSet",
    "status": "active",
    "compose": {
        "include": [
            {
                "system": "http://hl7.org/fhir/administrative-gender"
            }
        ]
    },
    "expansion": {
        "identifier": "urn:uuid:67a687d3-5169-4f0c-ad8e-d0a9d32699a9",
        "timestamp": "2017-11-10T21:04:12+00:00",
        "total": 4,
        "parameter": [
            {
                "name": "version",
                "valueUri": "http://hl7.org/fhir/administrative-gender|3.0.1"
            }
        ],
        "contains": [
            {
                "system": "http://hl7.org/fhir/administrative-gender",
                "code": "male",
                "display": "Male"
            },
            {
                "system": "http://hl7.org/fhir/administrative-gender",
                "code": "female",
                "display": "Female"
            },
            {
                "system": "http://hl7.org/fhir/administrative-gender",
                "code": "other",
                "display": "Other"
            },
            {
                "system": "http://hl7.org/fhir/administrative-gender",
                "code": "unknown",
                "display": "Unknown"
            }
        ]
    }
}

This expand operation is useful in a variety of contexts, namely:

  • Populating a drop-down list
  • Implementing code completion
  • Check if a code is valid for a particular context

You can read more about the $expand operation here.

ValueSet Validation

Another useful operation on the ValueSet resource is $validate-code.  This allows you to ask, in a single call, if a particular code is part of a given value set.  This can save some client side logic and bandwidth when developing apps.  Using the same value set as above, we can check if female is a valid code with the following command.

GET https://api-v5-stu3.hspconsortium.org/stu3/open/ValueSet/administrative-gender/$validate-code?code=female

Response:

{
    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "result",
            "valueBoolean": true
        },
        {
            "name": "message",
            "valueString": "Validation succeeded"
        },
        {
            "name": "display",
            "valueString": "Female"
        }
    ]
}

Likewise, we can see that incorrect not a member of the value set by making a similar request:

https://api-v5-stu3.hspconsortium.org/stu3/open/ValueSet/administrative-gender/$validate-code?code=incorrect

Response:

{
    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "result",
            "valueBoolean": false
        },
        {
            "name": "message",
            "valueString": "Code not found"
        }
    ]
}

You can read more about the $validate-code operation here.

Code lookup

Another useful task when developing apps is retrieving details about a particular code. Say you have access to the code value, but not the display value.  To look up the display you can make the request:

GET https://api-v5-stu3.hspconsortium.org/stu3/open/CodeSystem/$lookup?code=female&system=http://hl7.org/fhir/administrative-gender

Response:

{
    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "name",
            "valueString": "Unknown"
        },
        {
            "name": "display",
            "valueString": "Female"
        },
        {
            "name": "abstract",
            "valueBoolean": false
        }
    ]
}

You can see that the result of the call contains a display value we can use when surfacing this code to the end user.

You can read more about the $lookup operation here.

Advanced Use Cases

In addition to the basic use cases we've walked through above, the FHIR spec outlines several advanced features such as subsumption testing, batch validation and translations.  As work progresses on the HSPC Terminology Service we will provide documentation on how to use these, in the meantime you can read about them here.

Resource Validation & Profiles

Profiling is a broad term in FHIR, but generally it is the process adding additional restrictions to base FHIR resources.  These additional restrictions often include restricting properties to a particular value set or making properties required (editing cardinality). This type of profiling can increase interopability and is encouraged in the FHIR ecosystem. 

These profile specifications are expressed using the StructureDefinition resource, providing a machine readable interpretation of the profiled resource.  All base FHIR profiles have a corresponding StructureDefinition resource and the FHIR spec also defines profiled versions of some resources to accomodate common use-cases.  Further, it's common for organizations to partner in creating their own StructureDefinitions which expand on the base FHIR defintions in order to accomodate the sharing of data around a particular domain.

The HSPC Terminology Service contains all base FHIR StructureDefinition resources (205) and we are working on support for FPAR profiled resources (141).  The FPAR resources are stored in the HSPC Terminology Service, however some value set data is incomplete at this time. 

Use Cases

This StructureDefinition information is utilized by the server to implement validation functionality. This is exposed with the $validate operation which can be performed at the resource instance level.  Validation uses the HL7 "InstanceValidator", which is able to check a resource for conformance to FHIR profiles (StructureDefinitions, ValueSets, and CodeSystems), including validating fields, extensions, and codes for conformance to their given ValueSets.

Validating a FHIR Resource

Let's use the validation functionality to validate a base FHIR Patient resource, based on the basic patient example in the FHIR docs.  The request would look like this:

POST https://api-v5-stu3.hspconsortium.org/stu3/open/Patient/$validate
--- REQUEST BODY ---
{
  "resourceType": "Patient",
  "identifier": [
    {
      "use": "usual",
      "type": {
        "coding": [
          {
            "system": "http://hl7.org/fhir/v2/0203",
            "code": "MR"
          }
        ]
      },
      "system": "urn:oid:1.2.36.146.595.217.0.1",
      "value": "12345",
      "period": {
        "start": "2001-05-06"
      },
      "assigner": {
        "display": "Acme Healthcare"
      }
    }
  ],
  "active": true,
  "name": [
    {
      "use": "official",
      "family": "Chalmers",
      "given": [
        "Peter",
        "James"
      ]
    },
    {
      "use": "usual",
      "given": [
        "Jim"
      ]
    },
    {
      "use": "maiden",
      "family": "Windsor",
      "given": [
        "Peter",
        "James"
      ],
      "period": {
        "end": "2002"
      }
    }
  ]
}

Response:

{
    "resourceType": "OperationOutcome",
    "text": {
        "status": "generated",
        "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h1>Operation Outcome</h1><table border=\"0\"><tr><td style=\"font-weight: bold;\">INFORMATION</td><td>[]</td><td><pre>No issues detected during validation</pre></td>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t</tr>\n\t\t</table>\n\t</div>"
    },
    "issue": [
        {
            "severity": "information",
            "code": "informational",
            "diagnostics": "No issues detected during validation"
        }
    ]
}

The response to our request is an OperationOutcome containing the results of the validation.  In the above instance, no issues were detected. 

This operation can be useful in ensuring that no data is lost in the creation of the resource.  If we were to add a field which isn't defined on the server (not contained in the StructureDefinition), it is acceptable behavior for the server to discard this field and save the remiander of the data. To avoid this, your application can call the validate endpoint before each save or update if there is any doubt about the data integrity. 

Let's show an example that does just this, adds a field the server isn't prepared to handle:

POST https://api-v5-stu3.hspconsortium.org/stu3/open/Patient/$validate
--- REQUEST BODY ---
{
  "resourceType": "Patient",
  "incorrect": "field",
  "identifier": [
    {
      "use": "usual",
      "type": {
        "coding": [
          {
            "system": "http://hl7.org/fhir/v2/0203",
            "code": "MR"
          }
        ]
      },
      "system": "urn:oid:1.2.36.146.595.217.0.1",
      "value": "12345",
      "period": {
        "start": "2001-05-06"
      },
      "assigner": {
        "display": "Acme Healthcare"
      }
    }
  ],
  "active": true,
  "name": [
    {
      "use": "official",
      "family": "Chalmers",
      "given": [
        "Peter",
        "James"
      ]
    },
    {
      "use": "usual",
      "given": [
        "Jim"
      ]
    },
    {
      "use": "maiden",
      "family": "Windsor",
      "given": [
        "Peter",
        "James"
      ],
      "period": {
        "end": "2002"
      }
    }
  ]
}

Response:

{
    "resourceType": "OperationOutcome",
    "text": {
        "status": "generated",
        "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h1>Operation Outcome</h1><table border=\"0\"><tr><td style=\"font-weight: bold;\">ERROR</td><td>[/Patient]</td><td><pre>Unrecognised property '@incorrect'</pre></td>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t</tr>\n\t\t</table>\n\t</div>"
    },
    "issue": [
        {
            "severity": "error",
            "code": "processing",
            "diagnostics": "Unrecognised property '@incorrect'",
            "location": [
                "/Patient"
            ]
        }
    ]
}

The result contains an error, indicating the presence of the unknown property 'incorrect'.

A slightly more advanced use of the $validate operation would be to verify that property values are a member of the correct value set.  Let's return to using our example value set, administrative-gender.  The FHIR Patient resource specifies that the Patient.gender field MUST be one of the values in this value set. Let's post a validation request containing the value "incorrect" for gender and see what happens.

POST https://api-v5-stu3.hspconsortium.org/stu3/open/Patient/$validate
--- REQUEST BODY ---
{
  "resourceType": "Patient",
  "gender": "incorrect",
  "identifier": [
    {
      "use": "usual",
      "type": {
        "coding": [
          {
            "system": "http://hl7.org/fhir/v2/0203",
            "code": "MR"
          }
        ]
      },
      "system": "urn:oid:1.2.36.146.595.217.0.1",
      "value": "12345",
      "period": {
        "start": "2001-05-06"
      },
      "assigner": {
        "display": "Acme Healthcare"
      }
    }
  ],
  "active": true,
  "name": [
    {
      "use": "official",
      "family": "Chalmers",
      "given": [
        "Peter",
        "James"
      ]
    },
    {
      "use": "usual",
      "given": [
        "Jim"
      ]
    },
    {
      "use": "maiden",
      "family": "Windsor",
      "given": [
        "Peter",
        "James"
      ],
      "period": {
        "end": "2002"
      }
    }
  ]
}

Response:

{
    "resourceType": "OperationOutcome",
    "text": {
        "status": "generated",
        "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h1>Operation Outcome</h1><table border=\"0\"><tr><td style=\"font-weight: bold;\">ERROR</td><td>[]</td><td><pre>Failed to parse request body as JSON resource. Error was: Invalid attribute value "incorrect": Unknown AdministrativeGender code 'incorrect'</pre></td>\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t</tr>\n\t\t</table>\n\t</div>"
    },
    "issue": [
        {
            "severity": "error",
            "code": "processing",
            "diagnostics": "Failed to parse request body as JSON resource. Error was: Invalid attribute value \"incorrect\": Unknown AdministrativeGender code 'incorrect'"
        }
    ]
}

The validation result informs us that 'incorrect' is not a code in the defined value set AdministrativeGender.  

You can read more about the $validate operator as well as validation in general here.

Querying StructureDefinition Resources

If you are interested in examining the StructureDefinition which defines certain profiles, you can do so by accessing the /StructureDefinition endpoint directly.  For example, the following request retrieves the FPAR profiled patient resource:

GET https://api-v5-stu3.hspconsortium.org/stu3/open/StructureDefinition/fparpatient

Response: (omitted due to size)

In the near future we will support more advanced interactions for profiled resources.

Conclusion

This sums up our first steps towards supporting terminology and profiling on the HSPC Sandbox.  In the future we hope to support and document use-cases such as profile-specific validation (us-core, hspc, fpar, etc) as well as add more terminology sets to our collection.



  • No labels