Receive patient data from general practitioners

This page contains step by step exercises that are part of the Let's Build! Building a FHIR data model with Forge at DevDays 2022 June.

Following these exercises will learn you how to start profiling, the art of defining your FHIR data model, with Forge.

After completing this tutorial, you will be able to:

  • Create FHIR profiles, derived profiles and extensions with Forge
  • Model data properties like cardinalities and data types
  • Create profile references
  • Adjust terminology bindings
  • Slice lists of data elements
  • Publish FHIR resources to Simplifier.net
  • Validate your work

  • A free Simpifier.net account (sign up here)
  • Forge for FHIR R4 (free for non-commercial use, download here)
  • If you’re on Windows: Double-click the installer and follow the process
  • If you’re on Mac or Linux: While Forge originally wasn’t built for these platforms, you can run Forge in a virtual machine with Windows or, in some case, with Wine.
  • Step 1: Basic Profiling 🔥

      Hospital X wants to receive patient data from general practitioners. The hospital has decided to build an interface conform the FHIR standard, starting with administrative data of patients. The following requirements are specified by Hosptial X:

    • A patient has at least 1 name, and each name has at least 1 family name and 1 given name.
    • Date of birth and gender are mandatory.
    • A photo should not be allowed to be added.
    • The hospital can only capture if a patient is deceased or not, not the actual dateTime.

    Steps to follow

    1. Create a new folder on your computer for this tutorial FHIR project.
    2. Start Forge and open the profile folder you just made.
    3. Create a new profile. Take a look at the FHIR resource list. In Forge, choose the resource that is the best fit for exchanging administrative patient data.
    4. Provide high-level metadata in the 'Properties' tab within Forge. Give it at least a name and a unique URL also named canonical, for example based on your name and country: 'http://[yourname].[yourcountrycode]/fhir/StructureDefinition/HospitalXPatient'. For me that will be: http://ardon.nl/fhir/StructureDefinition/HospitalXPatient.
    5. Set the constraints according to the requirements of Hospital X in the 'Element Tree' view of Forge.
    Differential view of 'Hospital X Patient Step 1'
    identifierΣ0..*Identifier
    activeΣ ?!0..1boolean
    useΣ ?!0..1codeBinding
    textΣ0..1string
    familyΣ1..1string
    givenΣ1..*string
    prefixΣ0..*string
    suffixΣ0..*string
    periodΣ I0..1Period
    telecomΣ I0..*ContactPoint
    genderΣ1..1codeBinding
    birthDateΣ1..1date
    deceasedBooleanboolean
    addressΣ0..*Address
    maritalStatus0..1CodeableConceptBinding
    multipleBirthBooleanboolean
    multipleBirthIntegerinteger
    photoI0..0Attachment
    relationship0..*CodeableConceptBinding
    name0..1HumanName
    telecomI0..*ContactPoint
    address0..1Address
    gender0..1codeBinding
    organizationI0..1Reference(Organization)
    periodI0..1Period
    language1..1CodeableConceptBinding
    preferred0..1boolean
    generalPractitionerI0..*Reference(Organization | Practitioner | PractitionerRole)
    managingOrganizationΣ I0..1Reference(Organization)
    otherΣ I1..1Reference(Patient | RelatedPerson)
    typeΣ1..1codeBinding

    Step 2: Extensions ➕

      Hospital X wants to capture additional data on the patient, which is not represented in the base resource. The following (additional) requirements are specified:

    • Place of birth is mandatory.
    • Optional information on inclusion in one or more clinical studies.

    Steps to follow

    Simple extension
    1. Find a relevant extension for place of birth. You can, for example, search in the FHIR Registry, Simplifier.net or the list of extensions in the core FHIR specification.

    2. Found one?

      • Download the extension as XML or JSON and save it in your project folder. You need to refresh the folder in Forge to see it.
      • Or... if you know which package contains the desired FHIR resource installing the package may even be more straightforward.
        • In Forge: go to the dependencies tab
        • Go to Simplifier icon
        • Search for hl7.fhir.r4.core
        • Install version 4.0.1 by selecting it and clicking on ‘Add’
    3. Add the extension to the patient profile, provide an appropriate extension slice name and make it mandatory.

    Complex extension

    Note: This does not concern a real-world example (instead of an extension, the ResearchSubject resource could be used). Creating this extension solely demonstrates how a (complex) extension can be created.

    1. Create a new extension for clinical study inclusion by selecting the profiling folder in Forge and clicking 'New Extension'. Select 'Extension definition' in the left menu and use the 'profiles-types.xml' in the new screen that pops up.
    2. The extension needs a canonical URL as well, and it needs to contain the context where this extension is allowed to be used. You can set this in the 'Properties' tab of the extension. (Context Type = 'fhirpath' and Context Expression = 'Patient')
    3. Add three elements: clinical trial number (Identifier), period of involvement (Period), and inclusion status (CodeableConcept).
    4. Add the extension to your patient profile.
    Differential view of 'Hospital X Patient Step 2'
    birthPlace1..Extension(Address)
    inclusionStatusExtension(Complex)
    family1..
    given1..
    gender1..
    birthDate1..
    deceasedBooleanboolean
    photo..0
    Differential view of the extension 'Hospital X Patient InclusionStatus step 2'
    urlFixed Value
    system1..
    value1..
    urlFixed Value
    valuePeriodPeriod
    urlFixed Value
    valueCodeableConceptCodeableConcept
    urlFixed Value
    value[x]..0

    Step 3: Profile references

      Hospital X wants to capture data on the conditions that the patients have and model this in FHIR. The following requirements are specified:

    • The condition has a link to the the earlier described patient model.
    • The general pracititioner who recorded the condition must be provided.
    • The hospital needs at least 1 identifier and 1 name (family and given) of the general practitioner for identification.

    Steps to follow

    1. Create a new profile based on the best FHIR resource to capture this information.
    2. Make sure that the conditions can only refer to patients that conform to the profile we have defined in the previous exercise.
    3. Create another profile based on the best FHIR resource to capture the general practitioner information.
    4. Ensure that patient's conditions contain information on the recorder and that the recorder contains the required information described in the use case.

    Differential view of 'Hospital X Condition step 3'

    identifierΣ0..*Identifier
    clinicalStatusΣ ?! I0..1CodeableConceptBinding
    verificationStatusΣ ?! I0..1CodeableConceptBinding
    category0..*CodeableConceptBinding
    severity0..1CodeableConceptBinding
    codeΣ0..1CodeableConcept
    bodySiteΣ0..*CodeableConcept
    subjectΣ I1..1Reference(Hospital X Patient)
    encounterΣ I0..1Reference(Encounter)
    onsetDateTimedateTime
    onsetAgeAge
    onsetPeriodPeriod
    onsetRangeRange
    onsetStringstring
    abatementDateTimedateTime
    abatementAgeAge
    abatementPeriodPeriod
    abatementRangeRange
    abatementStringstring
    recordedDateΣ0..1dateTime
    recorderΣ I1..1Reference(Hospital X Practitioner)
    asserterΣ I0..1Reference(Practitioner | PractitionerRole | Patient | RelatedPerson)
    summaryI0..1CodeableConcept
    assessmentI0..*Reference(ClinicalImpression | DiagnosticReport | Observation)
    type0..1CodeableConcept
    codeΣ I0..*CodeableConcept
    detailΣ I0..*Reference(Resource)
    note0..*Annotation

    Differential view of 'Hospital X Practitioner step 3'

    identifierΣ1..*Identifier
    activeΣ0..1boolean
    useΣ ?!0..1codeBinding
    textΣ0..1string
    familyΣ1..1string
    givenΣ1..*string
    prefixΣ0..*string
    suffixΣ0..*string
    periodΣ I0..1Period
    telecomΣ I0..*ContactPoint
    addressΣ0..*Address
    genderΣ0..1codeBinding
    birthDateΣ0..1date
    photoI0..*Attachment
    identifier0..*Identifier
    code1..1CodeableConcept
    periodI0..1Period
    issuerI0..1Reference(Organization)
    communication0..*CodeableConceptBinding

    Step 4: Terminology bindings 💎

      Hospital X can only handle certain terminology and wants to capture specific data on the conditions that the patients have. The following requirements are specified:

    • The conditions need to have coded information that is the identification of the condition.
    • The hospital wants to register conditions with SNOMED CT codes and only allows ‘Clinical Finding’ codes.

    Steps to follow

    1. Find the right FHIR ValueSet that matches the above-described needs for the Condition resource. You can, for example, search in the FHIR Registry, Simplifier.net or the list of ValueSet in the core FHIR specification. Shortcut : link to the SNOMEDCTClinicalFindings ValueSet.
    2. Bind the ValueSet to the correct element in the profile.
    3. Adjust the binding strength to required.
    4. Make the element mandatory.

    Differential view of 'Hospital X Condition step 4'

    identifierΣ0..*Identifier
    clinicalStatusΣ ?! I0..1CodeableConceptBinding
    verificationStatusΣ ?! I0..1CodeableConceptBinding
    category0..*CodeableConceptBinding
    severity0..1CodeableConceptBinding
    codeΣ1..1CodeableConceptBinding
    bodySiteΣ0..*CodeableConcept
    subjectΣ I1..1Reference(Hospital X Patient)
    encounterΣ I0..1Reference(Encounter)
    onsetDateTimedateTime
    onsetAgeAge
    onsetPeriodPeriod
    onsetRangeRange
    onsetStringstring
    abatementDateTimedateTime
    abatementAgeAge
    abatementPeriodPeriod
    abatementRangeRange
    abatementStringstring
    recordedDateΣ0..1dateTime
    recorderΣ I1..1Reference(Hospital X Practitioner)
    asserterΣ I0..1Reference(Practitioner | PractitionerRole | Patient | RelatedPerson)
    summaryI0..1CodeableConcept
    assessmentI0..*Reference(ClinicalImpression | DiagnosticReport | Observation)
    type0..1CodeableConcept
    codeΣ I0..*CodeableConcept
    detailΣ I0..*Reference(Resource)
    note0..*Annotation

    Step 5: Derived profiles ⛓️

      Hospital X operates in the United States of America. Their API must be compatible with the US-Core profiles. On top of the US-Core profile for Immunization, it has additional requirements.

    • The path by which the vaccine product is taken into the body needs to be known.
    • The quantity of vaccine product that was administered is needed.

    Steps to follow

    We will create a derived profile of the applicable profile as defined in the US Core implementation guide to ensure compatibility. Creating a derived profile can either by downloading and saving the base profile or by installing the US Core FHIR package. Let's install US Core.

    1. Select your profiling folder in Forge and go to the dependencies tab.
    2. Click on the Simplifier icon to search for packages in Simplifier.net
    3. Search for US or hl7.fhir.us.core and install the '4.1.0' version by selecting it and clicking on 'Add'.
    4. Navigate back to the project tab (and notice that the US core packages and their dependencies are shown), open the US core package, and navigate to the FHIR profile needed for this use case.
    5. Right-click, and select 'New Derived Profile'
    6. Provide the profile with metadata and notice that you have inherited all the constraints from the base profile in the element tree view.
    7. Now, let's profile the use case requirements!

    Differential view of 'Hospital X Immunization step 5'

    identifier0..*Identifier
    statusS Σ ?!1..1codeBinding
    statusReasonS0..1CodeableConcept
    vaccineCodeS Σ I1..1CodeableConceptBinding
    patientS Σ I1..1Reference(US Core Patient Profile)
    encounterI0..1Reference(Encounter)
    occurrenceDateTimedateTime
    occurrenceStringstring
    recorded0..1dateTime
    primarySourceS Σ1..1boolean
    reportOrigin0..1CodeableConcept
    locationI0..1Reference(Location)
    manufacturerI0..1Reference(Organization)
    lotNumber0..1string
    expirationDate0..1date
    site0..1CodeableConcept
    route1..1CodeableConcept
    doseQuantityI1..1SimpleQuantity
    functionΣ0..1CodeableConceptBinding
    actorΣ I1..1Reference(Practitioner | PractitionerRole | Organization)
    noteΣ0..*Annotation
    reasonCode0..*CodeableConcept
    reasonReferenceI0..*Reference(Condition | Observation | DiagnosticReport)
    isSubpotentΣ ?!0..1boolean
    subpotentReason0..*CodeableConcept
    documentType0..1string
    reference0..1uri
    publicationDate0..1dateTime
    presentationDate0..1dateTime
    programEligibility0..*CodeableConcept
    fundingSource0..1CodeableConcept
    date0..1dateTime
    detailI0..1Reference(Observation)
    reported0..1boolean
    series0..1string
    authorityI0..1Reference(Organization)
    targetDisease0..*CodeableConcept
    doseNumberPositiveIntpositiveInt
    doseNumberStringstring
    seriesDosesPositiveIntpositiveInt
    seriesDosesStringstring

    Step 6: Slicing ✂️🍕

      Hospital X has additional for the general practitioner data:

    • The general practitioner needs to have exactly one active (official) United States National Provider Identifier (NPI) identifier.
    • All other identifiers which are known for the practitioner, if any, also need to come from the NPI. But they need to be marked as ‘old’.

    Steps to follow

    1. Open the previously created Practitioner profile.
    2. Slice the identifier element and add two slices.
    3. Define the slicing details on the sliced root. They are differentiated by the value of identifier.use.
    4. Define the two slices representing the above requirements. The naming system for the NPI can be found at HL7's known identifier systems.

    Differential view of 'Hospital X Practitioner step 6'

    useΣ ?!1..1codeBindingFixed Value
    typeΣ0..1CodeableConceptBinding
    systemΣ1..1uriFixed Value
    valueΣ1..1string
    periodΣ I0..1Period
    assignerΣ I0..1Reference(Organization)
    useΣ ?!1..1codeBindingFixed Value
    typeΣ0..1CodeableConceptBinding
    systemΣ1..1uriFixed Value
    valueΣ1..1string
    periodΣ I0..1Period
    assignerΣ I0..1Reference(Organization)
    activeΣ0..1boolean
    useΣ ?!0..1codeBinding
    textΣ0..1string
    familyΣ1..1string
    givenΣ1..*string
    prefixΣ0..*string
    suffixΣ0..*string
    periodΣ I0..1Period
    telecomΣ I0..*ContactPoint
    addressΣ0..*Address
    genderΣ0..1codeBinding
    birthDateΣ0..1date
    photoI0..*Attachment
    identifier0..*Identifier
    code1..1CodeableConcept
    periodI0..1Period
    issuerI0..1Reference(Organization)
    communication0..*CodeableConceptBinding

    Step 7: Publish to Simplifier.net 📚

    Let's upload all the profiles to Simplifier.net and check if everything works as expected.

    1. Create a Simplifier project (based on R4) if you haven't created one already: create one here

    2. In Forge, click on your profile folder and hit the link button, and select your Simplifier project. Then, use the synchronize button to upload all your profiles.

      • Project not shown? Check that the project is configured based on the same FHIR version as your profile.
    3. Alternatively, you could zip your profile folder and upload the zib through the user interface on Simplifier.

    If all went well, you should see the profiles in your project. You can check your profile constraints in the rendering as shown in the Overview tab of your profile. Selecting diff mode helps to pin down the made changes.

    Step 8: Validation (bonus) ✔️

      The developers of the general practitioners that will send patient data to Hospital X are starting to implement the use case based on your profiles. They are missing examples of resources that conform to the FHIR profiles of Hospital X.

    • Provide valid instances of the published profiles to demonstrate the expected FHIR resources.
    • Test the profiles by validating the example instances against the profiles.

    Steps to follow

    It is good practice to create an instance of your profile while creating that profile. It will improve your modeling, provide documentation for the implementers and allow you to validate and test your profile. Therefore, the bonus exercise is to create instances that conform to the built profiles. Ensure that the instance has a .meta.profile element that includes the canonical URL of your profile.

    Example of a 'Hospital X Patient': Belle Ulijn

    {
        "resourceType": "Patient",
        "id": "HospitalXPatient-01",
        "meta": {
            "profile":  [
                "http://ardon.nl/fhir/StructureDefinition/HospitalXPatient"
            ]
        },
        "identifier":  [
            {
                "system": "https://www.acme.org/fhir/NamingSystem/ssin",
                "value": "41072100284"
            }
        ],
        "name":  [
            {
                "use": "official",
                "text": "Belle Ulijn",
                "family": "Ulijn",
                "given":  [
                    "Belle"
                ]
            }
        ],
        "telecom":  [
            {
                "system": "phone",
                "value": "+3247458497"
            },
            {
                "system": "email",
                "value": "belleulijn@mail.be",
                "use": "home"
            }
        ],
        "gender": "female",
        "birthDate": "1941-07-21",
        "deceasedBoolean": false,
        "address":  [
            {
                "use": "home",
                "type": "both",
                "line":  [
                    "Rue de Boneffe 422"
                ],
                "city": "Opont",
                "postalCode": "6852",
                "country": "Belgium"
            }
        ],
        "multipleBirthBoolean": false,
        "generalPractitioner":  [
            {
                "reference": "Practitioner/HospitalXPractitioner-01",
                "display": "E. Penninx"
            }
        ]
    }

    Example of a 'Hospital X Practitioner': Enrico Penninx

    {
        "resourceType": "Practitioner",
        "id": "HospitalXPractitioner-01",
        "meta": {
            "profile":  [
                "http://ardon.nl/fhir/StructureDefinition/HospitalXPractitioner"
            ]
        },
        "identifier":  [
            {
                "use": "official",
                "system": "http://hl7.org/fhir/sid/us-npi",
                "value": "10079938"
            }
        ],
        "name":  [
            {
                "use": "official",
                "text": "Enrico Penninx",
                "family": "Penninx",
                "_family": {
                    "extension":  [
                        {
                            "url": "http://hl7.org/fhir/StructureDefinition/humanname-own-name",
                            "valueString": "Penninx"
                        }
                    ]
                },
                "given":  [
                    "Enrico"
                ],
                "_given":  [
                    {
                        "extension":  [
                            {
                                "url": "http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier",
                                "valueCode": "BR"
                            }
                        ]
                    }
                ]
            }
        ]
    }

    Example of a 'Hospital X Condition': Chronic pharyngitis

    {
        "resourceType": "Condition",
        "id": "HospitalXCondition-01",
        "meta": {
            "profile":  [
                "http://ardon.nl/fhir/StructureDefinition/HospitalXCondition"
            ]
        },
        "code": {
            "coding":  [
                {
                    "system": "http://snomed.info/sct",
                    "code": "140004",
                    "display": "Chronic pharyngitis"
                }
            ]
        },
        "subject": {
            "reference": "Patient/HospitalXPatient-01",
            "display": "Belle Ulijn"
        },
        "recorder": {
            "reference": "Practitioner/HospitalXPractitioner-01",
            "display": "E. Penninx"
        }
    }


    1. Upload your instances to your project and validate them by going to the resource and hitting the validation icon on the top right. Note: if you are on a paid plan, you can run the Quality Control feature validating the entire project in one go!

    2. Or instead of uploading the instance, you can also copy and paste it in simplifier/validate. Make sure R4 is selected and you scope the validation to your project/package.

    3. Lastly, the bonus bonus exercirse is to make these three invalid examples valid!

    If you want to know all the benefits of publishing and validating your profiles with packages, the following exercises are highly recommended: ACME R4 Package Tutorial.

    back to top