Events triggered for reinserted studies?

Hello! I have a feature in my RIS where I add a temporary status (unstable) to incoming studies so that users know that the study is not yet complete (by using orthanc.ChangeType.NEW_STUDY). I use the events of the OrthancPluginChangeType enum defined here (https://github.com/jodogne/OrthancContributed/blob/master/Plugins/orthancVPIRevealPlugin/Include/orthanc/OrthancCPlugin.h)

However, sometimes a study might not receive all instances (e.g CT with 326 of 350 images), so the user sends the study again to complete the 24 instances left.

The problem is that the resend of the study does not trigger the orthanc.ChangeType.NEW_STUDY event, and of course this is the right behavior. But the orthanc.ChangeType.STABLE_STUDY event is triggered when the resend finishes. Therefore I was wondering if there is a way to know when a study is receiving images after being marked as stable, or how you guys handle this situation.

Thanks!

Hello,

I guess you could set a custom metadata attached to study when the first “orthanc.ChangeType.STABLE_STUDY” occurs:
https://book.orthanc-server.com/faq/features.html#metadata-attachments

On the reception of a “orthanc.ChangeType.NEW_INSTANCE” event, you would find the parent study of the instance (using the REST API), then check whether the metadata is set for this study. This will tell you if the study is receiving instances after having being marked as stable.

HTH,
Sébastien-

Hey Sebastien! How are you?

It works! But there is a problem I’m trying to solve: the requests are sent everytime an instance passes by, which is very undesirable.

I am thinking of holding a global variable as a cache of processed instances/series/studies. Having some kind of group identifier for instances would certainly help, but I don’t know if one exists. Anyway, I’ll update the thread with the solution.

By the way, here are the relevant snippets to anyone interested.

First, the change listeners
1.png

Second, the OnStableStudy method with the PUT request to add a “Stable” metadata tag to the study
2.png

Third, the OnStoredInstance method with the new logic to check whether the instance belongs to a new study or an existent one.
3.png

Fourth, the registered callbacks
4.png

A quinta-feira, 7 de abril de 2022 à(s) 06:30:48 UTC+1, s.jo...@gmail.com escreveu:

I solved the repeated requests in the OnStoredInstance event by using the StudyInstanceUID of the instances. Below are the changes I applied to the previous code.

Create a global variable to store studies which had its first instance processed in the OnStoredInstance event

processedStudies = {}

Define your OnStoredInstance with the StudyInstanceUID check logic

def OnStoredInstance(dicom, instanceId):
instance = json.loads(dicom.GetInstanceSimplifiedJson())
studyInstanceUID = instance.get(‘StudyInstanceUID’)

global processedStudies
processedStudy = processedStudies.get(studyInstanceUID)

if not processedStudy:
processedStudies[studyInstanceUID] = True
your custom logic here, to be executed for the first received instance of a study…

Remove the StudyInstanceUID from the global variable in the stable study event

def onStableStudy(resourceId):
study = json.loads(orthanc.RestApiGet(‘/studies/%s’ % resourceId))
statistics = json.loads(orthanc.RestApiGet(‘/studies/%s/statistics’ % resourceId))
series = json.loads(orthanc.RestApiGet(‘/studies/%s/series’ % resourceId))
study.get(‘MainDicomTags’)[‘modalities’] = ‘,’.join(filter(None, set(map(lambda s: s.get(‘MainDicomTags’).get(‘Modality’), series))))
study.get(‘MainDicomTags’)[‘manufacturers’] = ‘,’.join(filter(None, set(map(lambda s: s.get(‘MainDicomTags’).get(‘Manufacturer’), series))))
study.get(‘MainDicomTags’)[‘bodyPartsExamined’] = ‘,’.join(filter(None, set(map(lambda s: s.get(‘MainDicomTags’).get(‘BodyPartExamined’), series))))

orthanc.RestApiPut(f"/studies/{resourceId}/metadata/Stable", “true”)
processedStudies.pop(study.get(‘MainDicomTags’).get(‘StudyInstanceUID’))

body = {
**study,
**statistics
}

response = requests.put(url=“###SISMED_FULL_URL###/api/dicom-exams/stable/” + resourceId, json=body, auth=HTTPBasicAuth(‘###SISMED_ADMIN###’, ‘###SISMED_ADMIN_PASSWORD###’), verify=False)
if response.ok:
orthanc.LogWarning(f"ESTÁVEL: {resourceId}“)
else:
orthanc.LogError(f"ERRO NA REQUISIÇÃO: {resourceId}”)
orthanc.LogError(f"RESPOSTA: {response.text}")
orthanc.LogError(response)

A sexta-feira, 8 de abril de 2022 à(s) 02:14:32 UTC+1, Diego Victor de Jesus escreveu:

There’s still an edge case where the user resends an exam where all the instances were already previously stored (don’t ask me why!). In this scenario, the first call triggers the OnStoredInstance logic, but the stable study event never gets called :frowning:

I guess a change of “OverwriteInstances” to true in the config.json would fix the problem, but it comes at a high cost (users very often resend big exams).

Perhaps we need specific events to better handle scenarios of resend studies?

A domingo, 10 de abril de 2022 à(s) 03:08:58 UTC+1, Diego Victor de Jesus escreveu:

The semantics of “StableStudy” is related to Orthanc changing the content of its database. If the same set of instances is ingested twice, it is thus normal that “StableStudy” is never triggered a second time.

Setting “OverwriteInstances” to “true” is the normal solution.

If you want you to avoid this solution, you could also reimplement the “StableStudy” logic in your Python plugin by monitoring the “OnStoredInstance” events and using the multithreading primitives of Python.