Structured Data Capture, published by HL7 International / FHIR Infrastructure. This guide is not an authorized publication; it is the continuous build for version 4.0.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/HL7/sdc/ and changes regularly. See the Directory of published versions
Page standards status: Trial-use |
Contents:
One of the objectives of the SDC implementation guide is to reduce data entry into forms when the relevant data already exists in discrete form within the clinical or administrative system completing the form. This saves the user time and increases accuracy. If a Questionnaire is created with knowledge of where the data for different questions within the form is expected to come from, the Form Filler or Form Fill Manager system can query for the relevant information and automatically fill in some of the answers. FHIR's REST interface provides a standard way to query this data, regardless of the type of client.
This 'population' process can happen in one of two ways:
The primary method of form pre-population is the $populate
operation. It performs the population process and returns a
QuestionnaireResponse
, with relevant fields pre-filled based on the information provided or already known by the server.
Note: The $populate-html
and $populate-link
operations have been deprecated due to a lack of any known implementation in the entire time it's been present,
and the adaptive questionnaires possibly having been used instead.
If using a populate operation, the operation will typically only be invoked once. However, there are two circumstances where it might be invoked more than once:
Both of these situations involve starting from an existing QuestionnaireResponse, which means that "re-populating" a form is only relevant using $populate.
If choosing to re-populate a form, there are several considerations to keep in mind:
There are three different modes of "population" possible:
"Choice selection" and "answer context" options will generally only be exposed when the user is interacting with the associated question (typically when a user clicks on an icon indicating they want to see the context or EHR choices).
SHALL NOT
be able to see information populated
into a form that they would not be able to see when navigating the source system directly (I.e. it is a mandatory requirement that the population process
not populate information in the form if the user completing the questionnaire would not have permission to see that data if they queried it directly). In some cases, this means that an answer in a form might not
be populated even though the data exists - because the user does not have authority to see that data.
Defining the rules for populating a questionnaire is essentially a mapping process. The author is mapping between the data element defined by a particular question or group item and a corresponding element in a FHIR resource or profile.
Mapping can be dangerous because it can lead to the sharing of incorrect data or, occasionally, the failure to share correct data. For this reason, it is essential that human users be given the opportunity to review questionnaire responses that have been populated by automated means.
Even with this precaution, care should be taken when performing data mappings, including:
SHALL
not be displayed to the user completing the form.
If an answer disables a portion of the QuestionnaireResponse containing significant user-entered data, the entry system SHOULD warn users that
that information will be removed on submission.
Provenance.entity.what
where the Provenance.entity.role
would be 'source'. Software information would be captured in
Provenance.agent
.SHALL
be treated as 'not answered' rather than being converted to a boolean value of 'false'.Populating a QuestionnaireResponse is a complex task. The system must be able to query resources, use FHIRPath or CQL to populate and potentially calculate relevant data elements, manage conditionality rules around enableWhen as part of the population process, etc. As a result, some client systems might prefer to offload the responsibility for handling pre-population of a form to a separate system. The FHIR specification defines a set of services that can be used to provide a variable degree of offloading - from just handling the population aspect through to handling the rendering of the form and interactive data capture completely through a separate site.
Operation | Description |
---|---|
populate | This operation supports generating a QuestionnaireResponse instance based on a specified Questionnaire. If matching data is available for any of the questions and the server supports the pre-population capability, the answers for those questions will be populated in the returned QuestionnaireResponse instance. |
In addition to the $populate operation, another alternative is to use the Adaptive Form mechanism. It hides the design of the questionnaire entirely and, in principle, allows the service to determine the next question to automatically fill in (or perhaps even suppress asking questions) based on data the service can access about the patient.
For SDC purposes, server systems claiming to support CapabilityStatements that require support for the populate
operation (SDC Form Manager) SHALL
, at minimum:
identifier
, questionnaire
, questionnaireRef
, subject
and
content
content
parameter
Similarly, client systems claiming to support the populate
operation
(SDC Form Filler) SHALL
, at a minimum:
Questionnaire/[identifier]/$populate
)
as well as indirectly either by identifier
or questionnaire
content
parameter* Supporting additional resources relevant to the context of the form is also encouraged. Past versions of this specification mandated support for passing C-CDA resources as FHIR Binary instances and this is still permitted. However, this specification no longer provides recommendations for extracting data elements from C-CDA and we have not yet heard of any systems that do this successfully in a production environment.
This specification defines three different mechanisms to embed information in Questionnaires to support population:
Systems are free to experiment with other population mechanisms but cannot expect support for those from other SDC-conformant systems.
Each mechanism has its own profile that includes the additional resource elements or extensions relevant for supporting a particular mechanism: SDC Questionnaire Populate - Observation,
SDC Questionnaire Populate - Expression, and SDC Questionnaire Populate - Structure Map profiles. Each profile identifies
specific 'must support' elements and extensions that systems that claim to support a specific SDC population mechanism SHALL
be capable of populating data, as befits the CapabilityStatement(s)
they claim conformance to. Each system should choose which approach(es) it wishes to use and support based on the elements specified in that profile.
Some of these mechanisms make use of FHIR-based queries, FHIRPath and/or CQL as well as extensions that include expressions in one of these languages. Implementers should read the Using Expressions page for background and guidance on these technologies and extensions.
These three mechanisms aren't necessarily mutually exclusive. It is possible to use StructureMap-based population to perform an initial set of 'complex' population and then have different elements within the Questionnaire that are set up to perform supplemental observation-based or expression-based population. Obviously, the same element should only be populated in one way. Also, combining methods adds complexity and may reduce the number of systems that are capable of appropriately handling the Questionnaire.
Note: StructureMap-based population takes precedence over all other mechanisms. If a StructureMap is present, any observation-based or expression-based population expectations are ignored entirely. Observation-based and expression-based population may be performed simultaneously, item by item. However, if both approaches attempt to populate the same item, behavior is undefined. It is strongly recommended that Questionnaire authors avoid configuring both mechanisms to target the same question item. Systems may choose to raise an error, ignore one of the methods, or include both results in the case of repeating items.
Profile: | SDC Questionnaire Populate - Observation profile |
---|---|
Relevant Extensions: | |
Example Questionnaires: | USSG Family Health Template |
This is the simplest of the population mechanisms. It takes advantage of the fact that most question answers in the healthcare space typically correspond to the
value
element of an Observation. It also takes advantage of the Questionnaire.item.code
element that identifies what a concept
each question or group corresponds to.
To use this method:
item.code
element on each question to be populated. Typically, this will be a LOINC code, but in some
jurisdictions/environments, SNOMED CT or other codes may be relevant.item.code
present - this might represent the code of a panel or the Observation.code of an Observation with no
value but with multiple Observation.component
elements. Child question items can then assert the item.code
of the "member-of"
Observations or the Observation.component.code
values.observationLinkPeriod
extension must also be included). This extension
indicates the period of time over which to search for matching observations. If there are no observations within that window, no population will occur.
For observations where how recent they are does not matter (e.g. blood type), simply set the duration to a long period of time - e.g. 200 years.
If an observationLinkPeriod
extension is defined at the root Questionnaire, on a group item (even if it has no item.code
), or on a question item,
that period applies to all descendant questions that have an item.code
, unless a closer (i.e., nearer in the hierarchy) observationLinkPeriod
is defined and overrides it.item.code
do not themselves get populated but pass the observationLinkPeriod
to their coded children.
Observation Link Period Hierarchical Diagram: This diagram illustrates the structure and flow of observationLinkPeriod
extension in a Questionnaire. It shows how the period applies from the Questionnaire root down to group items and question items, with cases of inheritance, overriding, and items without codes.
item.code
inherit the nearest observationLinkPeriod from their ancestors, such as the root or a parent group, which allows them to participate in observation-based auto-population. If an observationLinkPeriod is defined directly on an item with item.code
, this specific period overrides any inherited period. Items without item.code
do not inherit any observationLinkPeriod and are excluded from the auto-population mechanism. However, if an item with no item.code
has descendants that do have item.code
, those descendants can still inherit the nearest applicable observationLinkPeriod from higher levels.item.code
elements might be present. If so, each is considered an acceptable Observation.code for the desired population
value.For example:
When performing the population operation, the system would look for questions that have the observationLinkPeriod
extension
and would then perform a query on the Observation using the context of the QuestionnaireResponse's subject - typically a Patient. The query would retrieve
the most recent observation for that subject whose code matched one of the Questionnaire.item
's codes, that had a value and whose value was of
the correct data type.
The 'logical' query performed for the above Questionnaire item being populated on August. 31 might look like this:
[base]?Observation?subject=[questionnaire response subject id]&code=http%3A//loinc.org|29463-7,http%3A//loinc.org|3141-9,http%3A//loinc.org|8341-0&status=final,amended,corrected&date=ge2018-06-02&_sort=-date&_count=1
In practice, the server might not support the _sort or _count parameters, so the filtering for "most recent" might need to be done locally - especially if there's a need to check for matching data type.
Considerations and rules when using this approach:
Quantity
SHOULD also have a type of Quantity. However, they MAY have a type of
integer
or decimal
provided that the unit
extension is present to allow determination of what unit to match on/convert to.SHALL
filter to only look at Observations with a status of 'final', 'amended', or 'corrected'.SHALL
check for the presence of the Observation.focus element and exclude elements where the focus is not the patient (e.g. we do not want the
heart rate of a fetus if trying to populate the heart rate of the mother.)SHALL
be limited to components of the Observation bound to the parent item and other Observations reachable by a hasMember
link from that
observation.Patient.birthDate
),
systems MAY take advantage of this knowledge to populate the answer of a question by retrieving data from resource elements other than
Observation.value
and Observation.component.value
.item.code
while other questions in the same form might be populated based on queries, FHIRPaths and/or CQL
specified in the form.Profile: | SDC Questionnaire Populate - Expression profile |
---|---|
Relevant Extensions: | |
Example Questionnaires: |
This approach to population is more generic. It supports retrieving data from any queryable FHIR resources available on the source system. Those queries can be based on the context in which the QuestionnaireResponse is being generated and/or on the results of other queries. Furthermore, it permits FHIRPath and CQL operations to be done on the resulting data such as calculations, conditional determinations, etc. As such, it is significantly more powerful than the Observation-based method. However, it also requires skill in using FHIR queries, FHIRPath, and/or CQL so it requires more technical expertise than the Observation-based approach.
To use this method:
launchContext
extension to identify any contextual information
that needs to be passed into the population process. Typical contexts would be the Patient or Encounter resources in whose context the questionnaire is
being completed, but other elements are also possible (e.g. an AdverseEvent if performing an adverse event report). These 'context' elements will be
available as expression variables for use in subsequent steps. variable
extension to query for any additional data required, possibly based on
context variables set in the previous step, and/or other variable extensions. (NOTE: Elements SHALL
be evaluated in the following order: questionnaire-launchContext
elements, then all Questionnaire-level variables in order of appearance in the Questionnaire.)itemPopulationContext
on group items to establish the context for
a group. When populating the questionnaire, this will do two things: it will create a group repetition for each row returned from the query; and it will
set the specified variable name to that resource repetition for use in processing descendant items of the group.
InitialExpression
and itemPopulationContext
will only be evaluated once for a given item in a questionnaire. For most items, this is during the initial population; however, it can also occur when a new repeating item (group or question answer with child items) is added. In this case, the contextExpression
would be empty—as the repetition has no context from the evaluation. However, all the descendant items of the group or answer with initial.value[x]
or initialExpression
would be evaluated.
For example, defaulting a date item to today()
or to the patient's birth date plus 6 months would result in an answer being populated (because the expression doesn't use context). In a different example, with a repeating group with a contextExpression
of Patient.contact
, the evaluation of a new repetition of the contact group will not have a context value and thus any population instructions tied to that context would not result in answers being populated.
variable
extension on items as well to perform intermediary calculations or
additional queries that are based on itemPopulationContext values.initialExpression
to
cause the initial answer for the question to be set to the specified expression. This should always be a FHIRPath or CQL expression that resolves to an item of the
appropriate type unless the element has a type of Reference, in which case the expression can ALSO be a FHIR query - and the item will be populated with a
reference to the resource. Another exception is for an element of type Attachment, the query can return a Binary or DocumentReference,
with the former populating the Attachment.content and the latter populating content and/or url, depending on what is present in the DocumentReference.
Note, this extension SHALL NOT
appear on groups.sdc-questionnaire-candidateExpression
to make available a list of possible answers for the user to choose from. As with initialExpression, this should always be a FHIRPath or CQL expression that resolves to
an item of the appropriate type unless the element has a type of Reference, in which case the expression can be a FHIR query - and any selected item will
be populated with a reference to that resource.sdc-questionnaire-contextExpression
to
indicate the resources to make available for display to the user to aid in answering the question. The information SHOULD be made available through user
action (clicking a button or link to launch a separate window/dialog) rather than being presented by default.Considerations and rules when using this approach:
candidateExpression
or contextExpression
extensions resolve to an empty set, do not display them.initialExpression
extensions.
Because the launch context might vary each time the QuestionnaireResponse is opened or edited, by populating launchContext
extensions into the values of (possibly hidden)
questions via initialExpression
extensions, the 'original' context in which the QuestionnaireResponse was created can be retained..initialExpression
, candidateExpression
or contextExpression
extensionwill return a resource, backbone element or complex data type, the
choiceColumn
extension can be used to control which data elements should be
exposed to the user (and what labels and widths should be allocated to each element so exposed).candidateExpression
or contextExpression
extension, consider whether there should be a preceding 'display' item that provides
instructions on how to filter from the available candidates or how to make use of the available context in answering the question.initial.value
or initialExpression
expression is used if it resolves; if not then candidateExpression
extension is used. A link to contextExpression
extension content can be present with either of the modes as it may help the user in verifying the content.initialExpression
, calculatedExpression
or candidateExpression
extension disagrees with the type of the item, with the following exceptions:
Resource
can map to a Reference
item type (populating the reference property with the resource type and id, optionally populating the display)
Quantity
can map to an integer
or decimal
item type provided that the
unit
extension is present to allow determination of what unit to
match on/convert to. However, if the Observation selected for population is a Quantity with a comparator (e.g., "greater than", "less than", etc.), then that
Observation cannot be used for population as the semantics of the comparator would be lost.
code
can be mapped to a coding
item type if the value can be uniquely resolved within its answer space,
and will be converted to the coding in the QuestionnaireResponse item answer (populating the provided code, and appropriate system value)
itemPopulationContext
and
questionnaire-itemExtractionContext, then the value will be repeated for both extensions.initialExpression
evaluates to a collection size that exceeds the maximum cardinality requirements of the item, the form filler has 3 options:
initialExpression
as if it were a candidateExpression
and give the user a chance to choose from amongst the results being returned; orSHALL
populate what occurrences it can. The user can then add in additional repetitions as
needed.variable
extension on the nearest
common ancestor in which all relevant questions or variables are descendants. The question will then have an initialExpression
extension that references that
calculated value. The reason for this is that FHIRPath only has access to the current context node and its descendants, not siblings or ancestors. However,
if it is known that there can only be one item with a particular linkId, then the value of that answer can be accessed directly by using
%context.descendants().select(item).where(linkId='someLinkId').answer
SHALL NOT
replace already filled in answers without user approval.
If a Library
has a parameter with a name
that corresponds to the name of a launch context, then the value for the launch context is made available as that parameter. Any parameters that do not correspond to launch contexts will generally not be made available to the library as there is no mechanism (other than Library-specific code) to know what content to make available. If there are multiple launch parameters with the same code
(but different code systems) that correspond to a Library parameter name, there is no standard mechanism to determine which launch context value to pass to the parameter.
Profile: | Extractable Questionnaire - StructureMap |
---|---|
Relevant Extensions: | |
Example Questionnaires: | FHIRPath Pre-pop Source Query |
The StructureMap approach is the most sophisticated approach of the three - and the most powerful. It allows iteration of groups based on repeating elements within resources, supports concept translation using structure maps and provides access to transformation capabilities not available with the Expression-based approach. It also allows the conversion process between data and Questionnaire to be maintained independently and to draw on shared sources across Questionnaires. This can be an advantage in certain environments where the content of the questionnaire may need tight control, but the data environment can be more dynamic. This comes at the cost of requiring expertise in the FHIR mapping language, which is not (yet?) a common skill.
To use this method:
launchContext
extension to
identify any contextual information that needs to be passed into the population process. Typical contexts would be the Patient or Encounter resources in
whose context the questionnaire is being completed, but other elements are also possible (e.g. an AdverseEvent if performing an adverse event report).
These 'context' elements will be available as expression variables for use in subsequent steps.sdc-questionnaire-sourceQueries
extension which SHALL
point to a
Batch consisting of one or more queries to execute. Prior to executing, FHIRPaths embedded in
the queries (referring to elements from the questionnaire-launchContext variables) SHALL
be resolved.sourceStructureMap
extension. This SHALL
define a transform
between the Bundle of Bundles that will result from executing the sourceQueries Batch and a QuestionnaireResponse that complies with the Questionnaire.For example:
To populate the QuestionnaireResponse, evaluate the FHIRPaths in the sourceQueries batch, execute the sourceQueries batch and then execute the StructureMap on the resulting Bundle. The result of that will be the pre-populated QuestionnaireResponse.
Considerations when using this approach: