behavior of using /xapi/dqr/import/ endpoint and relabel mapping

101 views
Skip to first unread message

Sharif Elguindi

unread,
May 13, 2024, 10:17:14 AMMay 13
to xnat_discussion
Hello All!

For our XNAT projects we typically label the Subject to the patient ID tag (0010, 0020) in dicom.  We are setting up some REST API scripts that call to import scans into XNAT projects using the /xapi/dqr/import/ endpoint.  When doing this, we use the 'relabel map' option in the json data we send when doing this to put the scans in the appropriate project/subject/session.  In this, we specifically specify the Subject should be the patientID.  It seems that when doing this, the DICOM patient name tag gets overridden to the patientID and this is the default for XNAT?

How do we stop that from happening when doing this? 

A sample REST API script with python looks something like this:

relabel_map = {
"Session": session,
"Subject": series_info["patientId"]
}

headers = {"accept": "application/json", "Content-Type": "application/json"}
import_URL = f"{env('XNAT_IP')}/xapi/dqr/import"

import_data = {
"aeTitle": "ae_title",
"forceImport": "true",
"pacsId": str(pacs_id),
"port": "port_of_ae",
"projectId": proj,
"studies": [
{
"relabelMap": relabel_map,
"seriesInstanceUids": [series_info["seriesInstanceUid"]],
"studyInstanceUid": studyUID,
"patientID": series_info["patientId"],
}
],
}

response = requests.post(
import_URL,
headers=headers,
data=str(import_data).replace("'", '"'),
auth=HTTPBasicAuth(env("XNAT_USERNAME"), env("XNAT_PASSWORD")),
verify=False,
)
We are on XNAT v.1.8.9.2.  

Sharif Elguindi

unread,
May 13, 2024, 11:31:56 AMMay 13
to xnat_discussion
I think I may have answered my own question, but want to post here to confirm with the experts!

We can just need to configure the site-wide custom Subject Routing rule to use the patient ID. This would be the first rule in the mapping of Project/Subject/Session.  for our use case, we just want to match any number or characters in the patientID like this:

(0010,0020):(\w+)

Am I thinking about this correctly? thank you!

Sharif Elguindi

unread,
May 15, 2024, 10:27:20 PMMay 15
to xnat_discussion
I am still having issues with this, so hoping I can get some advice. 

We have a DQR plugin that we are making import requests through with the XNAT REST API.  Generally we want to have control over the Subject and Session names using the relabelMap parameter.  When we do this, the patient name in the dicom files gets replaced with the Subject - in this case the patientID.  How do we stop that behavior - we want to preserve the dicom files we import as much as possible.  I have tried many different configurations but am having no luck.  

Is this possible to achieve? Any guidance would be appreciated - thank you!

Charlie Moore

unread,
May 17, 2024, 1:16:22 PMMay 17
to xnat_discussion
Hi Sharif,

I'm not sure if this can really be accomplished right now in DQR cleanly. "Subject" and "Session" are not quite just fields for defining the subject and session labels. They do result in that, yes, but really, they are special shortcuts in DQR remapping designed to do what you are seeing. In particular, specifying "Subject" is designed to overwrite the values in both (0010,0010) Patient Name and (0010,0020) Patient ID with what you provided. "Session" replaces (0008,0050) Accession Number and (0020,0010) Study ID with the provided value. You can overwrite only the Patient Name, for example, by specifying "Relabel Patient Name" instead of "Subject". However, DQR is designed to use the value in Patient Name for assigning the subject label, and as far as I can tell, does not support custom routing (happy to be proven wrong here). The only way I see of accomplishing it is to write a custom DICOM object identifier that extends the DQR one that pulls the subject label from the Patient ID instead.

Thanks,
Charlie Moore

Sharif Elguindi

unread,
May 28, 2024, 2:27:15 PMMay 28
to xnat_discussion
Charlie -

Thanks so much for your reply!  I tried a few more things, like moving the site anonymization script to run before hitting pre-archive via the rest API in this thread, but it didn't change the behavior: https://groups.google.com/g/xnat_discussion/c/0m4PXeRmYGg/m/eVtxcpTCAgAJ

I was able to achieve it in a bit of a hacky way: I simply add a project anonymization script that reads the 'Session' which has the patient name in it, and basically puts it back in the Patient Name.  This does work, but not an ideal solution for us.

I'd like to look into modifying the current DQR plugin so that there is more control over what parts of the DICOM get overridden - are there some tips/docs/code to help me get started?

Appreciate it!

Charlie Moore

unread,
Jun 3, 2024, 1:12:03 PMJun 3
to xnat_discussion
Hi Sharif,

Please do keep in mind that anonymization in XNAT is a complex topic, and so hacks around it may have unintended consequences. In particular, you should double check the XML for one of your sessions (look in the Actions box on the session report page) and make sure that the original pre-anon values haven't been persisted in a way you wouldn't want.

As for DQR, I believe the hardcoding of Patient Name as the tag from which to pull the subject label happens here: https://bitbucket.org/xnatdev/dicom-query-retrieve/src/21888150174c86307d6d556ae94f2e1f5dfef5e0/src/main/java/org/nrg/xnatx/dqr/DicomQueryRetrievePlugin.java#lines-73 . The most future-proof solution I can think of on your end would be to define a new DICOM object identifier in a plugin that is very similar to the one that DQR defines. You could choose a different tag other than Patient Name (I believe you wanted Patient ID), and then you can set up DQR to use your custom DICOM object identifier instead of the out-of-the-box "dqrObjectIdentifier". Note that if you go down this route, it's important that both:
1. You preserve the "RoutedStudyDicomProjectIdentifier" section which is how DQR uses the project you selected earlier in the process as the destination rather than attempting to derive the project ID from the DICOM headers.
2. The name of your DICOM object identifier should start with "dqr" so that the front-end recognizes it as valid for the DQR workflow.

Hopefully that helps.
Thanks,
Charlie Moore

Sharif Elguindi

unread,
Jun 5, 2024, 8:47:11 PMJun 5
to xnat_discussion
Hi Charlie -

Thank you - this is immensely helpful!  The XML does seem fine, but yes I agree we do not want to keep this solution going forward.

Your suggestion of modify the DQR seems feasible for us.  However, we got stuck trying to first build a clone of DQR 2.0.2 per the readme from the bitbucket.  The command: ./gradlew fatJar gives an error: "no task defined for fatJar" ?

We can build it by just running ./gradlew jar, but it fails to install on our XNAT build 1.8.10.1.

Let me know if I can provide additional details - as our first step we are just trying to build our own version of the plugin - before modifying the suggested line to change the default behavior.

Thank you!

John Flavin

unread,
Jun 6, 2024, 10:59:34 AMJun 6
to xnat_di...@googlegroups.com
I believe DQR is built with the xnatPluginJar task. The only plugin that is built with fatJar is the Container Service, and that task name should probably be changed.

--
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/0522eb56-cb23-4b5c-a1b8-6e47e62c8494n%40googlegroups.com.

Sharif Elguindi

unread,
Jun 6, 2024, 5:04:01 PMJun 6
to xnat_discussion
Hi John -

That did the trick!  Thank you!

Now that we are going down this path with adjusting the DQR plugin for our needs, could you also potentially point us to another modification we are hoping to make.  Currently some of our PACs systems create an extra '^' in some dicom tags related to physicians.  Currently, the default behavior of the DQR is to not return any results because this doesn't follow the dicom standard, however, most clinical systems we use ignore this and produce no errors.

Any chance for some hints in the codebase for where this type of logic is coded? thank you very much!

Reply all
Reply to author
Forward
0 new messages