Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Personal/wiy/support observation category #26

Merged
merged 6 commits into from
Jan 17, 2020

Conversation

wi-y
Copy link
Contributor

@wi-y wi-y commented Jan 15, 2020

added support for observation category

@@ -9,6 +9,10 @@ namespace Microsoft.Health.Fhir.Ingest.Template
{
public class CodeValueFhirTemplate : FhirTemplate
{
#pragma warning disable CA2227
public virtual IList<FhirCodeableConcept> Category { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be IList like the "Codes" property below?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see, Codes is a singular CodeableConcept (list of codes), whereas Category is a list of CodeableConcepts: https://www.hl7.org/fhir/observation.html

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap! Confusing at first but it makes sense. It is something Will and I talked through today. For codes it is singular codeable concept because it is still one concept but there could be different code systems (LOINC, SNOMED, etc). Categories is different. You could have two different concepts say something is a vital sign as well as a iomt.

@@ -81,6 +86,12 @@ protected override Observation MergeObservationImpl(CodeValueFhirTemplate templa

existingObservation.Status = ObservationStatus.Amended;

existingObservation.Category = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to eliminate the categories on the existing observation? Are we assuming that the only ones there are the ones from our template?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is an assumption the connector "owns" the observations it creates. As a side note I don't think that is described in our documentation so we should add that where appropriate. On to the behavior I would prefer a union of the categories but this also works. A union would be problematic with the current data we have since it is an array of array and the intersection isn't entirely clear. It would also open us up to weird cases like if the template had the same codes duplicated across multiple categories in the array.

The question becomes if a template is changed while an observation is in progress what do we want to happen? Right now the categories from the latest template win, so if it was vital signs but now just iomt, then iomt will be what is in the final observation. This is slightly different from how we handle codes where we just append what is in the template but never remove what isn't found. I would prefer the logic match but complexity is different for this scenario. I am okay with this approach if the rest of the team is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's up for debate, but my preference is to overwrite.

To me it seems strange to have one system sending in a category for an observation and then have another system send in another category for the same observation. I would assume that both systems would be consistent and send the same category for the same observation.

I don't mind pulling out this particular line of code though. If no category is specified in the template then this line wipes out the category if it previously existed in the observation, which is a bit controversial.

If we remove this line then we only overwrite if there is a category specified in the template. However, as a minor side effect, there would be no way to delete a category.

Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine keeping it. Wiping out is fine since if that is the template change there won't be a category for observations going forward.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So just to make sure the only way this changes is template changes, so overwrite going forward is OK with me and we would have to assume some consistency due diligence on the template managers part. Also if it runs through a profile on the way in that could also help with enforcement/consistency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sordahl-ga through the connector/tool that is correct. Changing the template is the only way to make modifications. If an organization allowed observations created by the connector to be edited by others there could be an issue but our position is the connector should own the observations it creates and they aren't mutable by other actors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dustinburson I was thinking of a use case (and maybe this is an incorrect usage of category) where a system would analyze observations and flag them for some reason (possibly for further investigation, or it's out of the norm or some other reason). Our system would then wipe that out if another reading in that time window comes in.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LiquidPT The scenario makes sense but I don't think that is an appropriate use of category according to the FHIR spec. More appropriate would be using another observation that references the device one with an interpretation or a risk assessment. If the underlying observation needs to be modified for the purpose you describe using the interpretation property (https://www.hl7.org/fhir/observation-definitions.html#Observation.interpretation) or an extension seems more appropriate.

@@ -542,5 +542,60 @@ public void GivenTemplateWithComponentAndObservationWithOutComponent_WhenMergObs
&& v.end == boundary.end
&& v.values.First().Item2 == "v2"));
}

[Fact]
public void GivenTemplateWithCategory_ThenCategoryReturned()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add another test where we merge observations with categories? Would help us solidify what we expect from that and ensure it's working as expected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed another test for the merge should be added. Please also cover the case of that existing codes are replaced during the merge. This will help establish that the behavior is intended.

Assert.Equal("a", observation.Category[0].Coding[0].Code);
Assert.Equal("b", observation.Category[0].Coding[0].Display);
Assert.Equal("c", observation.Category[0].Coding[0].System);
Assert.Equal("category text 1", observation.Category[0].Text);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there not be a second coding (d;e;f) in here to test for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Will update the test

@@ -322,6 +322,7 @@ The CodeValueFhirTemplate is currently the only template supported in FHIR mappi
| --- | ---
|**TypeName**| The type of measurement this template should bind to. There should be at least one DeviceContent template that outputs this type.
|**PeriodInterval**|The period of time the observation created should represent. Supported values are 0 (an instance), 60 (an hour), 1440 (a day).
|**Category**|Any number of [Codings](http://hl7.org/fhir/datatypes-definitions.html#coding) to classify the type of observation created.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't more accurate to say any number of codeable concepts and link the codeable concept definition?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree

@@ -81,6 +86,12 @@ protected override Observation MergeObservationImpl(CodeValueFhirTemplate templa

existingObservation.Status = ObservationStatus.Amended;

existingObservation.Category = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is an assumption the connector "owns" the observations it creates. As a side note I don't think that is described in our documentation so we should add that where appropriate. On to the behavior I would prefer a union of the categories but this also works. A union would be problematic with the current data we have since it is an array of array and the intersection isn't entirely clear. It would also open us up to weird cases like if the template had the same codes duplicated across multiple categories in the array.

The question becomes if a template is changed while an observation is in progress what do we want to happen? Right now the categories from the latest template win, so if it was vital signs but now just iomt, then iomt will be what is in the final observation. This is slightly different from how we handle codes where we just append what is in the template but never remove what isn't found. I would prefer the logic match but complexity is different for this scenario. I am okay with this approach if the rest of the team is.

@@ -542,5 +542,60 @@ public void GivenTemplateWithComponentAndObservationWithOutComponent_WhenMergObs
&& v.end == boundary.end
&& v.values.First().Item2 == "v2"));
}

[Fact]
public void GivenTemplateWithCategory_ThenCategoryReturned()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed another test for the merge should be added. Please also cover the case of that existing codes are replaced during the merge. This will help establish that the behavior is intended.


var observation = processor.CreateObservation(template, observationGroup);
Assert.Equal("a", observation.Category[0].Coding[0].Code);
Assert.Equal("b", observation.Category[0].Coding[0].Display);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use the Assert.Collection() function to iterate through a collection and then supply lambda's for each collection index. Results in a little cleaner syntax and better error messages in the test output then things aren't correct. There are examples in other tests here like GivenTemplateWithComponent_WhenCreateObservation_ThenObservationReturned_Test.

new CodeableConcept
{
Text = category.Text,
Coding = category.Codes.Select(code => new Coding { System = code.System, Code = code.Code, Display = code.Display })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will want to make sure a text only category but null codings works correctly as well. I believe this code will error if the category codes are null.

Copy link
Contributor Author

@wi-y wi-y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated code/tests to address feedback

@wi-y wi-y merged commit 9978ef3 into master Jan 17, 2020
@dustinburson dustinburson deleted the personal/wiy/support-observation-category branch November 8, 2022 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants