Stream: shorthand
Topic: Snapshot versus Differential in FSH
Hank Lenzi (Jan 19 2022 at 22:20):
Say I have a full spec (see below, for an Immunization profile template). The question is: is I define the whole spec (by which I mean: all the elements composing the Immunization Resource), then do I have a Snapshot? And if I only define some, then is is what I have a Differential?
// Following the tutorial: https://www.youtube.com/watch?v=gPt_ZSpZlCc&t=425s
// https://simplifier.net/DevDaysImmunization/ImmunizationProfile/~overview
// Modifies: https://www.hl7.org/fhir/immunization.html
// It seems sushiconfig.yaml already defines a lot of stuff, so how much should we put of metadata here???
// AAAAAHHHH → what sushi-yaml defines are IMPLEMENTATION GUIDE PROPERTIES. IT SAYS SO IN THE FILE ITSELF
// THE AUTHOR OF THE TUTORIAL IS USING ANOTHER TOOL - WE'LL DO AS HE SAYS
Profile: ImmunizationProfile // Name
Parent: Immunization
Id: immunization-profile
Title: "Immunization profile"
Description: "This profile represents the contraints applied to the RESOURCE Immunization as determined by the medical regulatory authorities"
// metadata: https://www.hl7.org/fhir/structuredefinition.html#metadata
* ^meta.lastUpdated = "2022-02-18T19:37:00.003+00:00"
* ^language = #pt-BR
* ^url = "http://hank.lenzi.55/fhir/StructureDefinition/Immunization"
* ^version = "202201A"
* ^status = #draft // draft | active | retired | unknown See: https://www.hl7.org/fhir/valueset-publication-status.html
* ^experimental = true // SD was drafted for education purposes
* ^date = "2020-03-11T18:20:06.3399184+00:00"
* ^publisher = "Hank Lenzi"
* ^purpose = "Learn FHIR through FSH"
// content = #complete
// contact
// useContext 0..
// jurisdiction 0..
// keyword 0..
// copyright 0..1
// fhirVersion 0..1
// mapping 0..
// kind 1..1 (primitive-type | complex-type | resource | logical) Type: StructureDefinitionKind // It's implicitely a Resource, becasue the Parent is the RESOURCE Immunization. This ain't JSON!
// type data Type is a "uri". If it were JSON, you wold say: "type": "Immunization". This is implicit in FSH.
// context 0.. IF AN EXTENSION. This is a PROFILE
// contextInvariant 0..
// derivation - if this were JSON: "derivation": "contraint",
// description (markdown)
// ---------------------------------- END OF COMMON PART FOR STRUCTURE DEFINTIONS --------------------------------------------//
// ---------------------------------------------------------------------------------------------------------------------------//
// NOTE: WHAT YOU HAVE TO MATCH FROM HERE DOWN IS THE "IMMUNIZATION" RESOURCE https://www.hl7.org/fhir/immunization.html
// NOTE: The first item on the Resource Immunization structure is the DomainResource - which is the very Immunization resource.
// NOTE: The Resource Immunization page also duments the TERMINOLOGY BINDINGS for it: https://www.hl7.org/fhir/immunization.html#tx
// NOTE: The following Terminology bindings apply:
// Immunization.status A set of codes indicating the current status of an Immunization. Required ImmunizationStatusCodes
// Immunization.statusReason The reason why a vaccine was not administered. Example ImmunizationStatusReasonCodes
// Immunization.vaccineCode The code for vaccine product administered. Example VaccineAdministeredValueSet
// Immunization.reportOrigin The source of the data for a record which is not from a primary source. Example ImmunizationOriginCodes
// Immunization.site The site at which the vaccine was administered. Example CodesForImmunizationSiteOfAdministration
// Immunization.route The route by which the vaccine was administered. Example ImmunizationRouteCodes
// Immunization.performer.function The role a practitioner or organization plays in the immunization event. Extensible ImmunizationFunctionCodes
// Immunization.reasonCode The reason why a vaccine was administered. Example ImmunizationReasonCodes
// Immunization.subpotentReason The reason why a dose is considered to be subpotent. Example ImmunizationSubpotentReason
// Immunization.programEligibility The patient's eligibility for a vaccation program. Example ImmunizationProgramEligibility
// Immunization.fundingSource The source of funding used to purchase the vaccine administered. Example ImmunizationFundingSource
// Immunization.protocolApplied.targetDisease The vaccine preventable disease the dose is being administered for. Example ImmunizationTargetDiseaseCodes
// EXAMPLE (INSTANCE): See below.
// We just go to the page for the Resource Immunization and copy stuff here
// identifier 0..
// -------------------------------------------- MANDATORY --------------------------------------------------------/
// status 1..1 ?!(←isMOdifier) (completed | entered-in-error | not-done) Type: code Immunization Status Codes
status 1..1
// --------------------------------------------------------------------------------------------------------------/
// statusReason 0..1 Type: CodeableConcept Immunization Status Reason Codes
// -------------------------------------------- MANDATORY --------------------------------------------------------/
// vaccineCode 1..1 Type: CodeableConcept Vaccine Administered Value Set
vaccineCode 1..1
// --------------------------------------------------------------------------------------------------------------/
// -------------------------------------------- MANDATORY --------------------------------------------------------/
// patient 1..1 Type: Reference(Patient)
patient 1..1
// --------------------------------------------------------------------------------------------------------------/
// encounter 0..1 Type: Reference(Encounter)
// -------------------------------------------- MANDATORY --------------------------------------------------------/
// occurrence[x] 1..1
// +---------------> occurrenceDateTime Type: dateTime
// +---------------> occurrenceString Type: string
occurrence[x]
// --------------------------------------------------------------------------------------------------------------/
// recorded 0..1 Type: dateTime
// primarySource 0..1 Type: boolean
// reportOrigin 0..1 CodeableConcept
// location 0..1 Reference(Location)
// manufacturer 0..1 Reference(Organization)
// lotNumber 0..1 Type: string
// expirationDate 0..1 Type: date
// site 0..1 Type: CodeableConcept Codes for Immunization Site of Administration
// route 0..1 Type: CodeableConcept Immunization Route Codes
// doseQuantity 0..1 Type: SimpleQuantity
// ------------------------------ PART OF THE PROFILING SPECIFICATION ----------------------------------------/
// performer 0.. Type: BackboneElement
// +--------------> function 0..1 Type: CodeableConcept Immunization Function Codes (Extensible)
// +--------------> actor 1..1 Type: Reference(Practitioner | PractitionerRole | Organization)
* performer 1..1 // there must be a performer
* performer.function 0..1
* performer.actor only Reference(PractitionerRole) // the performer must be played by the PratictionerRole
// --------------------------------------------------------------------------------------------------------------/
// note 0.. Type: Annotation
// reasonCode 0.. Type: CodeableConcept Immunization Reason Codes
// subpotentReason 0.. CodeableConcept Immunization Subpotent Reason
// ------------------------------ PART OF THE PROFILING SPECIFICATION ----------------------------------------/
// education 0.. Type: BackboneElement
// +--------------> documentType 0..1 Type: string
// +--------------> reference 0..1 Type: uri
// +--------------> publicationDate 0..1 Type: dateTime
// +--------------> presentationDate 0..1 Type: dateTime
* education 0..0
// --------------------------------------------------------------------------------------------------------------/
// programEligibility 0.. CodeableConcept Immunization Program Eligibility
// fundingSource 0..1 // +--------------> Type: CodeableConcept Immunization Funding Source
// ------------------------------ PART OF THE PROFILING SPECIFICATION ----------------------------------------/
// reaction 0..* BackboneElement
// +--------------> data 0..1 dateTime
// +--------------> detail 0..1 Reference(Observation)
// +--------------> reported 0..1 boolean
// --------------------------------------------------------------------------------------------------------------/
// protocolApplied 0..* BackboneElement
// +--------------> series 0..1 string
// +--------------> authority 0..1 Reference(Organization)
// +--------------> targetDisease 0..* CodeableConcept Immunization Target Disease Codes
// +--------------> doseNumber[x] 1..1
// +--------------> doseNumberPositiveInt positiveInt
// +--------------> doseNumberString string
// +--------------> seriesDoses[x] 0..1
// +--------------> seriesDosesPositiveInt positiveInt
// +--------------> seriesDosesString string
//
Thanks.
-- Hank
Chris Moesel (Jan 19 2022 at 23:23):
Hi @Hank Lenzi. I'm not sure if I fully understood your question, but basically:
The differential should contain only those things that are different from the parent. For example, if you change a cardinality from 0..1
to 1..1
then the differential will contain that element (by id
and path
) with the new min
value of 1
. It does not need to contain anything else. Some authors/tools may put unchanged data in the differential, but this is generally not necessary (except in some very limited edge cases where the IG Publisher needs it).
The snapshot contains every element in the structure with all the properties that were defined on each element. It also reflects any of the changed values (from the differential) alongside all the unchanged values. The snapshot is helpful for tooling that wants the whole picture.
So, in FSH, when you define profiles, you're usually specifying only what goes in the differential (w/ the exception of top-level properties like ^publisher
, ^purpose
, etc. that sit outside of the snapshot and differential). When you run SUSHI, it will generate only the differential elements by default. And then when you run the IG Publisher, it will generate the snapshot elements by merging the differential elements into the parent definition. Does that help?
Hank Lenzi (Jan 20 2022 at 11:45):
Gotcha! Thanks!
Last updated: Apr 12 2022 at 19:14 UTC