FHIR to CDISC Joint Mapping Implementation Guide
1.0.0 - STU 1 International flag

FHIR to CDISC Joint Mapping Implementation Guide, published by HL7 International - BR&R Work Group. This guide is not an authorized publication; it is the continuous build for version 1.0.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/HL7/fhir-cdisc-mapping/ and changes regularly. See the Directory of published versions

Vital Signs

Like laboratory results, vital signs are also typically captured in Observations. FHIR actually defines specific profiles for common vital sign measures, significantly increasing the consistency of basic vital signs data. These profiles mandate the declaration of the vital-signs category. This allows vital signs to be easily separated from other observations.

One consideration to be aware of is that Blood Pressure is typically captured as a single Observation with two components, however it is sometimes captured as two distinct resource instances. When converting, both approaches will need to be accounted for.

VS Mappings

Guidance on interpreting the tables can be found here.

CDISC FHIR map (or gap) Comment
Label CDASH SDTM Element FHIRPath
Study Identifier STUDYID
Core: HR
Type: Char
STUDYID
Core: Req
Type: Char
ResearchStudy.identifier
0..* Identifier

ResearchSubject.where(subject=Observation.subject).study.resolve().partOf.resolve().identifier

Observation.extension(workflow-researchstudy).valueReference.resolve().partOf.resolve().identifier

Mapping is based on presumption that research subject will be tied to site-specific ResearchStudy, which will then be part of overall ResearchStudy.

The path using the extension will only exist if the system maintaining the Observation is aware of its relevance to the Study. ResearchStudy links to Patient. Observation links to Patient. If the patients are the same, that establishes the linkage. There's also an extension that allows direct linkage to a 'study' from any resource - if the source system has actually established such a linkage.
Study Site Identifier SITEID
Core: HR
Type: Char
DM.SITEID
Core: Req
Type: Char
ResearchStudy.site
0..* Reference

ResearchSubject.where(subject=Observation.subject).study.resolve().identifier

Observation.extension(workflow-researchstudy).valueReference.resolve().identifier

Mapping is based on presumption that research subject will be tied to site-specific ResearchStudy, which will then be part of overall ResearchStudy.

The path using the extension will only exist if the system maintaining the Observation is aware of its relevance to the Study.
Subject Identifier for the Study SUBJID
Core: HR
Type: Char
DM.SUBJID
Core: Req
Type: Char
ResearchSubject.identifier
0..* Identifier

ResearchSubject.where(individual=Observation.subject).identifier

Study subject is found by finding the StudySubject that corresponds to the same Patient and ResearchStudy as the Observation.

No standard way to decide which subject identifier to use
Visit Name VISIT
Core: R/C
Type: Char
VISIT
Core: Perm
Type: Char
Encounter should have a standard instantiatesCanonical extension that would allow pointing to the ActivityDefinition. This would be the ActivityDefinition.name. Submit a change request to add the extension
Visit Date VISDAT
Core: R/C
Type: Char
Encounter.period
0..1 Period

Observation.encounter.resolve().period.start

Linked via Observation.encounter
Vital Signs Performed VSPERF
Core: O
Type: Char
VSSTAT
Core: Perm
Type: Char
Observation.status
1..1 code
Binding: ObservationStatus required

Observation.status=('final' or 'cancelled')

Vital Signs Date VSDAT
Core: R/C
Type: Char
VSDTC
Core: Exp
Type: Char
values: ISO 8601
Observation.effectiveDateTime
0..1 dateTime

Observation.effectiveDateTime

Vital Signs Time VSTIM
Core: R/C
Type: Char
VSDTC
Core: Exp
Type: Char
values: ISO 8601
Observation.effectiveDateTime
0..1 dateTime

Observation.effectiveDateTime

Category for Vital Signs VSCAT
Core: O
Type: Char
VSCAT
Core: Perm
Type: Char
Observation.category
0..* CodeableConcept
Binding: ObservationCategory preferred

Observation.category

FHIR allows multiple categorizations at various levels of granularity.

Observation.category.coding.system="http://terminology.hl7.org/CodeSystem/observation-category" + Observation.category.coding.code="vital-signs". This combination can be used to extract vital sign data points from EHR system and correctly assign them to the VS domain.
Subcategory for Vital Signs VSSCAT
Core: O
Type: Char
VSSCAT
Core: Perm
Type: Char
Observation.category
0..* CodeableConcept
Binding: ObservationCategory preferred

Observation.category

FHIR allows multiple categorizations at various levels of granularity.

Observation.category.coding.system="http://terminology.hl7.org/CodeSystem/observation-category" + Observation.category.coding.code="vital-signs". This combination can be used to extract vital sign data points from EHR system and correctly assign them to the VS domain.
Vital Signs Group ID VSGRPID VSGRPID
Core: Perm
Type: Char
This would typically be done by having the related Observations being 'membersOf' a common parent Observation.
Vital Signs Planned Time Point Name VSTPT
Core: R/C
Type: Char
VSTPT
Core: Perm
Type: Char
Observation.extension
0..* Extension

Observation.extension('R5-Observation.instantiatesCanonical').resolve().title

TimePoints will be represented in FHIR as PlanDefinition.activities. Referencing a PlanDefinition is supported in R5. Can use a standard extension to pre-adopt.
Vital Signs Completion Status VSSTAT
Core: O
Type: Char
VSSTAT
Core: Perm
Type: Char
Observation.status
1..1 code
Binding: ObservationStatus required

Observation.status

ServiceRequest.status IN {'cancelled'|'on-hold'|'revoked'| 'entered-in-error'}

In some instances, VSSTAT="NOT DONE" records will come from FHIR Observation resources where Observation.status="cancelled". This is not an exact match and there could be observations which have been scheduled and did not happen so an observation may not exist.
ServiceRequest.status
1..1 code
Binding: ServiceRequestStatus required

Observation.status

ServiceRequest.status IN {'cancelled'|'on-hold'|'revoked'| 'entered-in-error'}

VS Result or Finding in Original Units VSORRES
Core: HR
Type: Char
VSORRES
Core: Exp
Type: Char
Observation.valueQuantity
0..1 Quantity obs-7

Observation.valueQuantity.value

Ensure the value provided from the EHR is considered an actual value (result), an interpretation or range.
VS Original Units VSORRESU
Core: R/C
Type: Char
VSORRESU
Core: Exp
Type: Char
Observation.valueQuantity
0..1 Quantity obs-7

Observation.valueQuantity.unit

Vital Signs Clinical Significance VSCLSIG
Core: O
Type: Char
SUPPVS.QVAL Observation.interpretation
0..* CodeableConcept
Binding: ObservationInterpretation extensible

Observation.interpretation

If clinical significance is a boolean, then the mapping is different from the existing http://hl7.org/fhir/ValueSet/observation-interpretation ValueSet. Meaning, the values of "normal", "high", :low", etc. can reside in the --NRIND variable. There are also cases where clinical significant outcome details can exist with corresponding details that don't fit into either of those mentioned buckets.
Vital Signs Position of Subject VSPOS
Core: R/C
Type: Char
VSPOS
Core: Perm
Type: Char
Observation.code
1..1 CodeableConcept
Binding: ObservationCode example

Observation.code

This is often pre-coordinated into the Observation.code, but can also be expressed in the method
Observation.method
0..1 CodeableConcept
Binding: ObservationMethod example

Observation.method

Location of Vital Signs Measurement VSLOC
Core: O
Type: Char
VSLOC
Core: Perm
Type: Char
Observation.bodySite
0..1 CodeableConcept
Binding: BodySite example

Observation.bodySite

Requires knowledge or review of data to ensure location, laterality and directionality are included in the code and can be parsed.
Vital Signs Laterality VSLAT
Core: O
Type: Char
VSLAT
Core: Perm
Type: Char
Observation.bodySite
0..1 CodeableConcept
Binding: BodySite example

Observation.bodySite

Requires knowledge or review of data to ensure location, laterality and directionality are included in the code and can be parsed.
Vital Signs Directionality VSDIR
Core: O
Type: Char
VSDIR* Observation.bodySite
0..1 CodeableConcept
Binding: BodySite example

Observation.bodySite

Requires knowledge or review of data to ensure location, laterality and directionality are included in the code and can be parsed.
Vital Signs Test code VSTESTCD VSTESTCD
Core: Req
Type: Char
Observation.code
1..1 CodeableConcept
Binding: ObservationCode example

Observation.code.coding.code

May use one of the following:coding.display and coding.code (plus coding.system)
Vital Signs Test Name VSTEST
Core: HR
Type: Char
VSTEST
Core: Req
Type: Char
Observation.code
1..1 CodeableConcept
Binding: ObservationCode example

Observation.code.coding.display

May use one of the following:coding.display and coding.code (plus coding.system)
Vital Signs Sponsor-Defined Identifier VSSPID
Core: O
Type: Char
VSSPID
Core: Perm
Type: Char
Observation.identifier
0..* Identifier

Observation.identifier.where(assigner=[sponsor organization id])

The assigner of the identifier can be explicit or inferred by the Identifier.system. Example: "assigner=sponsor", the value of assigner can either be a simple name using "display" (e.g. "assigner.display=MyPharma" or a reference to an "Organization"
Vital Signs Repetition Number VSREPNUM
Core: O
Type: Char
SUPPVS.QVAL This could be captured as a specific ActivityDefinition where you'd have a distinct ActivityDefinition for each occurrence. However, it is more likely to be a single ActivityDefinition for the test and an extension would be added on Observation.instantiates to indicate which occurrence is the Observation.
FHIR map (or gap) CDISC Comment
Label Element FHIRPath CDASH SDTM
Study Identifier ResearchStudy.identifier
0..* Identifier

ResearchSubject.where(subject=Observation.subject).study.resolve().partOf.resolve().identifier

Observation.extension(workflow-researchstudy).valueReference.resolve().partOf.resolve().identifier

STUDYID
Core: HR
Type: Char
STUDYID
Core: Req
Type: Char
Mapping is based on presumption that research subject will be tied to site-specific ResearchStudy, which will then be part of overall ResearchStudy.

The path using the extension will only exist if the system maintaining the Observation is aware of its relevance to the Study. ResearchStudy links to Patient. Observation links to Patient. If the patients are the same, that establishes the linkage. There's also an extension that allows direct linkage to a 'study' from any resource - if the source system has actually established such a linkage.
Study Site Identifier ResearchStudy.site
0..* Reference

ResearchSubject.where(subject=Observation.subject).study.resolve().identifier

Observation.extension(workflow-researchstudy).valueReference.resolve().identifier

SITEID
Core: HR
Type: Char
DM.SITEID
Core: Req
Type: Char
Mapping is based on presumption that research subject will be tied to site-specific ResearchStudy, which will then be part of overall ResearchStudy.

The path using the extension will only exist if the system maintaining the Observation is aware of its relevance to the Study.
Subject Identifier for the Study ResearchSubject.identifier
0..* Identifier

ResearchSubject.where(individual=Observation.subject).identifier

SUBJID
Core: HR
Type: Char
DM.SUBJID
Core: Req
Type: Char
Study subject is found by finding the StudySubject that corresponds to the same Patient and ResearchStudy as the Observation.

No standard way to decide which subject identifier to use
Visit Name Encounter should have a standard instantiatesCanonical extension that would allow pointing to the ActivityDefinition. This would be the ActivityDefinition.name. Submit a change request to add the extension VISIT
Core: R/C
Type: Char
VISIT
Core: Perm
Type: Char
Visit Date Encounter.period
0..1 Period

Observation.encounter.resolve().period.start

VISDAT
Core: R/C
Type: Char
Linked via Observation.encounter
Vital Signs Performed Observation.status
1..1 code
Binding: ObservationStatus required

Observation.status=('final' or 'cancelled')

VSPERF
Core: O
Type: Char
VSSTAT
Core: Perm
Type: Char
Vital Signs Date Observation.effectiveDateTime
0..1 dateTime

Observation.effectiveDateTime

VSDAT
Core: R/C
Type: Char
VSDTC
Core: Exp
Type: Char
values: ISO 8601
Vital Signs Time Observation.effectiveDateTime
0..1 dateTime

Observation.effectiveDateTime

VSTIM
Core: R/C
Type: Char
VSDTC
Core: Exp
Type: Char
values: ISO 8601
Category for Vital Signs Observation.category
0..* CodeableConcept
Binding: ObservationCategory preferred

Observation.category

VSCAT
Core: O
Type: Char
VSCAT
Core: Perm
Type: Char
FHIR allows multiple categorizations at various levels of granularity.

Observation.category.coding.system="http://terminology.hl7.org/CodeSystem/observation-category" + Observation.category.coding.code="vital-signs". This combination can be used to extract vital sign data points from EHR system and correctly assign them to the VS domain.
Subcategory for Vital Signs Observation.category
0..* CodeableConcept
Binding: ObservationCategory preferred

Observation.category

VSSCAT
Core: O
Type: Char
VSSCAT
Core: Perm
Type: Char
FHIR allows multiple categorizations at various levels of granularity.

Observation.category.coding.system="http://terminology.hl7.org/CodeSystem/observation-category" + Observation.category.coding.code="vital-signs". This combination can be used to extract vital sign data points from EHR system and correctly assign them to the VS domain.
Vital Signs Group ID This would typically be done by having the related Observations being 'membersOf' a common parent Observation. VSGRPID VSGRPID
Core: Perm
Type: Char
Vital Signs Planned Time Point Name Observation.extension
0..* Extension

Observation.extension('R5-Observation.instantiatesCanonical').resolve().title

VSTPT
Core: R/C
Type: Char
VSTPT
Core: Perm
Type: Char
TimePoints will be represented in FHIR as PlanDefinition.activities. Referencing a PlanDefinition is supported in R5. Can use a standard extension to pre-adopt.
Vital Signs Completion Status Observation.status
1..1 code
Binding: ObservationStatus required

Observation.status

ServiceRequest.status IN {'cancelled'|'on-hold'|'revoked'| 'entered-in-error'}

VSSTAT
Core: O
Type: Char
VSSTAT
Core: Perm
Type: Char
In some instances, VSSTAT="NOT DONE" records will come from FHIR Observation resources where Observation.status="cancelled". This is not an exact match and there could be observations which have been scheduled and did not happen so an observation may not exist.
ServiceRequest.status
1..1 code
Binding: ServiceRequestStatus required

Observation.status

ServiceRequest.status IN {'cancelled'|'on-hold'|'revoked'| 'entered-in-error'}

VS Result or Finding in Original Units Observation.valueQuantity
0..1 Quantity obs-7

Observation.valueQuantity.value

VSORRES
Core: HR
Type: Char
VSORRES
Core: Exp
Type: Char
Ensure the value provided from the EHR is considered an actual value (result), an interpretation or range.
VS Original Units Observation.valueQuantity
0..1 Quantity obs-7

Observation.valueQuantity.unit

VSORRESU
Core: R/C
Type: Char
VSORRESU
Core: Exp
Type: Char
Vital Signs Clinical Significance Observation.interpretation
0..* CodeableConcept
Binding: ObservationInterpretation extensible

Observation.interpretation

VSCLSIG
Core: O
Type: Char
SUPPVS.QVAL If clinical significance is a boolean, then the mapping is different from the existing http://hl7.org/fhir/ValueSet/observation-interpretation ValueSet. Meaning, the values of "normal", "high", :low", etc. can reside in the --NRIND variable. There are also cases where clinical significant outcome details can exist with corresponding details that don't fit into either of those mentioned buckets.
Vital Signs Position of Subject Observation.code
1..1 CodeableConcept
Binding: ObservationCode example

Observation.code

VSPOS
Core: R/C
Type: Char
VSPOS
Core: Perm
Type: Char
This is often pre-coordinated into the Observation.code, but can also be expressed in the method
Observation.method
0..1 CodeableConcept
Binding: ObservationMethod example

Observation.method

Location of Vital Signs Measurement Observation.bodySite
0..1 CodeableConcept
Binding: BodySite example

Observation.bodySite

VSLOC
Core: O
Type: Char
VSLOC
Core: Perm
Type: Char
Requires knowledge or review of data to ensure location, laterality and directionality are included in the code and can be parsed.
Vital Signs Laterality Observation.bodySite
0..1 CodeableConcept
Binding: BodySite example

Observation.bodySite

VSLAT
Core: O
Type: Char
VSLAT
Core: Perm
Type: Char
Requires knowledge or review of data to ensure location, laterality and directionality are included in the code and can be parsed.
Vital Signs Directionality Observation.bodySite
0..1 CodeableConcept
Binding: BodySite example

Observation.bodySite

VSDIR
Core: O
Type: Char
VSDIR* Requires knowledge or review of data to ensure location, laterality and directionality are included in the code and can be parsed.
Vital Signs Test code Observation.code
1..1 CodeableConcept
Binding: ObservationCode example

Observation.code.coding.code

VSTESTCD VSTESTCD
Core: Req
Type: Char
May use one of the following:coding.display and coding.code (plus coding.system)
Vital Signs Test Name Observation.code
1..1 CodeableConcept
Binding: ObservationCode example

Observation.code.coding.display

VSTEST
Core: HR
Type: Char
VSTEST
Core: Req
Type: Char
May use one of the following:coding.display and coding.code (plus coding.system)
Vital Signs Sponsor-Defined Identifier Observation.identifier
0..* Identifier

Observation.identifier.where(assigner=[sponsor organization id])

VSSPID
Core: O
Type: Char
VSSPID
Core: Perm
Type: Char
The assigner of the identifier can be explicit or inferred by the Identifier.system. Example: "assigner=sponsor", the value of assigner can either be a simple name using "display" (e.g. "assigner.display=MyPharma" or a reference to an "Organization"
Vital Signs Repetition Number This could be captured as a specific ActivityDefinition where you'd have a distinct ActivityDefinition for each occurrence. However, it is more likely to be a single ActivityDefinition for the test and an extension would be added on Observation.instantiates to indicate which occurrence is the Observation. VSREPNUM
Core: O
Type: Char
SUPPVS.QVAL