SUSHI Tutorial

An end-to-end tutorial showing how to run SUSHI using a sample FSH project

FHIR Shorthand (FSH) is a specially-designed language for defining the content of FHIR Implementation Guides (IGs). It is simple and compact, with tools to produce Fast Healthcare Interoperability Resources (FHIR) profiles, extensions and IGs. FSH is compiled from text files to FHIR artifacts using SUSHI. To get started using FSH, you need to install and run SUSHI using the steps below.

Step 1: Review Introduction

If you haven’t done so already, please read or review the Introduction documentation to gain an understanding of the conventions used in this tutorial and the resources available to you.

Step 2: Install Node.js and Sushi

If you have not already installed SUSHI, follow the SUSHI Installation instructions.

Step 3: Download Sample FSH Project

To start with some working examples of FSH files and a skeleton FSH project, download the FSH Tutorial Starter and unzip it into a directory of your choice.

After the file is unzipped, you should see two subdirectories:

  • FishExample
  • FishExampleComplete

Change the working directory to FishExample. There is a sushi-config.yaml file, and two FSH files within the /input/fsh subdirectory:

  • FishPatient.fsh
  • Veterinarian.fsh

In addition, there are several files for building the IG.

Step 4: Run SUSHI

Now that you have SUSHI installed and a minimal FSH project, open up a command window, and navigate to the FishExample directory. Run SUSHI on those FSH files by executing:

 sushi build .

Running SUSHI will create a FishExample/fsh-generated directory, and populate it with the files needed to create the IG using the HL7 FHIR IG Publisher tool.

While running SUSHI, there will be a series of informational messages. When SUSHI completes, you should see a summary output similar this:

╔════════════════════════ SUSHI RESULTS ══════════════════════════╗
║ ╭───────────────┬──────────────┬──────────────┬───────────────╮ ║
║ │    Profiles   │  Extensions  │   Logicals   │   Resources   │ ║
║ ├───────────────┼──────────────┼──────────────┼───────────────┤ ║
║ │       2       │      0       │      0       │       0       │ ║
║ ╰───────────────┴──────────────┴──────────────┴───────────────╯ ║
║ ╭────────────────────┬───────────────────┬────────────────────╮ ║
║ │      ValueSets     │    CodeSystems    │     Instances      │ ║
║ ├────────────────────┼───────────────────┼────────────────────┤ ║
║ │         0          │         0         │         0          │ ║
║ ╰────────────────────┴───────────────────┴────────────────────╯ ║
║                                                                 ║
╠═════════════════════════════════════════════════════════════════╣
║ Fin-tastic job!                        0 Errors      0 Warnings ║
╚═════════════════════════════════════════════════════════════════╝

The files generated by SUSHI are located in the FishExample/fsh-generated directory. Check that the FishExample/fsh-generated/resources subdirectory contains two generated StructureDefinitions and a generated ImplementationGuide.

Step 5: Generate the Sample IG

At the command prompt, enter:

  _updatePublisher
  ./_updatePublisher.sh

This will download the latest version of the HL7 FHIR IG Publisher tool into ./input-cache. This step can be skipped if you already have run the command recently, and have the latest version of the IG Publisher tool.

Now run:

  _genonce
  ./_genonce.sh

This will run the HL7 FHIR IG generator, which may take several minutes to complete.

After the publisher is finished, open the file /FishExample/output/index.html to see the resulting IG.

If you click on the Artifacts Summary item in the menu, you will see that the IG contains two profiles, FishPatient and Veterinarian. If you look at each of them, you will notice that they have minimal differentials. The only way in which they differ from their base resource is that they require at least one name.

Step 6: Setting Cardinalities in a Profile

It is not widely known, but FHIR is designed to be used for veterinary medicine as well as human. For a non-human patient, we need to record the species. The Patients in this Tutorial are going to be various species of fish 🐟.

Since fish don’t get legally married (although some species do pair bond) and they don’t communicate in a human language, the first thing we’ll do in the FishPatient profile is eliminate these elements. To do this, open the file FishPatient.fsh in your favorite plain-text editor, and add the following rules after the last non-blank line in the file:

* maritalStatus 0..0
* communication 0..0

Note that rules start with *. FSH expresses cardinality as, {min}..{max}, the same as FHIR.

Step 7: Create a Species Extension for FishPatient

To specify the species of our aquatic patients, we’ll need an extension.

We have a choice of whether to make the extension inline or standalone. Inline extensions do not result in a separate StructureDefinition, and cannot be reused in other profiles. Standalone extensions are the opposite: they have independent StructureDefinitions, and can be reused. For this example, let’s make a standalone extension.

Extensions are created using the contains keyword. To add a standalone species extension, add the following rule after the cardinality rules:

* extension contains FishSpecies named species 0..1

This rule states that the extension array of the Patient resource will incorporate the FishSpecies extension with the local name species.

To define the FishSpecies extension, add the following lines to the end of the FishPatient.fsh file:

Extension:   FishSpecies
Id:          fish-species
Title:       "Fish Species"
Description: "The species of the fish."

Run SUSHI again (sushi build .). The count of Extensions should now be 1.

Step 8: Define a Value Set for Fish Species

The FishSpecies extension doesn’t quite do its job yet, because we haven’t specified what type of values it might accept. To add this information, enter these lines following the description of FishSpecies:

* value[x] only CodeableConcept
* valueCodeableConcept from FishSpeciesValueSet (extensible)

The first rule restricts the value[x] (a built-in element of every FHIR extension) to a CodeableConcept using the only keyword. The second binds it to a value set (yet to be defined) using the from keyword. The binding strength will be extensible, meaning the codes in the FishSpeciesValueSet must be used except when the value set is missing a specific fish species.

To define FishSpeciesValueSet, add the following lines to the same file:

ValueSet:    FishSpeciesValueSet
Title:       "Fish Species Value Set"
Id:          fish-species-value-set
Description: "Codes describing various species of fish, taken from SNOMED-CT."
* codes from system http://snomed.info/sct where concept is-a SCT#90580008  "Fish (organism)"

Run SUSHI again. The count of ValueSets should now be 1. Try generating the IG by running _genonce again. Open the file /FishExample/output/index.html to see the resulting IG.

  • Do you see where the FishPatient profile is in the IG?
  • Does the differential reflect your changes?
  • How does FHIR render the value set you defined?

Step 9: Define an Alias

An Alias is a way to define a shorthand for a URL or OID. For example, in the value set definition above, we could have defined an Alias to make referencing the http://snomed.info/sct URL easier, as shown below. Aliases are conventionally defined at the top of the file.

Add this line at the top of the FishPatient.fsh file:

Alias:   SCT = http://snomed.info/sct

and then replace the last line in the FishSpeciesValueSet with:

* codes from system SCT where concept is-a #90580008  "Fish (organism)"

Step 10: Create an Instance of FishPatient

Every IG should provide examples of its profiles. Let’s do that by introducing an example FishPatient named Shorty. Create this example instance using the Instance keyword, with InstanceOf set to FishPatient and Usage set to Example.

Include the following information about Shorty in the instance:

  • His given (first) name is “Shorty” and his family (last) name is “Koi-Fish”.
  • Shorty is a Koi fish (Cyprinus rubrofuscus), represented as SNOMED-CT code 47978005 “Carpiodes cyprinus (organism)”.

If you need help with this, you can reference the Defining Instances section of the specification. If you still need help, you can peek at the FSH files in the FishExampleComplete directory.

Run SUSHI again, and re-generate the IG.

  • Did it compile without errors?
  • What does the IG look like now?

Step 11: Extend the Veterinarian Profile

Now, add constraints and/or extensions to the Veterinarian profile:

  • Add qualifications consistent with a Veterinary practice. Qualifications are taken from code system http://nucc.org/provider-taxonomy, and the code is 174M00000X, for “Veterinarian”.

  • In addition, slice the identifier array, making a license number required. The code system is http://terminology.hl7.org/CodeSystem/v2-0203 and the code is LN, for “License number”.

If you need help with this, you can refer to the assignment rules and slicing rules sections of the specification. If you still need help, you can peek at the FSH files in the FishExampleComplete directory.

Run SUSHI again, and re-generate the IG.

  • Did it compile without errors?
  • What does the IG look like now?

Congratulations! You’ve completed the FSH tutorial. It might be time to feast on some sushi!


Last modified September 17, 2024: Add tutorial files (#100) (814b403)