Skip to content

Conversation

@dmendelowitz
Copy link
Contributor

Summary

A set number of fields can now be specified to be masked with dataAbsentReason extensions in a Patient resource

New behavior

The CSV Patient Extractor and FHIR Patient Extractor can now take an optional constructor argument "mask", which is an array containing any number of fields that are capable of being masked. The specified fields will have their values replaced by dataAbsentReason extensions with the code 'masked'. The fields that can currently be masked are any values the CSV Patient Extractor can take as input (currently "gender", "mrn", "name", "address", "birthDate", "language", "ethnicity", "birthsex" and "race")

Code changes

  • patientUtils.js now has a function called maskPatientData that takes a FHIR bundle with a Patient resource and an array of fields to mask. maskPatientData will modify the bundle to have dataAbesentReason extensions where necessary
  • CSVPatientExtractor.js and FHIRPatientExtractor.js now take an optional argument of a 'mask' array and call maskPatientData with the mask array as the last step of the extraction process.
  • patientUtils.test.js now contains tests for maskPatientData

Testing guidance

  • Ensure that maskPatientData masks specified fields with proper extensions
  • Ensure the output is still a valid FHIR bundle
  • Test the functionality on both the MEF and E-MEF
  • Check that the new tests pass and test a sufficient number of cases

Example config:

For mcode-extraction-framework:
"extractors": [ { "label": "patient", "type": "CSVPatientExtractor", "constructorArgs": { "filePath": "./test/sample-client-data/patient-information.csv", "mask": ["gender","mrn","name","address","birthDate","language","ethnicity","birthsex","race"] } } ]
For epic-mcode-extraction-framework:
"extractors": [ { "label": "patientExtractor", "type": "FHIRPatientExtractor", "constructorArgs": { "mask": ["gender","mrn","name","address","birthDate","language","ethnicity","birthsex","race"] } } ]
(In both configs mask contains all possible fields, feel free to try any combination)

Copy link
Contributor

@julianxcarter julianxcarter left a comment

Choose a reason for hiding this comment

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

This PR looks really good to me! I had two small suggestions that I've made a note of.

I tested this with the Epic-MEF as well and it worked great for the most part. I do think we'll need a smaller PR over there to handle cases within the EpicCancerDiseaseStatusExtractor and EpicTreatmentPlanChangeExtractor where they could potentially try to pull the patient's name for those resources after a user has specified it to be masked. I'm not sure if that's in scope for this task, but just something to consider.

Scratch that, I actually think we could make this change within the getPatientName function in the MEF? We should definitely discuss if that function should return a Masked for privacy reasons value or something like that.

@dmendelowitz dmendelowitz force-pushed the replacing-patient-fields branch from e2ea180 to 9cdcab4 Compare March 17, 2021 17:40
@dmendelowitz
Copy link
Contributor Author

This PR looks really good to me! I had two small suggestions that I've made a note of.

I tested this with the Epic-MEF as well and it worked great for the most part. I do think we'll need a smaller PR over there to handle cases within the EpicCancerDiseaseStatusExtractor and EpicTreatmentPlanChangeExtractor where they could potentially try to pull the patient's name for those resources after a user has specified it to be masked. I'm not sure if that's in scope for this task, but just something to consider.

Scratch that, I actually think we could make this change within the getPatientName function in the MEF? We should definitely discuss if that function should return a Masked for privacy reasons value or something like that.

Is the getPatientName function actually used anywhere in the MEF? I only see it in the patientUtils file and then in the test file. Knowing the context would definitely help with figuring out how it should act when the field is masked.

*/
function getPatientName(name) {
return `${name[0].given.join(' ')} ${name[0].family}`;
return ('extension' in name[0]) ? 'masked' : `${name[0].given.join(' ')} ${name[0].family}`;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looking for opinions on what should actually be returned here when the name field is masked (this is used in EpicCancerDiseaseStatus and EpicTreatmentPlanChange Extractors for context)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the string 'masked' is good! I don't think it's safe to return null or undefined since it might get applied to a required field, and I think it might be too much for right now to support returning a full dataAbsent extesion.

Copy link
Contributor

@jafeltra jafeltra left a comment

Choose a reason for hiding this comment

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

This looks really good! I also just had one small comment, but this is a really cool feature!

*/
function getPatientName(name) {
return `${name[0].given.join(' ')} ${name[0].family}`;
return ('extension' in name[0]) ? 'masked' : `${name[0].given.join(' ')} ${name[0].family}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the string 'masked' is good! I don't think it's safe to return null or undefined since it might get applied to a required field, and I think it might be too much for right now to support returning a full dataAbsent extesion.

@dmendelowitz
Copy link
Contributor Author

I think all comments have been addressed now, give it another look and let me know if anything else comes up

Copy link
Contributor

@jafeltra jafeltra left a comment

Choose a reason for hiding this comment

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

This looks awesome!

Copy link
Contributor

@julianxcarter julianxcarter left a comment

Choose a reason for hiding this comment

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

This looks great to me!

@dmendelowitz dmendelowitz merged commit 836b608 into master Mar 18, 2021
@dmendelowitz dmendelowitz deleted the replacing-patient-fields branch March 18, 2021 15:35
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