SUSHI Tutorial
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.
Tip
If you find this helpful, you may also want to look at our self-service FSH Seminar course, which includes a more extensive walkthrough of using SUSHI and FSH.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 .
Note
The dot (.) represents “this directory,” the location of the FSH files. You can also specify the location explicitly by replacing the dot with a directory path.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.
Tip
If you are blocked by a firewall, or if for any reason_updatePublisher
fails to execute, download the current IG Publisher jar file here. When the file has downloaded, move it into the directory /FishExample/input-cache (creating the directory if necessary).
Warning
Before proceeding to the next command: If you have never run the IG Publisher, you may need to install Jekyll first. See Installing the IG Publisher for details.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."
Tip
FSH ignores extra whitespace, so authors can choose to use whitespace for improved visual alignment, as in the extension definition above.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)"
Info
The rule in the value set definition above selects all codes from SNOMED-CT that are children of the concept “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)"
Tip
Using aliases has no effect on the IG; it simply makes the FSH code a bit neater.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 is174M00000X
, for “Veterinarian”. -
In addition, slice the
identifier
array, making a license number required. The code system ishttp://terminology.hl7.org/CodeSystem/v2-0203
and the code isLN
, 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!