FHIR Chat · differentials · implementers

Stream: implementers

Topic: differentials


view this post on Zulip Nick George (Sep 22 2018 at 16:33):

Couple questions about differentials and array elements:
If a base ElementDefinition has elements [A, B, C], and profiled ElementDefinition has [A, modifiedB, C], should the differential include [A, modifiedB, C], or just [modifiedB]? If just [modifiedB], is there a algorithm to finding which element in the snapshot list it corresponds to (e.g., first field with primitive type "id"?

second, I noticed some things we "let slide" in the differential - e.g., constraints on a base definition are copied over to the profile, with the additional "source" field listing the base that they came from, but we don't seem to bother to put that in the differential, presumably because it's implied/derivable/not interesting. are there machine-friendly rules for that? Another example: "base" field - which again is an obvious diff due to the profile-base relationship.

view this post on Zulip Nick George (Sep 22 2018 at 16:36):

(concrete example of point 2: http://hl7.org/fhir/extension-minvalue.json.html . The second "constraint" on "Extension" ElementDefinition lists "Extension" as the source of the constraint, which is technically speaking a diff from the same constraint on the base Extension, but this does not show up in the differential)

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 18:58):

Differential only needs to include the elements that have changed. However, some of the tools depend on the whole hierarchy to reach the elements also be included. So, for example, if you wanted to have a differential that asserted a constraint on Patient.contact.name, you'd have to first include the element for Patient and for Patient.contact. (Though you wouldn't need to say anything about them other than "an element with this path exists".)

There is indeed an "algorithm" for matching elements in a differential to the base and calculating what the snapshot is. But calling it an "algorithm" is a bit misleading. There's over 1000 lines of really complex (and somewhat evil) code in the Java reference implementation and a similar amount in the other reference implementations that do it.

view this post on Zulip Nick George (Sep 22 2018 at 19:21):

interesting, thanks. How about the repeated elements?

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 20:02):

I'm not understanding the question

view this post on Zulip Nick George (Sep 22 2018 at 20:14):

let's say the base definition has a field
[ {id: "A", field: "bar"}, {id: "B", field: "bar"}, {id: "C", field: "baz"} ],
and the profile has, for the same field
[ {id: "A", field: "bar"}, {id: "B", field: "barModified"}, {id: "C", field: "baz"} ]

view this post on Zulip Nick George (Sep 22 2018 at 20:15):

would the differential just list
[{id: "B", field: "barModified"}]
or
[ {id: "A", field: "bar"}, {id: "B", field: "barModified"}, {id: "C", field: "baz"} ]

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 20:16):

Well, what you'd actually have is:
ids of A, A.A, A.B and A.C
The differential would have A and A.Bmodified

view this post on Zulip Nick George (Sep 22 2018 at 20:19):

so,
[ {id: "A"}, {id: "B", field: "barModified"}, {id: "C"} ]
?

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 20:27):

I'm not sure what "field" is. You're going to have a dot-separated path. And you have to have an element for the "root" as well as for the element that was modified.

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 20:28):

So if we take a real example of the Patient resource and you've modified Patient.name (e.g. made minOccurs=1), then you'd have one element with path "Patient" and another with element "Patient.name". You wouldn't bother including Patient.identifier, Patient.gender, Patient.id, etc.

view this post on Zulip Nick George (Sep 22 2018 at 20:31):

I'm tlaking about on the ElementDefinition itself. So, say e.g., you can have 3 constraints on the base definition. On my profile, I have the same three constraints, but I've changed the severity of the middle one

view this post on Zulip Nick George (Sep 22 2018 at 20:32):

so for the differential for that element definition, we'll need a field for constraints

view this post on Zulip Nick George (Sep 22 2018 at 20:32):

in this case the array above is of constraints, and field is severity

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 20:41):

Ah. To be honest, I don't know what the tooling will do there. I don't know that we've had anyone who's ever tried to change the severity of a constraint (as opposed to just adding a new one). In principle, you should only have to list the changed one and specify the same "key". Whether that'll work or not, you'll need to test. (And if it doesn't work, submit a change request.)

view this post on Zulip Nick George (Sep 22 2018 at 20:58):

fair enough, thanks. I'm not sure what you mean by "work" though - I'm writing my own tooling here and am curious what the correct behavior would be.

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 21:01):

The intention is that if the key is the same, it's recognized as the same constraint. "Work" = work with the existing reference implementations that perform snapshot generation. I don't think we have a test-case that covers this scenario.

view this post on Zulip Lloyd McKenzie (Sep 22 2018 at 21:03):

If you're creating your own tooling to determine a snapshot based on a differential, my first recommendation is "don't" - we've spent many hundreds of person-hours on the software in the reference implementations trying to cover most of the edge cases. If you do really want to build your own, then at least look at the test cases included as part of the Java reference implementation.

view this post on Zulip Nick George (Sep 22 2018 at 21:07):

heh that's fair - it's a bit of a strange use case though, I'm not sure existing implementations will cover what we're trying to do. Thanks a lot for your help!

view this post on Zulip robert worden (Sep 23 2018 at 20:15):

has anyone tried to write down a mathematical spec of what a differential means, i.e how it defines snapshot? It's a shame to have such an important part of FHIR defined by test cases and ugly code.

view this post on Zulip Lloyd McKenzie (Sep 23 2018 at 20:37):

The gist of how it works is defined on the profiling page. No clue how you'd describe slicing, default slices, re-slicing, etc. mathematically...

view this post on Zulip Michel Rutten (Sep 24 2018 at 11:25):

Hi @robert worden, I agree. Fortunately, @Chris Grenz has made a serious effort trying to describe the rules for generating a snapshot:
https://github.com/chrisgrenz/FHIR-Primer/wiki/Snapshots-Determining-Refines

view this post on Zulip Michel Rutten (Sep 24 2018 at 11:34):

FYI The implementation of the snapshot generator in the .NET API generates and handles sparse differentials. Unconstrained elements can be safely omitted from the differential, as defined by the FHIR spec. The .NET logic is smart enough to deal with orphaned elements in the sparse diff representation. However as Lloyd mentions, the open source publication tooling does not (yet) handle orphaned elements.


Last updated: Apr 12 2022 at 19:14 UTC