In this module you will learn more about terminology. We will use Forge, the official HL7® FHIR® profile editor, to build our profiles. You can download Forge for free.
The topics covered in this module are:
Terminology is about the codes you can record in your data - say a doctor picking a code for cough, or setting the status of a prescription to active.
There are a few resources in FHIR that cover (or are related to) terminology: CodeSystem, ValueSet, coded data types, ElementDefinition, NamingSystem, ConceptMap and ExpansionProfile.
A couple of these resources and their relations are shown in the image below. The next sections will explain them in more detail.
A CodeSystem defines a set of concepts (codes) with a coherent meaning, for example condition-clinical is a CodeSystem in the core specification for setting the clinical status of a condition.
A ValueSet is a selection of codes for use in a particular context. The relation of a ValueSet to a CodeSystem is that it selects (codes from) one or more CodeSystems. The actual codes belong to the CodeSystem, while the ValueSet is composed by linking to these codes in the CodeSystem. For example, the ValueSet condition-clinical includes all codes defined in the CodeSystem condition-clinical. When the codes in the CodeSystem are updated, the ValueSet automatically contains the updated codes. The lockedDate element can be used to "freeze" the codes to a particular version of the CodeSystem. You can also link to another ValueSet to include all codes from this ValueSet.
To compose your ValueSet, use the compose
element. With the include
element you can add concepts or codes from one or more CodeSystems and/or other ValueSets. You can either:
concept.code
elementfilter
element to select a group of codes orValueSet
element to refer to a ValueSet that contains a list of codes you want to includeNote that it is not possible to use both the concept
and filter
elements, you have to select either one of them to add codes from a CodeSystem.
You can also explicitly state that particular codes from a code system or other ValueSets should be excluded by using the exclude
element.
Below are examples of the use of the concept
and filter
elements. In the first example, two ICD-10 codes for breast cancer are included.
Example 1
<compose> <include> <system value='http://hl7.org/fhir/sid/icd-10-cm'/> <concept> <code value='C50'/> </concept> <concept> <code value='C50.01'/> </concept> </include> </compose>
The second example is an example of a ValueSet that includes all codes from the Loinc CodeSystem where the parent property equals LP43571-6
.
Example 2
<compose> <include> <system value="http://loinc.org"/> <filter> <property value="parent"/> <op value="="/> <value value="LP43571-6"/> </filter> </include> </compose>
Besides the compose
element, which is used to create the ValueSet, you may notice that there is also an element called expansion
. This element is used in the response of a FHIR Terminology Server when a user wants to retrieve all codes from a ValueSet by using the $expand
operation.
This is also known as ValueSet expansion or ValueSet enumeration. The $expand
operation is commonly used together with the filter
operation to reduce the number of codes returned in an expansion. Note that this results in a reduced view of the ValueSet, not a change in the ValueSet itself
Codes in CodeSystems can have one of the following data types:
When you are profiling and you need to choose one of these data types, the best and safest choice will usually be the CodeableConcept. As the CodeableConcept can have one or more Codings, the profile will be more reusable this way. The use of Codings is more limited and primarily used in extensions when there's need for finer control over use of translations and text.
The relation of coded data types to the other resources in the terminology module is that they refer to a CodeSystem and conform to an ElementDefinition.
An ElementDefinition defines an element in a resource or extension. For example, the Patient resource has an element called name
, which is the name of the patient. The ElementDefinition of name
defines the properties of the name
element, for example it defines that its data type is HumanName and its cardinality is 0..*. Within the terminology module, the ElementDefinition defines the (coded) data type and the ValueSet containing the codes that you can select in this element. The ElementDefinition binds a ValueSet. The binding strength is defined in the ElementDefinition as well. We will explain this in more detail in the next chapter.
For example, let's take a look at the ElementDefinition of the clinicalStatus
element.
Condition | Condition | Element IdCondition Detailed information about conditions, problems or diagnoses DefinitionA clinical condition, problem, diagnosis, or other event, situation, issue, or clinical concept that has risen to a level of concern.
| ||
identifier | Σ | 0..* | Identifier | Element IdCondition.identifier External Ids for this condition DefinitionThis records identifiers associated with this condition that are defined by business processes and/or used to refer to it when a direct URL reference to the resource itself is not appropriate (e.g. in CDA documents, or in written / printed documentation). Need to allow connection to a wider workflow.
|
clinicalStatus | Σ ?! | 0..1 | codeBinding | Element IdCondition.clinicalStatus active | recurrence | inactive | remission | resolved DefinitionThe clinical status of the condition. This element is labeled as a modifier because the status contains codes that mark the condition as not currently valid or of concern.
|
verificationStatus | Σ ?! | 0..1 | codeBinding | Element IdCondition.verificationStatus provisional | differential | confirmed | refuted | entered-in-error | unknown DefinitionThe verification status to support the clinical status of the condition. verificationStatus is not required. For example, when a patient has abdominal pain in the ED, there is not likely going to be a verification status. This element is labeled as a modifier because the status contains the code refuted and entered-in-error that mark the Condition as not currently valid. condition-ver-status (required) Constraints
unknown
|
category | 0..* | CodeableConcept | Element IdCondition.category problem-list-item | encounter-diagnosis DefinitionA category assigned to the condition. The categorization is often highly contextual and may appear poorly differentiated or not very useful in other contexts.
| |
severity | 0..1 | CodeableConceptBinding | Element IdCondition.severity Subjective severity of condition DefinitionA subjective assessment of the severity of the condition as evaluated by the clinician. Coding of the severity with a terminology is preferred, where possible. condition-severity (preferred) Constraints
| |
code | Σ | 0..1 | CodeableConcept | Element IdCondition.code Identification of the condition, problem or diagnosis Alternate namestype DefinitionIdentification of the condition, problem or diagnosis. 0..1 to account for primarily narrative only resources. Not all terminology uses fit this general pattern. In some cases, models should not use CodeableConcept and use Coding directly and provide their own structure for managing text, codings, translations and the relationship between elements and pre- and post-coordination.
|
bodySite | Σ | 0..* | CodeableConcept | Element IdCondition.bodySite Anatomical location, if relevant DefinitionThe anatomical location where this condition manifests itself. Only used if not implicit in code found in Condition.code. If the use case requires attributes from the BodySite resource (e.g. to identify and track separately) then use the standard extension body-site-instance. May be a summary code, or a reference to a very precise definition of the location, or both.
|
subject | Σ | 1..1 | Reference(Patient | Group) | Element IdCondition.subject Who has the condition? Alternate namespatient DefinitionIndicates the patient or group who the condition record is associated with. Group is typically used for veterinary or public health use cases. References SHALL be a reference to an actual FHIR resource, and SHALL be resolveable (allowing for access control, temporary unavailability, etc). Resolution can be either by retrieval from the URL, or, where applicable by resource type, by treating an absolute reference as a canonical URL and looking it up in a local registry/repository.
|
context | Σ | 0..1 | Reference(Encounter | EpisodeOfCare) | Element IdCondition.context Encounter or episode when condition first asserted Alternate namesencounter DefinitionEncounter during which the condition was first asserted. This record indicates the encounter this particular record is associated with. In the case of a "new" diagnosis reflecting ongoing/revised information about the condition, this might be distinct from the first encounter in which the underlying condition was first "known". Reference(Encounter | EpisodeOfCare) Constraints
|
onset[x] | Σ | 0..1 | Element IdCondition.onset[x] Estimated or actual date, date-time, or age DefinitionEstimated or actual date or date-time the condition began, in the opinion of the clinician. Age is generally used when the patient reports an age at which the Condition began to occur.
| |
onsetDateTime | dateTime | Data Type | ||
onsetAge | Age | Data Type | ||
onsetPeriod | Period | Data Type | ||
onsetRange | Range | Data Type | ||
onsetString | string | Data Type | ||
abatement[x] | 0..1 | Element IdCondition.abatement[x] If/when in resolution/remission DefinitionThe date or estimated date that the condition resolved or went into remission. This is called "abatement" because of the many overloaded connotations associated with "remission" or "resolution" - Conditions are never really resolved, but they can abate. There is no explicit distinction between resolution and remission because in many cases the distinction is not clear. Age is generally used when the patient reports an age at which the Condition abated. If there is no abatement element, it is unknown whether the condition has resolved or entered remission; applications and users should generally assume that the condition is still valid. When abatementString exists, it implies the condition is abated.
| ||
abatementDateTime | dateTime | Data Type | ||
abatementAge | Age | Data Type | ||
abatementBoolean | boolean | Data Type | ||
abatementPeriod | Period | Data Type | ||
abatementRange | Range | Data Type | ||
abatementString | string | Data Type | ||
assertedDate | Σ | 0..1 | dateTime | Element IdCondition.assertedDate Date record was believed accurate DefinitionThe date on which the existance of the Condition was first asserted or acknowledged. The assertedDate represents the date when this particular Condition record was created in the EHR, not the date of the most recent update in terms of when severity, abatement, etc. were specified. The date of the last record modification can be retrieved from the resource metadata.
|
asserter | Σ | 0..1 | Reference(Practitioner | Patient | RelatedPerson) | Element IdCondition.asserter Person who asserts this condition DefinitionIndividual who is making the condition statement. References SHALL be a reference to an actual FHIR resource, and SHALL be resolveable (allowing for access control, temporary unavailability, etc). Resolution can be either by retrieval from the URL, or, where applicable by resource type, by treating an absolute reference as a canonical URL and looking it up in a local registry/repository. Reference(Practitioner | Patient | RelatedPerson) Constraints
|
stage | 0..1 | BackboneElement | Element IdCondition.stage Stage/grade, usually assessed formally DefinitionClinical stage or grade of a condition. May include formal severity assessments.
| |
summary | 0..1 | CodeableConcept | Element IdCondition.stage.summary Simple summary (disease specific) DefinitionA simple summary of the stage such as "Stage 3". The determination of the stage is disease-specific. Not all terminology uses fit this general pattern. In some cases, models should not use CodeableConcept and use Coding directly and provide their own structure for managing text, codings, translations and the relationship between elements and pre- and post-coordination.
| |
assessment | 0..* | Reference(ClinicalImpression | DiagnosticReport | Observation) | Element IdCondition.stage.assessment Formal record of assessment DefinitionReference to a formal record of the evidence on which the staging assessment is based. References SHALL be a reference to an actual FHIR resource, and SHALL be resolveable (allowing for access control, temporary unavailability, etc). Resolution can be either by retrieval from the URL, or, where applicable by resource type, by treating an absolute reference as a canonical URL and looking it up in a local registry/repository. Reference(ClinicalImpression | DiagnosticReport | Observation) Constraints
| |
evidence | 0..* | BackboneElement | Element IdCondition.evidence Supporting evidence DefinitionSupporting Evidence / manifestations that are the basis on which this condition is suspected or confirmed. The evidence may be a simple list of coded symptoms/manifestations, or references to observations or formal assessments, or both.
| |
code | Σ | 0..* | CodeableConcept | Element IdCondition.evidence.code Manifestation/symptom DefinitionA manifestation or symptom that led to the recording of this condition. Not all terminology uses fit this general pattern. In some cases, models should not use CodeableConcept and use Coding directly and provide their own structure for managing text, codings, translations and the relationship between elements and pre- and post-coordination. manifestation-or-symptom (example) Constraints
|
detail | Σ | 0..* | Reference(Resource) | Element IdCondition.evidence.detail Supporting information found elsewhere DefinitionLinks to other relevant information, including pathology reports. References SHALL be a reference to an actual FHIR resource, and SHALL be resolveable (allowing for access control, temporary unavailability, etc). Resolution can be either by retrieval from the URL, or, where applicable by resource type, by treating an absolute reference as a canonical URL and looking it up in a local registry/repository.
|
note | 0..* | Annotation | Element IdCondition.note Additional information about the Condition DefinitionAdditional information about the Condition. This is a general notes/comments entry for description of the Condition, its diagnosis and prognosis. For systems that do not have structured annotations, they can simply communicate a single annotation with no author or time. This element may need to be included in narrative because of the potential for modifying information. Annotations SHOULD NOT be used to communicate "modifying" information that could be computable. (This is a SHOULD because enforcing user behavior is nearly impossible).
|
The type of this element is a code and it binds the ValueSet condition-clinical. Below you see part of the XML code of the ElementDefinition.
Condition.clinicalStatus element
<element id="Condition.clinicalStatus"> <path value="Condition.clinicalStatus" /> <short value="active | recurrence | inactive | remission | resolved" /> <definition value="The clinical status of the condition." /> <type> <code value="code" /> </type>
ValueSet binding
<binding> <strength value="required" /> <description value="The clinical status of the condition or diagnosis." /> <valueSetReference> <reference value="http://hl7.org/fhir/ValueSet/condition-clinical" /> </valueSetReference> </binding>
A NamingSystem is used for the unique identification of concepts, people, devices etc. A NamingSystem can either be used to define an identifier system (e.g. a patient number) or a code system (e.g. UCUM or LOINC). The kind
element defines the way in which the NamingSystem is used (identifier, codesystem or root). Root means that the NamingSystem is used as the root for other naming systems. Below we’ll explain the difference between the use of the NamingSystem for identifiers and its use for CodeSystems.
The most common use of the NamingSystem is to manage identifiers. For example, if you wanted to describe the Dutch BSN number (i.e. the Dutch security number) which used to uniquely identify Dutch citizens as a FHIR resource - you'd create a NamingSystem. This resource would have a description of what the BSN does, who manages it, and most importantly, it would also declare the identifier that can be used to refer to it in FHIR resources.
It is also possible to use the NamingSystem resource to define the existence of an external CodeSystem that you don’t have control over. In this case, you can use the NamingSystem to describe the CodeSystem’s use, its owner and create an identifier for it. If you are the owner of the CodeSystem resource you would of course use the CodeSystem resource itself to define it. Below is an example of the use of the NamingSystem to define a CodeSystem.
Example
<NamingSystem xmlns="http://hl7.org/fhir"> <id value="example"/> <name value="SNOMED CT"/> <status value="active"/> <kind value="codesystem"/> <date value="2014-12-13"/> <publisher value="HL7 International on behalf of IHTSDO"/> <contact> <name value="FHIR project team"/> <telecom> <system value="url"/> <value value="http://hl7.org/fhir"/> </telecom> </contact> <responsible value="IHTSDO & affiliates"/> <description value="SNOMED CT is a concept-based, scientifically validated terminology that provides a unique and permanent concept identifier that can be included in multiple HL7 data types including CD and CE. The concepts are managed to avoid semantic drift; so the meaning remains constant. If the concept is found to be ambiguous or the meaning changes, the concept is inactivated but still retained and the identifier is never reused. SNOMED CT's concepts are interrelated hierarchically and using description logic. SNOMED CT concepts have a unique fully-specified name, a preferred term, and, optionally, synonyms. The description languages include English and Spanish."/> <uniqueId> <type value="oid"/> <value value="2.16.840.1.113883.6.96"/> </uniqueId> <uniqueId> <type value="uri"/> <value value="http://snomed.info/sct"/> <preferred value="true"/> </uniqueId> </NamingSystem>
A ConceptMap defines a mapping from a set of concepts defined in a CodeSystem to one or more concepts defined in other CodeSystems. The source
element refers to the original ValueSet and the target
element to the destination ValueSet. The actual mappings are defined in the group
element, where group.element.code
is the original value from the source and group.element.target.code
is the new value in the target destination.
Example
<group> <source value="http://hl7.org/fhir/address-use"/> <target value="http://hl7.org/fhir/v3/AddressUse"/> <element> <code value="home"/> <display value="home"/> <target> <code value="H"/> <display value="home"/> </target> </element>
In this example, the home
code in from the address-use ValueSet from HL7 FHIR version DSTU2 is mapped to H
in the AddressUse ValueSet from version HL7 FHIR version STU3.
An ExpansionProfile is used to configure the behaviour of a terminology server when it processes ValueSet resources. It's not necessary to understand all its details at this point, but it's good to know that they are used for the ValueSet expansion
and validation
operations.
ValueSet and CodeSystem are the two most important resources covering terminology that you will be working with. To learn more about them, head over to the excellent FHIR Drills ValueSet and CodeSystem page that describes them in detail. Read on to learn how can you profile terminology, starting with changing the binding strength.
The very first thing that you need to know is: the strength of the binding that a field has to a ValueSet. There can be four, summarised below:
Binding strength | Meaning | How you can profile this |
---|---|---|
Required | You can only select codes from this valueset and none other | You can remove codes from the valueset but you cannot add any new codes |
Extensible | You must select codes from this valueset, but you can use other codes if the valueset doesn't have a matching code | You can add and removes codes from the valueset, but don't duplicate or replace existing ones |
Preferred | You should select codes from the valueset, but it's not strictly necessary | You don't have to use these codes, but it's recommended that you do |
Example | This is just an example of codes you could use | You should set this to a ValueSet of your own, or at least strengthen the binding (raise it) |
The easiest type of profiling you could do with terminology, besides fixing an element to be a specific code, is to change the binding strength. Similar to how you can only constrain and not relax the cardinality of an element (make it tighter), you can only constrain the binding of of a valueset - that is, make it stricter. You can do this in Forge by selecting an element with a coded data type (e.g. Patient.maritalStatus
) and changing the strength field.
In some cases you may want to add or remove codes from an existing ValueSet. However, you can't actually edit someone else's ValueSet. In this case you will need to create your own ValueSet and define which codes you want to include. Note that you can only add codes if the binding strength is not required.
For example, let's say you want to constrain Patient.gender
, which currently has a required binding to AdministrativeGender
. For example, you want to constrain the "unknown" code out from this required ValueSet. This ValueSet is managed by HL7, so you will need to create your own ValueSet which includes all of the codes except the ones you'd like to exclude. Once you've got your ValueSet, change the ValueSet reference in the binding.
A common usecase that comes up is binding a file to multiple valuesets. You can't do that directly in FHIR, but here are two solutions:
While constraining terminology, you may notice that you have two ways of going about it: 1) valueset binding, and 2) fixed value:
Prefer using the valueset binding as it is more flexible: with a valueset you can include a subsection of a codesystem, codes from several codesystems, and you are not limiting supplementary codes from other codesystems from being sent along with the required ones.
Here below are examples of customers that we helped building profiles.
Nictiz is the centre of expertise for standardization and eHealth in The Netherlands. HL7 Netherlands core and MedMij profiles are published on Simplifier. MedMij is a national project that aims to give Dutch citizens integrated access to all their health data in one personal health environment. FHIR is used as a standard to exchange health information between the involved parties. The profiles are based on standardized clinical building blocks called Health and Care Information Models (HCIM).
Below is an example of the Dutch profile on Medication, which is defined as the HCIM called ZIB Product.
In the Netherlands, the Z-Index maintains a classification system called the G-Standaard for medication. Different CodeSystems can be used to describe medication products and ingredients:
Besides the registration of G-Standaard codes, ATC codes are registered as well. The Anatomical Chemical Therapeutical (ACT) classification is a hierarchical classification of medicines on organ (system) and therapeutical and chemical properties.
Nictiz has defined different ValueSets to capture the codes from these CodeSystems. In the Dutch Medication profile called ZIB-Product, the medication.code.coding
and ingredient.itemCodeableConcept.coding
elements are sliced. Each slice contains a required binding to one of these ValueSets. In this way, all codes are allowed, but the receiving party can distinguish between the different CodeSystems that are used.
HelseVest is a Norwegian health authority, responsible for the western region of Norway. One of their projects is the Helsevest Prescription project, which aims to provide integrations for medication prescription. Below is an example of one of the ValueSets that is used in this project.
Format URL | http://hl7.no/fhir/ValueSet/kule-benevning-tidsenhet |
Published by | HL7 Norge |
Status | Draft (since 2017-01-27) |
Experimental | False |
Dette kodeverket inneholder benevning for tidsenheter. Skal benyttes for datatypen PQ når enhet skal være tidsenhet.
This value set includes codes from the following code systems:
Code | Display | |
wk | week |
The ValueSet includes all codes from the core units-of-time ValueSet, but excludes the code wk
for week. Here below is the corresponding XML code.
<ValueSet> <text> <status value="generated" /> <div> <h2> Benevning tidsenhet </h2> <tt> http://hl7.no/fhir/ValueSet/kule-benevning-tidsenhet </tt> <p> Dette kodeverket inneholder benevning for tidsenheter. Skal benyttes for datatypen PQ når enhet skal være tidsenhet. </p> </div> </text> <url value="http://hl7.no/fhir/ValueSet/kule-benevning-tidsenhet" /> <identifier> <system value="urn:ietf:rfc:3986" /> <value value="urn:oid:2.16.578.1.12.4.1.1.9088" /> </identifier> <name value="Benevning tidsenhet" /> <status value="draft" /> <experimental value="false" /> <publisher value="HL7 Norge" /> <date value="2017-01-27" /> <description value="Dette kodeverket inneholder benevning for tidsenheter. Skal benyttes for datatypen PQ når enhet skal være tidsenhet." /> <compose> <import value="http://hl7.org/fhir/ValueSet/units-of-time" /> <exclude> <system value="http://hl7.org/fhir/ValueSet/units-of-time" /> <concept> <code value="wk" /> <display value="week" /> </concept> </exclude> </compose> </ValueSet>
In this exercise you will create your own ValueSets and include these in your profile.
Here below are a couple of links that you may find useful during this exercise:
+
on the right of FHIR Value Sets to create your ValueSet.Name
, URL
and Description
fields (e.g. name=MyRelationshipCodes, URL=https://example.org/fhir/ValueSet/MyRelationshipCodes)Code System
field with the URL of the system you want to select codes from.Property
, Operation
and Value
fields in the first row to add the filter criterium. Hint: these codes will have an is-a relationship with the code fammemb.+ Exclude Filter
.Code System
field with the URL of the system you want to exclude codes from.Property
, Operation
and Value
fields in the first row to add the filter criterium. Hint: these codes will have an is-a relationship with the code inlaw.Upload to FHIR server
and choose Validate Value Set
. You may also upload your ValueSet to a FHIR server in this step. Click on Download Value Set
to download and save the JSON code of your created ValueSet.We are always looking for ways to improve our products. The Profiling Academy was built using our own IG-editor in Simplifier. If you have any feedback on this module or on our Profiling Academy in general, please leave a comment in the Issue Tracker of the project.
Most modules end with an exercise. Use Forge to start profiling yourself. Just contact us at simplifier@fire.ly if you need any help.
Follow one of our predefined or tailor-made courses. We will make sure you know FHIR inside-out.
Let us assist you with your FHIR use case. Visit our company website to know more about our services or get into contact with Rien Wertheim right away.
Powered by SIMPLIFIER.NET