Which DICOM fields can I query with Orthanc?

Hello all,

I’m still a bit new to DICOM and Orthanc, and am in the process of evaluating Orthanc to see if it’s a fit for my use-case.

I’d like to learn a little bit more about how to query Orthanc. I know the DICOM spec contains a lot of data fields, and that Orthanc doesn’t index all of them. Is it possible to search on a data field if it is not indexed by Orthanc? If it is not indexed by Orthanc, is there a way to tell Orthanc to index it? Is there a list I can look at that contains all the data fields that are indexed by Orthanc?

For example, I would like to get all DICOMs with a given Device Serial Number (0018,1000) . Is it possible to do a query on Device Serial Number through the DICOMWeb Plugin? Is it possible through the Orthanc REST API? Is it possible through the DICOM protocol itself? What if I want to query on Institution Name (0008,0080)?

Also, is there any way to query Orthanc using a “logical or” operator? Such as : “Give me all the DICOMs with a Device Serial of 10001, 10002, OR 10003”

Thanks for taking a look at this!

Hello,

Is it possible to search on a data field if it is not indexed by Orthanc?

Yes: Check out the “StorageAccessOnFind” configuration option. By default, if a tag is not indexed, Orthanc will read the full DICOM file from its storage area to extract the tag (obviously, this operation is costly):
https://groups.google.com/g/orthanc-users/c/0VvppRkzGXw/m/Vz5VPW9xBgAJ

If it is not indexed by Orthanc, is there a way to tell Orthanc to index it? Is there a list I can look at that contains all the data fields that are indexed by Orthanc?

As of Orthanc 1.8.2, you cannot index more tags. The so-called “main DICOM tags” are the only ones to be indexed in the database, and their list can be found in the “DicomMap.cpp” source file:
https://hg.orthanc-server.com/orthanc/file/Orthanc-1.8.2/OrthancFramework/Sources/DicomFormat/DicomMap.cpp#l48

For example, I would like to get all DICOMs with a given Device Serial Number (0018,1000) . Is it possible to do a query on Device Serial Number through the DICOMWeb Plugin?

Yes:

$ curl https://demo.orthanc-server.com/dicom-web/series?0018,1000=0000000843815bmr

Is it possible through the Orthanc REST API?

Yes:

$ curl https://demo.orthanc-server.com/tools/find -d ‘{“Level”:“Series”,“Query”:{“DeviceSerialNumber”:“0000000843815bmr”},“Expand”:true}’

Is it possible through the DICOM protocol itself?

Yes:

$ findscu localhost 4242 -S -k QueryRetrieveLevel=SERIES -k DeviceSerialNumber=0000000843815bmr

What if I want to query on Institution Name (0008,0080)?

$ curl https://demo.orthanc-server.com/dicom-web/studies?0008,0080=HUG

$ curl https://demo.orthanc-server.com/tools/find -d ‘{“Level”:“Study”,“Query”:{“InstitutionName”:“HUG”},“Expand”:true}’
$ findscu localhost 4242 -S -k QueryRetrieveLevel=STUDY -k InstitutionName=HUG

Also, is there any way to query Orthanc using a “logical or” operator? Such as : “Give me all the DICOMs with a Device Serial of 10001, 10002, OR 10003”

In the examples below, we look for serial numbers “0000000843815bmr” or “10”:

$ curl https://demo.orthanc-server.com/dicom-web/series?0018,1000=0000000843815bmr%2C10
$ curl -s https://demo.orthanc-server.com/tools/find -d ‘{“Level”:“Series”,“Query”:{“DeviceSerialNumber”:“0000000843815bmr\10”},“Expand”:true}’
$ findscu localhost 4242 -S -k QueryRetrieveLevel=SERIES -k DeviceSerialNumber=0000000843815bmr\10

Note that “%2c” in the DICOMweb version corresponds to the URL encoding of the comma.

Sébastien-

Thank you for the response – super helpful! I do have a couple follow-up questions, because I’m a little bit confused.

  1. I see that you are able to query for Device Serial Number. However, when I look at the file you linked (DicomMap.cpp), I don’t see Device Serial Number or the code 0018,1000 listed in that file. Am I looking in the wrong place? Apologies, I’m a Python programmer and don’t know C++ very well.

  2. You mention the StorageAccessOnFind option. If I have that turned on, what happens when I do a lookup on a DICOM field that is indexed? Will it search the index? Or will it read the full DICOM file?

Thanks again for helping me out!

The DicomMap.cpp does not mention all the tags, but only the ones that are actually indexed in the database.

1- As written by BGO, there are 2 categories of DICOM tags: The ones that are indexed in the SQL database (those are the “main DICOM tags”, whose list is in the aforementioned “DicomMap.cpp”), and the ones that are not indexed (those ones must be read from the storage area when accessed).

Because DICOM tags are extremely numerous, we only index the subset of DICOM tags that are the most commonly used in medical imaging applications (hence “main DICOM tags”). The other tags are only accessed when needed.

For instance, when doing a query, Orthanc will first filter the indexed tags (i.e. the “main DICOM tags”) using its SQL index. In a second time, if “StorageAccessOnFind” configuration option is “Always”, the non-indexed tags will only be read for the remaining candidates. It is thus highly advised to do queries that include indexed tags in order to limit the number of possible candidates.

2- This is explained in the documentation of the “StorageAccessOnFind” option:

https://hg.orthanc-server.com/orthanc/file/Orthanc-1.8.2/OrthancServer/Resources/Configuration.json#l574

// Performance setting to specify how Orthanc accesses the storage
// area during C-FIND. Three modes are available: (1) “Always”
// allows Orthanc to read the storage area as soon as it needs an
// information that is not present in its database (slowest mode),
// (2) “Never” prevents Orthanc from accessing the storage area, and
// makes it uses exclusively its database (fastest mode), and (3)
// “Answers” allows Orthanc to read the storage area to generate its
// answers, but not to filter the DICOM resources (balance between
// the two modes). By default, the mode is “Always”, which
// corresponds to the behavior of Orthanc <= 1.5.0.
“StorageAccessOnFind” : “Always”,

=> Orthanc will always use its database index wherever possible. If some queried tag is not indexed (i.e. if it is not a “main DICOM tag”), the behavior depends on this option.

Thank you for the thoughtful, in-depth responses. One more question along these lines : if I use the PostgreSQL plugin and I store my DICOM files in Postgres ( “EnableStorage” : true), what happens when I query for a tag that is not indexed? Does it download the full DICOM file from Postgres and then search through the document inside the Orthanc server? Or does the document search happen inside Postgres, using Postgres’s full-text search feature?

–Jeremy

The first answer is the correct one: If non-indexed tags are queried, Orthanc will download the file from PostgreSQL and do the parsing/search by itself in order to retrieve the value of the tags. PostgreSQL is not used for full-text search.

Also, note that Orthanc doesn’t retrieve the full DICOM file from the storage area (may it be the filesystem or PostgreSQL). Instead, Orthanc uses the so-called “DICOM-as-JSON” attachment: This is a precomputed JSON summary of the full DICOM file (this summary notably doesn’t include the pixel data information):
https://book.orthanc-server.com/faq/orthanc-storage.html#storage-area

This summary is typically 10 ten times smaller than the full DICOM file. So, the amount of data to be retrieved from PostgreSQL is much smaller than the size of the DICOM file.

Note that we plan to replace the “DICOM-as-JSON” mechanism in future versions of Orthanc, in favor of a “range request” to only retrieve the portion of the DICOM file up to its pixel data.

Sébastien-

Hello all,

I’ve found this topic searching for a way to query single fields of Orthanc database using cURL or DCMTK.
Can anyone explain how to query the values highlighted in the attached image?
Out at the top of the picture the parent folders for the first highlighted value are the same than the second one except for the root hint that is 0022.1007 that is Right Eye.
Thanks for taking a look at my question

Simplest solution is probably to retrieve the tags in Json format through http://localhost:8042/instances/../tags and then parse the json to extract the value.

Thanks Alain
I’ll test it tomorrow and let you know, thanks