Filtering incoming dicom instances using metadata (with python plugin)

I’m trying to filter incoming Dicom instances using the metadata of the instance. I saw this is possible using Lua server-side scripting (https://book.orthanc-server.com/users/lua.html#id8), but I was interested in doing this in python.

When I looked at the SDK for the filter callback signature (https://sdk.orthanc-server.com/group__Toolbox.html#ga40738a61e1b77ed4945347b61f4b5483) I saw this:

“Note that the metadata information is not available (i.e. GetInstanceMetadata() should not be used on “instance”).”

Why is this so? If I understand this correctly, does this mean I cannot filter an incoming instance using a python plugin by, let’s say, checking if the modality type of the instance is CT?

How would you recommend I build such a filter? I’m not averse to using Lua, but using python is a strong preference.

Hi,

Metadata are stored in the DB and attached to the instance. At the time filtering is performed, the instance has not been stored in DB yet and therefore the metadata are not yet available.

Also note that this SDK method is not yet wrapped in python (today, only 70-80% of the SDK is wrapped in python. here is the list of available methods in python: https://bitbucket.org/osimis/orthanc-setup-samples/src/master/python-samples/python-sdk.txt)

So today, lua is indeed your only chance to filter incoming instances.

Possible workaround: delete unwanted instances in OnStoredInstance (https://book.orthanc-server.com/plugins/python.html#accessing-the-content-of-a-new-instance)

HTH

Alain

Hello,

Actually, you can get metadata in the “OnStoredInstance” callback of Python. For instance:

import orthanc

def OnStoredInstance(dicom, instanceId):
print(dicom.GetInstanceMetadata(‘RemoteAET’))

orthanc.RegisterOnStoredInstanceCallback(OnStoredInstance)

However, as written in the documentation of the Python plugin:“Warning - Your callback function will be called synchronously with the core of Orthanc. This implies that deadlocks might emerge if you call other core primitives of Orthanc in your callback (such deadlocks are particular visible in the presence of other plugins or Lua scripts). It is thus strongly advised to avoid any call to the REST API of Orthanc in the callback. If you have to call other primitives of Orthanc, you should make these calls in a separate thread, passing the pending events to be processed through a message queue.” [Python plugin for Orthanc — Orthanc Book documentation]

As a consequence, here is a preferred way to implement auto-routing of instances using Python:

import json
import orthanc

ROUTING_AET = ‘HELLO’
TARGET = ‘sample’

def OnChange(changeType, level, resource):
if changeType == orthanc.ChangeType.NEW_INSTANCE:

On new instance whose source AET matches the AET of

interest, send it to another modality

metadata = json.loads(orthanc.RestApiGet(‘/instances/%s/metadata?expand’ % resource))
if metadata.get(‘RemoteAET’) == ROUTING_AET:
orthanc.RestApiPost(‘/modalities/%s/store’ % TARGET, resource)

elif changeType == orthanc.ChangeType.JOB_SUCCESS:

Delete the routed instance once it has properly been

received by the target modality

job = json.loads(orthanc.RestApiGet(‘/jobs/%s’ % resource))
instances = job[‘Content’][‘ParentResources’]
for instance in instances:
orthanc.RestApiDelete(‘/instances/%s’ % instance)

orthanc.RegisterOnChangeCallback(OnChange)

Also, check out the following sample in the Orthanc Book for a more efficient way of auto-routing, by sending studies as a whole:

HTH,
Sébastien-

Thank you, guys! This was very helpful!