Identification of modalities for C-FIND & C-MOVE operations

Hi there!

I’m working on a PoC using Orthanc as a proxy to an external DICOM index.
I’m making use of the Python plugin, so I can override ‘OnFind’ and ‘OnMove’ handlers and implement the behavior I need.

My problem is I need to access modality information in those handlers, so I’m trying to manage modalities. What I see from Orthanc’s configuration is that I can define modalities via config file or using its REST API. Either way, the modality “alias” is the one used as the identifier, so this must be unique. But the rest of the attributes are not (AET, host, port).

When a new association is established, how do I know the modality it is performing the C-FIND or C-MOVE operation? the interface exposes ‘issuer_aet’ or ‘called_aet’ as parameters, and even knowing that the AET is supposed to be unique for a hospital, like docs state:

[…] each imaging device (may it be a client or a server) must be associated with a symbolic name that is called the application entity title (AET). The AET is assumed to be unique inside the Intranet of the hospital. For best compatibility between vendors, the AET should be only made of alphanumeric characters in upper case (plus the “-” and “_” characters), and its length must be below 16 characters.
Taken together, the IP address, the TCP port and the AET describe all the parameters of a DICOM server. The administrators of a medical imaging network should carefully keep track of these parameters for each imaging device, and should define an hospital-wide policy to assign AETs to new devices.

This sometimes is not true in my case; not sure if this is the reason why Orthanc’s configuration file would support two modalities with the same AET + port + host configuration, as this valid config shows:

  ...
  "DicomModalities": {
    "SCU": {
      "AET" : "ORTHANC-SCU",
      "Port" : 4242,
      "Host" : "scu"
    },
    "SCU2": {
      "AET" : "ORTHANC-SCU",
      "Port" : 4242,
      "Host" : "scu"
    }
  },
  ...

So in summary:

  1. Does Orthanc map the DICOM association with a particular registered modality for C-FIND or C-MOVE operations?
  2. Is there a way to have access to the DICOM association attributes of the operation (host & port) using the Python plugin?

Thank you! Regards,
Alberto

Hi Alberto,

Your understanding is correct: Inside a hospital, the same AET shall not be reused but this happens and that’s why Orthanc also accepts multiple modalities with the same AET and IP and port.

Right now, there is no way to know more about the issuer of the C-Find or C-Move in a plugin.
It would be possible to modify the SDK to pass the IP of the issuer but, unfortunately, that’s not a trivial task.

In case you or your company are willing to fund this implementation, feel free to get in touch with us.

Best regards,

Alain

Hey @alainmazy , thank you very much for the quick response!

I was checking the C++ code and I found the logic that deals with the association:

    {
      bool checkIp;
      std::list<RemoteModalityParameters> modalities;

      {
        OrthancConfiguration::ReaderLock lock;
        lock.GetConfiguration().LookupDicomModalitiesUsingAETitle(modalities, remoteAet);
        checkIp = lock.GetConfiguration().GetBooleanParameter("DicomCheckModalityHost", false);
      }
      
      if (modalities.empty())
      {
        LOG(WARNING) << "DICOM authorization rejected  for AET " << remoteAet
                     << " on IP " << remoteIp << ": This AET is not listed in "
                     << "configuration option \"DicomModalities\"";
        return false;
      }
      else if (modalities.size() == 1)
      {
        // DicomCheckModalityHost is true: check if the IP match the configured IP
        if (checkIp &&
            remoteIp != modalities.front().GetHost())
        {
          LOG(WARNING) << "DICOM authorization rejected for AET " << remoteAet
                       << " on IP " << remoteIp << ": Its IP address should be "
                       << modalities.front().GetHost()
                       << " according to configuration option \"DicomModalities\"";
          return false;
        }
        else if (modalities.front().IsRequestAllowed(type))
        {
          return true;
        }
        else
        {
          ReportDisallowedCommand(remoteIp, remoteAet, type);
          return false;
        }
      }
      else
      {
        // If there are multiple modalities with the same AET, consider the one matching this IP 
        // or check if the operation is allowed for all modalities
        bool allowedForAllModalities = true;

        for (std::list<RemoteModalityParameters>::const_iterator
               it = modalities.begin(); it != modalities.end(); ++it)
        {
          if (it->IsRequestAllowed(type))
          {
            if (checkIp &&
                it->GetHost() == remoteIp)
            {
              return true;
            }
          }
          else
          {
            allowedForAllModalities = false;
          }
        }

Where

  void OrthancConfiguration::LookupDicomModalitiesUsingAETitle(std::list<RemoteModalityParameters>& modalities,
                                                               const std::string& aet) const
  {
    modalities.clear();

    for (Modalities::const_iterator it = modalities_.begin(); it != modalities_.end(); ++it)
    {
      if (IsSameAETitle(aet, it->second.GetApplicationEntityTitle()))
      {
        modalities.push_back(it->second);
      }
    }
  }

So yeah, what you said: AETs are supposed to be unique, but if there are repeated results, it will try to match the IP as the “deal breaker”.

Right now, there is no way to know more about the issuer of the C-Find or C-Move in a plugin.
It would be possible to modify the SDK to pass the IP of the issuer but, unfortunately, that’s not a trivial task.

In case you or your company are willing to fund this implementation, feel free to get in touch with us.

Sounds good, I’ll talk with the team to see what are our options.

Thank you very much!

Regards,

Alberto

@alainmazy I’ve sent you an email to get more info about making IP & port accessible from the plugin SDK.