FSH Seminar
0.1.0 - ci-build

Publish Box goes here

Part 1: Reading an IG

The goal of this module is to describe why you might want to create a FHIR IG, what a FHIR IG is, and how to read one. To do this, we will cover some foundational concepts in the abstract, and then see how these concepts are implemented in a completed IG.

Why author a FHIR IG?

The base FHIR specification is purposefully incomplete. While it defines the critical, generalizable elements needed for a FHIR implementation, such as the syntax and the base FHIR resources, it leaves the use case-specific implementation details undefined.

Pie chart showing what is and isn't covered by the base FHIR specification.

FHIR Implementation Guides (IGs) fill in these gaps in different ways depending on the specific needs.

Grahame Grieve, the FHIR Product Director, breaks down the purpose of FHIR IGs into four broad categories in this presentation:

  1. National Base IGs

    Doesn’t describe a full implementation; instead, describes how regulations for a national health infrastructure apply in the context of FHIR. Typically this involves the code systems, identifiers, and extensions necessary for regulation (e.g., race and ethnicity in the US; or Australian indigenous status) specific to the jurisdiction in question.

    (Typically these should not contain constraints like requiring presence of a specific element or MustSupport, which are more suitable for IGs satisfying one of the other purposes below.)

    Examples: US Core, AU Base

  2. Domain of Knowledge IGs

    Describes how to represent a clinical or business concept, without defining an API for exchanging these data.

    Example: International Patient Summary, mCODE

  3. Community of Implementation

    An agreement on how data are exchanged by a group of actors (i.e., contains an API).

    Example: mCODE, US Core

  4. Product IGs

    Documents what a specific piece of software does in the FHIR ecosystem. These are not published by HL7, but may be published by vendors to document their own software. Often are not public.

Some IGs fulfill multiple purposes, which is generally ok as long as the implications are considered carefully. For example, in the case of National Base IGs, a multi-purpose may be problematic: for example, in US Core, implementers may want to inherit the National Base IG content and not the Community of Implementation content, the latter of which includes US Core’s cardinality/MustSupport constraints.

The content in this course is to some degree focused around the reading and writing of Domain of Knowledge IGs, and to a lesser extent Community of Implementation1, though many parts of the course are applicable to all.

What is a FHIR IG?

Now that we have established the broad purpose for creating a FHIR IG, we will more formally define the contents of an IG.

In short, FHIR Implementation Guides (IGs) are:

A set of rules of how a particular interoperability or standards problem is solved 2

To define these rules, IGs include:

  1. Computable rules
  2. Human-readable versions of the computable rules
  3. Additional narrative descriptions of the rules, and additional information about the problem the IG is trying to solve

The high-level goal of an IG is to provide sufficiently detailed instructions to implementers so that they can independently set up systems that will be able to successfully communicate with each other.

To meet this goal, the computable rules are often insufficient. IGs usually include a significant amount of narrative content to supplement the computable rules, which may describe:

  1. The primary use cases that are in the scope of the IG
  2. The actors, and how the actors are expected to interact
  3. How the components of the IG can be used together to meet the needs of these actors for these use cases
  4. Conformance criteria that are not able to be represented in the computable portion of the IG

Conformance

Implementations are said to conform to an IG if they abide by both the computable and narrative rules in the IG.

The computable portions of an IG can be used for automated testing for conformance. For example:

Narrative conformance criteria typically use RFC 2119 key words in all-caps like MUST, SHOULD, and MAY. This signals to implementers which specific parts of the narrative should be treated as conformance criteria. Because narrative conformance criteria can’t usually be assessed algorithmically, the IG authors must take care to make sure the narrative content clearly provides the necessary information to implementers.

Reading an IG

  1. First, start by reading the narrative content.

    Start by reading the narrative on the home page. If other narrative pages are prominently mentioned or linked to from the home page, read them as well.

  2. Then, examine the computable content.

    Several different types of computable content are contained within a typical IG (these are described below). Where you start depends on your goal.

    For example, if you are interested in gaining a general understanding of an IG, you may want to review all the computable content superficially (which can be done by clicking each link on the artifacts.html page of the IG).

    Alternatively, you may be interested in an implementation for a specific actor or use case. In this case, the IG will hopefully provide some guidance on which resources are most important. If not, for content-related use cases, Profiles are likely the best entry point to the computable content. For API-driven use cases, CapabilityStatements are a logical starting point.

The next few sections will provide an overview of common types of computable artifacts.

Common Computable Artifacts: Profiles

The goal of a FHIR profile is to take one of the base FHIR resources and add computable rules on top of it. These rules come in two flavors:

  1. Constraints that apply to an entire element, such as how many times a given element can appear or which terminology to use for a code
  2. Constraints that apply to specified splits or parts of an element3

To make this more concrete, let’s look at an example instance of a base FHIR resource – in this case, Patient. This instance is the package of data a FHIR server might use to represent a specific patient. For example, if you wanted to retrieve the data for the patient with the medical record number 1032702, you could query https://hospital.example.org/fhir/Patient/1032702. The response to this query would be the instance of the Patient resource describing this patient, which might look like this:

{
  "resourceType": "Patient",                                                      // Resource identity and metadata
  "id": "PatientExample",
  "meta": {
    "profile": [
      "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient"
    ]
  },
  "extension": [                                                                  // Extension
    {
      "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex",
      "valueCode": "F"
    }
  ],
  "identifier": [                                                                 // Standard data
    {
      "use": "usual",
      "type": {
        "coding": [
          {
            "code": "MR",
            "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
            "display": "Medical Record Number"
          }
        ],
        "text": "Medical Record Number"
      },
      "system": "http://hospital.smarthealthit.org",
      "value": "1032702"
    }
  ],
  "active": true,
  "name": [
    {
      "family": "Shaw",
      "given": [
        "Amy",
        "V."
      ]
    }
  ],
  "telecom": [
    {
      "system": "phone",
      "value": "555-555-5555",
      "use": "home"
    },
    {
      "system": "email",
      "value": "amy.shaw@example.com"
    }
  ],
  "gender": "female",
  "birthDate": "1987-02-20",
  "address": [
    {
      "line": [
        "49 Meadow St",
        "Apartment B"
      ],
      "city": "Mounds",
      "state": "OK",
      "postalCode": "74047",
      "country": "US",
      "period": {
        "start": "2016-12-06",
        "end": "2020-07-22"
      }
    }
  ]
}

The fields under “Standard data” in the example above are often called “elements” in an instance of a FHIR resource, as are extensions and slices. For example, the element gender has the value female in the example above. Elements may be nested (like address.city, which has the value Mounds), have multiple values (like address.line), or refer to a specific code from a terminology (like extension[us-core-birthsex].valueCode).

When evaluating an instance for conformance, the computable rules specified in the base FHIR resource and any applicable profiles are applied across the elements in the instance. In this case, the instance must conform to the rules specified in FHIR’s specification for the Patient resource – or it wouldn’t be an instance of Patient at all.

Additionally, if a resource instance follows the rules defined by a FHIR profile (and any applicable general conformance criteria from the profile’s IG), then the instance is said to “conform” to the profile. A single instance may even conform to multiple profiles simultaneously.4

A note on FHIR jargon. The FHIR spec defines a number of resources, which are information models that are the building blocks of FHIR implementations. FHIR servers create an instance of a given resource (i.e., an instance of the Patient resource representing a specific patient). It is this instance that may conform to a given FHIR profile, not the resource itself. But in casual conversation, you may hear that “resource X conforms to profile Y” – this really means “resource instance X conforms to profile Y”, but saying “resource instance” is cumbersome.

You may also here “resource” used to refer to the FHIR specification’s definition of a resource: e.g., “name is an element of the Patient resource” refers to the name element in the FHIR spec’s definition of the Patient resource.

Each profile has its own page in an IG build, and this is where you can find the conformance rules specified by that profile. Here’s an example of a profile page in an IG. The next part of the course will talk about how these pages are generated.


Below is an annotated screenshot showing some of the key components of profiles in an IG:

  1. The Content tab is the entry point to the profile, and contains the majority of the key information you’ll need to understand the profile.
  2. The Detailed Descriptions tab lists all the information for each element in the resource being profiled.
  3. The Examples tab lists example instances provided by the authors that conform to the profile.
  4. The XML, JSON, and (optionally) TTL tabs show the computable version of the profile in the respective format. (TTL stands for Turtle format, which is not widely used.)
  5. The yellow box at the top of the page indicates which version of the IG you are viewing. This is important so you can tell if you are on the most up-to-date published version of an IG – sometimes Google searches or other links will land you on an old version.
  6. This section contains profile metadata including the defining URL, computable Name, human-readable Title, and the narrative Definition.
  7. Under the profile metadata is the narrative portion of the profile.
  8. Finally, the formal views of profile content appears at the bottom of the page. This is the human-readable version of the computable version of the profile. We will discuss this in detail below.

Formal View of Profile Content Tabs

  1. Text Summary provides a brief auto-generated narrative description of the profile.
  2. Differential Table shows only the rules added by this specific profile. In other words, it compares the Profile you are viewing to its parent (either a base FHIR resource or another profile).
  3. Snapshot Table shows all the rules contained in the profile, including rules inherited from its parents.
  4. Snapshot Table (Must Support) is the subset of the elements on the previous tab with a MustSupport flag. This is described later.

Typically the differential (“diff”) table tab is the best place to start when trying to understand what a rules a profile is setting. Here’s the diff table from the example of profile linked above:

Screenshot of diff table from the example profile

This shows that this profile adds two constrains: the addition of MustSupport flags for the root Patient element (indicating that the entire profile is MustSupport to implementers ), and Patient.deceased[x]. The meaning of MustSupport and the full set of possible element-level constraints are discussed in the next part of the course.

The snapshot table tab is typically the best way to see all elements that may/should/must be populated for an instance of a resource to conform. This table is too long in the example profile to reproduce as a screenshot, but you can see it here.

The table tabs have a high amount of information density:

Annotated screenshot of the snapshot table from the example profile

The next part of the course will cover the constrains in the table tabs in more detail. In the meantime, you can click on the headings in the example profile to go to the relevant parts of the FHIR spec.

Common Computable Artifacts: Terminology

FHIR IGs can define two terminology-related artifacts:

  1. Code systems define a universe of predefined codes that may be used to represent data. ICD-10 is one of the most well-known code systems, but there are many others. If no existing code system meets a given use case, a custom one can be defined within an IG.5
  2. Value sets define a subset of a code system that is relevant for a given element. There are two methods for defining value sets: intensionally or extensionally. Intensional value sets are algorithmically defined, while extensional value sets have an enumerated list of codes. These two methods can be combined or used separately.

Other Computable Artifacts

There are many more artifacts that can be defined by IGs. These will be enumerated in Part 4.

Reviewing an Example IG

To see a practical application of the concepts discussed above, we will review portions of the minimal Common Oncology Data Elements (mCODE) Implementation Guide (specifically the STU2 version), which is primarily a Domain of Knowledge IG but also has some Community of Implementation content:6

  • Home page: This is the entry point to the IG, and typically describes the background, scope, and general structure of the IG. Ideally the home page of an IG should be the single point of entry for all key content: by following links in the navigation bar or in the narrative of the home page, all the key IG content should be easily accessible.

    The IG home page should also help guide the reader through the key content within the IG. Some IGs do a better job of this than others, and if the authors’ intent is not clear for a given IG you can fall back onto some standard navigation pages (discussed below).

    The key information on the mCODE home page is related to the Content by Group pages (see next bullet point), and the diagram showing the structure of mCODE STU2.

    mCODE’s home page also links to some other key concepts and resources specific to this IG, including the Data Dictionary, development history, credits, and author contact information.

  • “Content by Group” pages: Section 1.2 of the home page links to the different groups of profiles and other artifacts in the IG. Not all IGs have this structure (and many IGs don’t have as many artifacts as the mCODE IG, making this kind of structure is unnecessary).

    Following the pattern described above of reading prominently linked narrative content before diving into the individual IG artifacts, consider reviewing these pages next after finishing the content on the home page.

    Note that the Content by Group Pages are also linked second in the navigation bar, another indication of their level of importance.

  • Conformance pages: These appear third in the navigation bar, and are custom-written narrative pages specifically for the mCODE IG, broken into four sections by topic.

    Reviewing the details of these is beyond the scope of this course, and not all IGs include this much information on conformance. However, one common item that you should be looking for is how the IG defines MustSupport, as this is a key conformance concept and is not defined in the base FHIR specification, but is instead left to profile authors to define

  • FHIR Artifacts: The fourth item in the navigation bar lists the various types of FHIR artifacts. These are custom pages made specifically for mCODE (except for “Complete Listing”; this is described below).

    Note that you likely have come across all the key artifacts as these are also listed at the bottom of each “Content by Group” page.

  • Standard navigation pages Every IG has an artifacts.html page, so if you find the IG’s approach to organizing artifacts in the narrative confusing, you can always open that page to see a comprehensive list of all artifacts. Here’s that page for mCODE (found at FHIR Artifacts > Complete Listing in the nav bar).

    IGs also have a table of contents page (toc.html) that you can use to see a full list of all the web pages in the IG. Here’s that page for mCODE.

Now that we (hopefully) understand the overall purpose of the IG and the general conformance criteria, let’s look in detail at one of the key profiles in the IG: Primary Cancer Condition.

This information tells me as an implementer what sort of data and terminology I’ll need to have available to create conforming instances of Condition.

This is the first pass of the process needed to understand each profile in the IG. Depending on the use case, other resources may also need to be reviewed in detail.


Now that we’ve seen how to read an IG, in the next part of the course we will look at how to create an IG from scratch.

  1. We do not spend much time on the portion of FHIR IGs related to APIs, which are typically targeted at software engineers. 

  2. https://www.hl7.org/fhir/implementationguide.html 

  3. These come in two flavors: slices (constraints on the parts of an element can hold multiple values) and extensions (constraints on an extension or modifierExtension element, which counter-intuitively use constraints to extend functionality). We will cover these in more detail later in the course. 

  4. Resource instances can actually specify which profiles they intend to conform to using the meta.profile metadata element. But instances may also unintentionally conform to many profiles – this is actually beneficial to interoperability as in some cases, a FHIR server’s default response may already conform to a given profile if that profile is relatively unconstrained. 

  5. Defining your own code system is generally only a good idea as a last resort. From the implementer’s perspective, it is generally more burdensome to add support for a brand new code system vs. using a more common code system that might already be part of an implementation. 

  6. STU refers to Standard for Trial Use, which is a HL7 ballot level indicating the maturity of the implementation guide. This is the most recent balloted version of mCODE as of writing. More information about the HL7 ballot process can be found here