Anonymization [subjects] - Removing patient's name

228 views
Skip to first unread message

Ace Vue

unread,
Jan 24, 2020, 7:49:18 PM1/24/20
to xnat_discussion
Hello Everyone,

     I'm fairly new to writing site-wide anonymization scripts on XNAT. Can anyone provide an example of how I can change a patient's name to a unique randomly generated subject name? I'm using version 1.6. Thanks in advance.

Mike McKay

unread,
Jan 27, 2020, 7:04:57 PM1/27/20
to xnat_discussion
I dont think there is currently any way to do this with a DICOM Edit site-wide anonymization script. You can write a script to change the patient's name, but not to a random name.

However, assuming the data is coming in via an XNAT SCP receiver, you should be able to do this with a fairly new XNAT feature, import processors: https://wiki.xnat.org/pages/viewpage.action?pageId=95224449

You'd need to create a Java class with a process method that would generate a random name from lists of first and last names (taking into account the patient's gender, if important) and set the patient name field in the DICOM object that was passed in to the method.

You'd add the class file to a plugin, make sure its path is in the component scan, put the plugin in your plugins directory, restart Tomcat, and do a REST call with Swagger to create a processor instance at the AfterProjectSet location.

I know Will Horton was interested in adding a real world example of a custom processor to the documentation, and this seems like a good one to use. Either he or Dave Maffitt might be able to help you. Dave is the XNAT team's DICOM Edit expert and recently took over backend development work of DQR and import processors.

-Mike

Herrick, Rick

unread,
Jan 28, 2020, 10:43:41 AM1/28/20
to xnat_di...@googlegroups.com

I think writing an import processor as Mike describes is probably the best approach to this issue. You have a lot of functionality available through XNAT itself and the underlying frameworks to, e.g., access database tables (if the subject ID mappings were stored in a table there), integrate with external systems, and so forth.

 

That said, there's also the option of custom DicomEdit functions in either DicomEdit 4 or 6. Creating a custom function is (in theory) pretty simple:

 

 

The issue with custom functions is that, because custom function classes are lightweight and created on demand, the context available to the function is relatively limited compared to what’s available to import processors. For example, you could basically hack in database access for a custom function, but that would fail when running outside of XNAT. That said, if you know your custom function will never run outside of XNAT and you’re comfortable writing code that would offend purists like me , that does give you another option.

 

--

Rick Herrick

Sr. Programmer/Analyst

Neuroinformatics Research Group

Washington University School of Medicine

Phone: +1 (314) 273-1645

    --

    You received this message because you are subscribed to the Google Groups "xnat_discussion" group.

    To unsubscribe from this group and stop receiving emails from it, send an email to xnat_discussi...@googlegroups.com.

    To view this discussion on the web visit https://groups.google.com/d/msgid/xnat_discussion/a95551fa-3173-4149-94b8-eef6f3e162ae%40googlegroups.com.

   

 


The materials in this message are private and may contain Protected Healthcare Information or other information of a sensitive nature. If you are not the intended recipient, be advised that any unauthorized use, disclosure, copying or the taking of any action in reliance on the contents of this information is strictly prohibited. If you have received this email in error, please immediately notify the sender via telephone or return mail.

Moore, Charlie

unread,
Jan 28, 2020, 11:47:48 AM1/28/20
to xnat_di...@googlegroups.com

Hello Ace,

 

Note: In what follows, I’m assuming you’re importing data into XNAT over C-STORE (using XNAT’s built-in SCP receiver). I’m also assuming you’re not doing anything fancy with specifying special XNAT routing information in the headers. Therefore, the value in DICOM element (0010,0010) Patient Name ends up as the subject’s label in XNAT.

 

There’s not a built-in way to do this, because it’s a bit problematic in the general case. If the script is truly generating random strings for the patient name in each incoming study, XNAT will have no way to tell that 5 studies that just came in should all actually belong to the same subject record in XNAT. If there’s some sort of lookup table in your XNAT to avoid this problem, then now the data isn’t really “anonymized” at all, it’s just been moved to a different spot on the system. If you’re not worried about these issues, then this is definitely a very reasonable request.

 

The previous suggestions are all good, but I think there’s another alternative that hasn’t been covered. First note that the subject label in XNAT will be extracted from the Patient Name DICOM element *before sitewide anonymization is applied*. A discussion of that recently can be found here: https://groups.google.com/forum/#!topic/xnat_discussion/_w8eybtu5jI . Therefore, no matter what script you write, you’re not going to be able to stop the patient name from getting into XNAT unless you either:

1.       Use a “high priority” routing mechanism along with a simple anon script to change the patient name. This is by far the easiest option out of anything mentioned thus far, but it puts all of the complexity *very* early into the process (i.e. at the modality, before even sending to XNAT), so it may not be feasible. Essentially, XNAT has different “passes” for trying to figure out how to assign an incoming study, which are detailed here: https://wiki.xnat.org/pages/viewpage.action?pageId=36373129 . If you used the first pass, you could put the new subject label/patient name in the Patient Comments field. Then, XNAT would assign the subject label based on that, and your anon script could simply be: (0010,0010) := subject. The issues with this approach are that it requires the logic and modifications before XNAT, so presumably this is not feasible.

2.       Write a somewhat clever script *and* move the default site anon processor location. As I mentioned in the thread I linked to earlier, if you use custom processing, you should be able to move site anonymization to before the routing step. Then, the remaining piece is replacing the value in (0010,0010). There’s no built-in way to do this randomly, but there’s a lesser-known function in DicomEdit called “getURL”: https://wiki.xnat.org/display/XTOOLS/DicomEdit+6.2+Language+Reference . Without having to deal with any XNAT code at all, you could write a dirt-simple web server that simply generates a random string and keeps track of what it has generated so far, and then grab a new value in your script when needed. If you’re not worried about collisions, you could probably go even simpler and just grab a random string from something like random.org .

3.       Add a CTP instance as an intermediate DICOM AE and perform the change between the modality and XNAT. That’s also mentioned in the thread linked above.

 

Thanks,

Charlie

 

From: xnat_di...@googlegroups.com <xnat_di...@googlegroups.com> On Behalf Of Herrick, Rick
Sent: Tuesday, January 28, 2020 9:44 AM
To: xnat_di...@googlegroups.com
Subject: Re: [XNAT Discussion] Anonymization [subjects] - Removing patient's name

 

Attention: This email originated from outside the university.

Mike McKay

unread,
Jan 29, 2020, 12:25:45 PM1/29/20
to xnat_discussion
This comment by Charlie is an important one: "If the script is truly generating random strings for the patient name in each incoming study, XNAT will have no way to tell that 5 studies that just came in should all actually belong to the same subject record in XNAT. If there’s some sort of lookup table in your XNAT to avoid this problem, then now the data isn’t really “anonymized” at all, it’s just been moved to a different spot on the system."

You almost certainly don't want a random patient name for every file, which is what would happen if your import processor simply assigned a random patient name every time with no memory of what was assigned before. However, I think there are ways around this without having to store the original patient names in your system. For example, you could have a table with two columns: hash of original patient name and random new name. When a new DICOM file comes in, the process method you wrote would hash its patient name, look for that hash in the table described above, use the previously generated random name if the hash exists, or else generate a new random name and add the patient name hash and that new random name to the table. You could also store the date the row was added and ignore old rows or check other DICOM fields if you don't want a John Smith imported two years from now to be given the same name in XNAT as the John Smith with a totally different date of birth whose data was imported now.

-Mike

    To unsubscribe from this group and stop receiving emails from it, send an email to xnat_discussion+unsubscribe@googlegroups.com.

    To view this discussion on the web visit https://groups.google.com/d/msgid/xnat_discussion/a95551fa-3173-4149-94b8-eef6f3e162ae%40googlegroups.com.

   

 

 


The materials in this message are private and may contain Protected Healthcare Information or other information of a sensitive nature. If you are not the intended recipient, be advised that any unauthorized use, disclosure, copying or the taking of any action in reliance on the contents of this information is strictly prohibited. If you have received this email in error, please immediately notify the sender via telephone or return mail.

--
You received this message because you are subscribed to the Google Groups "xnat_discussion" group.

To unsubscribe from this group and stop receiving emails from it, send an email to xnat_discussion+unsubscribe@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages