Can't run FIND request on server from multitenant plugin

I am trying to run a second dicom server with the multitenant dicom plugin from the official linux release version 12.3. I can connect to the new server with an ECHO request, but trying to send a FIND fails. The Orthanc log shows:

E0320 10:45:40.809692 7f8c8df83640 PluginsManager.cpp:153] Not implemented yet: ICU is disabled for this target
E0320 10:45:40.817404 7f8c8df83640 PluginsManager.cpp:153] C-FIND request handler has failed: Not implemented yet

This happens even on a fresh install with default configuration and only the multitenant plugin added.

Does the multitenant plugin simply not work yet? Or can someone enlighten me as to what the ICU in the error message means?

Hi,

Disclaimer: I’m note really familiar with this plugin.

libICU is a C++ library to perform text encoding conversion and, from this comment in the code it seems it is disabled for most plugins:

/**
 * Remove the dependency upon ICU in plugins, as this greatly increase
 * the size of the resulting binaries, since they must embed the ICU
 * dictionary.
 **/

So I would say that the Multitenant plugin is currently not able to handle C-Find that needs character sets conversion.

I’ll let Sébastien look into it since he is more familiar with this plugin and encodings :wink:

Best regards,

Alain.

Okay, that does make sense.
Though the error happens on C-Find requests with pure ASCII. Though there might be somethings hidden, I am on a Danish system. I will have to investigate the characters in my C-Find requests.

One fix would then probably be to build Orthanc, or at least the Multitenant plugin, myself with the ICU flag flipped. Though I would like to avoid having to do that.

Hello,

The precompiled binaries of the “multinenant DICOM plugin” have been upgraded to include multilingual support thanks to the following changeset: orthanc: dce22a789a2b

You can download those binaries for the mainline of Orthanc at the usual location: Orthanc downloads

Those modifications will be included in forthcoming Orthanc 1.12.4 release.

Kind Regards,
SĂ©bastien-

1 Like

Hi SĂ©bastien

That looks seems to work great. Thank you very much.

After testing some more with another DICOM client there seems to still be some issues with character encoding support in the multitenant DICOM plugin.

If the C-Find request includes a value for SpecificCharacterSet, 0 recourses are returned. If SpecificCharacterSet is included but left blank it works fine and it responds with “ISO_IR 192” (i.e. UTF-8) in the field. Which is the same as the client that made me discover the issue requests, so no transcoding should even be necessary.

I tried applying a workaround, with a Lua script. But it seems that the multitenant plugin bypasses at least the IncomingFindRequestFilter Lua function. Is that intentional?

Logs has this, through the multitenant plugin with SpecificCharacterSet specified:

I0326 10:50:01.176809     7f3fa07b0640 ServerContext.cpp:1565] Number of candidate resources after fast DB filtering on main DICOM tags: 2
I0326 10:50:01.178576     7f3fa07b0640 ServerContext.cpp:1713] Number of matching resources: 0

And has this, through the normal server or through the plugin with SpecificCharacterSet not specified.

I0326 10:51:31.017906         DICOM-46 ServerContext.cpp:1565] Number of candidate resources after fast DB filtering on main DICOM tags: 2
I0326 10:51:31.131182         DICOM-46 ServerContext.cpp:1713] Number of matching resources: 2

Hello,

Please provide a minimal working example (i.e., sample DICOM images + calls from the command line). Otherwise, it is impossible to provide any help.

Also, bear in mind that this is a “sample” plugin. This means that this plugin is more a proof-of-concept for you to adapt.

Regards,
SĂ©bastien-

Oh, I do see now that is an example plugin. Thanks, for the help so far, and if it is not worth it to look into that is totally fine. I will find another way to do what i wanted with the plugin or might have to dig into the code myself.

But since you asked here is a minimal working example anyway:

The problem can be found with running the mainline version from today, with just the multitenant plugin added. And standard configuration, except a file with the following to configure the multitenant plugin:

{
    "MultitenantDicom" : {
    "Servers" : [
      {
        "AET" : "ORTHANC_2",
        "Port" : 4243,
        "Labels" : [ "TEST" ],
        "LabelsConstraint" : "None",
        "LabelsStoreLevels" : [ "Study", "Series", "Instance" ]
      }
    ]
  }
}

Then at least one dicom file added to the server. I just used this small example file found online: https://www.rubomedical.com/dicom_files/dicom_viewer_0002.zip But any file should work.

With no tags added to any resource both dicom servers should see all files. The following Python code, then tries both servers with a simple C-Find request with SpecificCharacterSet set to “ISO_IR 192” and then to “”.

from pynetdicom import AE
from pynetdicom.sop_class import (
    Verification,
    PatientRootQueryRetrieveInformationModelGet,
    PatientRootQueryRetrieveInformationModelFind,
)
from pydicom import Dataset

class DICOMConnection:
    def __init__(self, ip, ae_title="ANY-SCP", port=4242):
        self.databuffer = None

        # Initialise the Application Entity
        ae = AE()
        ae.add_requested_context(Verification)
        # Add the requested presentation contexts (QR SCU)
        ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet)
        ae.add_requested_context(PatientRootQueryRetrieveInformationModelFind)
        self.assoc = ae.associate(ip, port, ae_title=ae_title)

    def terminate(self):
        self.assoc.release()

    def getUIDs(self, ds):
        series = {}
        responses = self.assoc.send_c_find(ds, PatientRootQueryRetrieveInformationModelFind)
        for (status, identifier) in responses:
            if status:
                if status.Status == 0xFF00:
                    series[identifier.StudyInstanceUID] = identifier
            else:
                self.terminate()
        return series

conec_main = DICOMConnection("localhost", "ORTHANC", 4242)
conec_plugin = DICOMConnection("localhost", "ORTHANC_2", 4243)

ds = Dataset()
ds.QueryRetrieveLevel = "STUDY"
ds.StudyInstanceUID = ""

ds.SpecificCharacterSet = "ISO_IR 192"
regular_with_SpecificCharacterSet = conec_main.getUIDs(ds)
multitenant_with_SpecificCharacterSet = conec_plugin.getUIDs(ds)

ds.SpecificCharacterSet = ""
regular_no_SpecificCharacterSet = conec_main.getUIDs(ds)
multitenant_no_SpecificCharacterSet = conec_plugin.getUIDs(ds)

print(f"Number of studies found connection to the main DICOM server with SpecificCharacterSet specified:"
      f" {len(regular_with_SpecificCharacterSet)}")
print(f"Number of studies found connection to the main DICOM server with SpecificCharacterSet blank:"
      f" {len(regular_no_SpecificCharacterSet)}")
print(f"Number of studies found connection to the DICOM server from the plugin with SpecificCharacterSet specified:"
      f" {len(multitenant_with_SpecificCharacterSet)}")
print(f"Number of studies found connection to the DICOM server from the plugin with SpecificCharacterSet blank:"
      f" {len(multitenant_no_SpecificCharacterSet)}")

conec_main.terminate()
conec_plugin.terminate()

The resulting output is then:

Number of studies found connecting to the main DICOM server with SpecificCharacterSet specified: 1
Number of studies found connecting to the main DICOM server with SpecificCharacterSet blank: 1
Number of studies found connecting to the DICOM server from the plugin with SpecificCharacterSet specified: 0
Number of studies found connecting to the DICOM server from the plugin with SpecificCharacterSet blank: 1

If querying the server from the plugin and specifying SpecificCharacterSet nothing is found. But for the other three permutations the study is found.

1 Like