Modifying dicom using python script

hey everyone,
I am new with python script. I was trying to modify dicom tag but facing issues .
Below I am attaching my script with error logs and rest of the information. Please guide me what I am doing wrong. Thankyou
Python script :

import orthanc
import json

def OnChange(changeType, level, resourceId):
    print('study: %s' % changeType)       
    if changeType == orthanc.ChangeType.STABLE_STUDY:
        modifyStudy(resourceId)

orthanc.RegisterOnChangeCallback(OnChange)

def modifyStudy(resourceId):
    print('studyId: %s' % resourceId)
    try:
        # Download a modified version of the instance
        modifyBody = {
            "Replace": {
                "InstitutionName": "MY NEW INSTITUTION"
            }
        }
    
        modifyRequest = orthanc.RestApiPost('studies/' + resourceId + '/modify', json.dumps(modifyBody))
        if modifyRequest.status_code != 200:
            print("Could not modify study: " + resourceId + ", it won't be retried!")
            return

    except Exception as e:
        print("An error occurred while modifying the study:", str(e))

Error Logs :

python-script-orthanc-python-1  | studyId: fe3f19a2-490f3d53-ae92b252-314e1053-a98b5396
python-script-orthanc-python-1  | I0731 12:09:17.205230 PluginsManager.cpp:161] (plugins) Calling Python global function: OrthancPluginRestApiPost()  
python-script-orthanc-python-1  | I0731 12:09:17.206596 OrthancPlugins.cpp:3203] (plugins) Plugin making REST POST call on URI studies/fe3f19a2-490f3d53-ae92b252-314e1053-a98b5396/modify (built-in API)
python-script-orthanc-python-1  | E0731 12:09:17.219564 PluginsManager.cpp:188] Exception while invoking plugin service 3002: Badly formatted URI
python-script-orthanc-python-1  | An error occurred while modifying the study: (12, 'Badly formatted URI')

python version on local machine : 3.9
Envs I am passing while running orthanc image in docker

      PYTHON_PLUGIN_ENABLED: true
      VERBOSE_ENABLED: "true"
      VERBOSE_STARTUP: "true"
      ORTHANC__PYTHON_VERBOSE: "true"

Hello :

There should be a leading slash in the URI :

orthanc.RestApiPost('/studies/' + resourceId + '/modify', json.dumps(modifyBody))

Additional Note 1: RestApiPost simply returns the response body. There will not be any status_code field. The way to catch errors is through exceptions.

Additional Note 2: You need to somehow prevent your code from running into an infinite loop, because the “stable study” event will once again be triggered after your change. For instance, you might want to only change InstitutionName if it’s not correct yet.

hello @benjamin.golinvaux ,
Thankyou so much for pointing out the mistakes.
Is there any way to get out of infinity loop also I want to keep the SOP same as original dicom files.

if I keep the same SOP as of original dicom instance. The dicom file will not get modified-Form tag in metadata.
I have one way to overcome from infinity loop which is to modified a some tag value and put some random value let says “alreadymodified”. and when the second time the stable study function run for modified study it will look for that tag and come out of the function.

Is there any method in python to avoid this long process ? or any tips how I can go with that.

with regards
Ankush

Hi
You might want to take a look at this sample

This is Lua but does what you need at the instance level, which allows to preserve the SOPInstanceUID, SeriesInstanceUID and StudyInstanceUID.

In my understanding, merely modifying the InstitutionName should not generate a new ID, so I am not really sure the reason for these two lines:

  • modifyRequest["Replace"]["SOPInstanceUID"] = tags["SOPInstanceUID"]
  • and modifyRequest["Force"] = true -- because we want to keep the same SOPInstanceUID

You can try it out, and check what happens if you remove them.

The trick that is used there to prevent the infinite loop is to use if origin['RequestOrigin'] ~= 'Lua' then so that the modification is only done if the instance is not originating from the script itself.

(I also suggest that you browse other samples in this excellent GitHub repo that contains a lot of ready-made setup… most of them are in the docker/ folder and contain either Lua or Python)

Hope this helps

hey @benjamin.golinvaux ,
In my understanding, merely modifying the InstitutionName
it will generate new IDs
if you not keep the resourses like SOPInstanceUID,SOPStudyID,SOPSeriesUID
origin['RequestOrigin'] ~= 'Lua'
this is going to work with lua script and I am ryt now working with Python script
(I also suggest that you browse other samples in this excellent GitHub repo that contains a lot of ready-made setup… most of them are in the docker/ folder and contain either Lua or Python)
Sure, I will look into this ,
Thankyou so much for help and suggestion
with regards
Ankush

Hello

Sorry I forgot to mention it, but I think the equivalent of origin['RequestOrigin'] ~= 'Lua' in your case would be origin["RequestOrigin"] != "Plugin"

Please add a debuging print(f'Origin = {origin["RequestOrigin"]}') to confirm what I wrote above.

Thanks.

@benjamin.golinvaux ,
sure , I will try out this
Thankyou so much