C-GET with success status even if sub-operations failed

Hi.

I am doing a C-GET (SCU) request with pynetdicom where I explicitly return an error code (0xA702) in the handler of the C-Store event. From what I read from the DICOM standard the C-GET should at least return a warning (0xB000), see C.4.3.1.4 Status as one or more sub-operations failed. I tried it with Orthanc as the SCP and it returns a success status (0x0000) even if all sub-operations failed. Is this the correct behavior? The strange thing is that our GE PACS has the same “problem”.
Also discussed in https://github.com/pydicom/pynetdicom/issues/552

Best regards,
Kai

Here is the code I use with pynetdicom:

from pydicom.dataset import Dataset
from pynetdicom import (
AE,
evt,
build_role,
debug_logger,
)
from pynetdicom.sop_class import (
PatientRootQueryRetrieveInformationModelGet,
CTImageStorage,
)

debug_logger()

def handle_store(event):
data = event.dataset
data.file_meta = event.file_meta
print(data.PatientName)
print(“in here”)

data.save_as(data.SOPInstanceUID, write_like_original=False)

return 0xA702

handlers = [(evt.EVT_C_STORE, handle_store)]

ae = AE(ae_title=“ADIT1”)

ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet)
ae.add_requested_context(CTImageStorage)
role = build_role(CTImageStorage, scp_role=True, scu_role=True)

ds = Dataset()
ds.QueryRetrieveLevel = “IMAGE”
ds.PatientID = “10001”
ds.StudyInstanceUID = “1.2.840.113845.11.1000000001951524609.20200705182951.2689481”
ds.SeriesInstanceUID = “1.3.12.2.1107.5.1.4.66002.30000020070513455668000000609”
ds.SOPInstanceUID = “1.3.12.2.1107.5.1.4.66002.30000020070513455668000000610”

assoc = ae.associate(“127.0.0.1”, 7501, ext_neg=[role], evt_handlers=handlers)

if assoc.is_established:
responses = assoc.send_c_get(ds, PatientRootQueryRetrieveInformationModelGet)
for (status, identifier) in responses:
print(status)
if status:
print(“C-GET query status: 0x{0:04x}”.format(status.Status))
else:
print(“Connection timed out, was aborted or received invalid response”)

assoc.release()
else:
print(“Association rejected, aborted or never connected”)

And the last part of the log:

I: Get SCP Result: 0x0000 (Success)
I: Sub-Operations Remaining: 0, Completed: 0, Failed: 1, Warning: 0
(0000, 0900) Status US: 0
(0000, 1021) Number of Completed Sub-operations US: 0
(0000, 1022) Number of Failed Sub-operations US: 1
(0000, 1023) Number of Warning Sub-operations US: 0
C-GET query status: 0x0000

Hello,

Thanks for reporting this issue. It should be fixed by the following changeset that is pending in the mainline (and that will be part of forthcoming 1.8.1 release):
https://hg.orthanc-server.com/orthanc/rev/c046d559edb3

With this changeset, here is the output of your pynetdicom script:

(0000, 0900) Status US: 42754
(0000, 1021) Number of Completed Sub-operations US: 0
(0000, 1022) Number of Failed Sub-operations US: 1
(0000, 1023) Number of Warning Sub-operations US: 0
C-GET query status: 0xa702

HTH,
Sébastien-

Hi Sébastien,

thanks for fix (it would be a dream if GE would fix our PACS in the hospital that fast … or at all ;-)). Another little question… The DICOM standard says that the SCU may cancel the C-GET operation by issuing a C-GET-CANCEL request at any time during the processing of the C-GET request. What would be the correct way to cancel a C-GET? I tried to return 0xFE00 status from the handler, but this does not work with Orthanc (at least in the last released version). Or would be the correct way to send a C-CANCEL in the event handler (by using event.assoc.send_c_cancel)? (Sorry, not sure if this is more a pynetdicom question).

Best regards,
Kai

I did some further tests and it seems sending a C-CANCEL is also not really respected by Orthanc during the C-STORE event (code below). But it seems that this is handled quite differently by the other PACS servers. Our GE PACS in the hospital just aborts the association (but only after some time). DCMTKs dcmqrscp on the other side seems to handle it correctly (see https://github.com/pydicom/pynetdicom/issues/553).

Here the code I tried (same as in the mentioned pynetdicom issue):

from pydicom.dataset import Dataset
from pynetdicom import (
AE,
evt,
build_role,
debug_logger,
)
from pynetdicom.sop_class import (
PatientRootQueryRetrieveInformationModelGet,
CTImageStorage,
)

debug_logger()

def handle_store(event):
to_match = PatientRootQueryRetrieveInformationModelGet
cxs = [cx for cx in assoc.accepted_contexts if cx.abstract_syntax == to_match]
cx_id = cxs[0].context_id
event.assoc.send_c_cancel(9999, cx_id)
return 0xA702

handlers = [(evt.EVT_C_STORE, handle_store)]

ae = AE(ae_title=“ADIT1”)

ae.add_requested_context(PatientRootQueryRetrieveInformationModelGet)
ae.add_requested_context(CTImageStorage)
role = build_role(CTImageStorage, scp_role=True, scu_role=True)

ds = Dataset()
ds.QueryRetrieveLevel = “STUDY”
ds.PatientID = “10001”
ds.StudyInstanceUID = “1.2.840.113845.11.1000000001951524609.20200705182951.2689481”

assoc = ae.associate(“127.0.0.1”, 7501, ext_neg=[role], evt_handlers=handlers)

if assoc.is_established:
responses = assoc.send_c_get(
ds,
PatientRootQueryRetrieveInformationModelGet,
msg_id=9999,
)
for (status, identifier) in responses:
print(status)
if status:
print(“C-GET query status: 0x{0:04x}”.format(status.Status))
else:
print(“Connection timed out, was aborted or received invalid response”)

assoc.release()
else:
print(“Association rejected, aborted or never connected”)

Hello,

I have done a full rewrite of the response and canceling in C-GET SCP:
https://hg.orthanc-server.com/orthanc/rev/6f5d4bfb2c90

This code is pending in the mainline, and will be part of forthcoming 1.8.1 release.

I have also created a suite of integration tests using pydicom to test C-GET SCP:
https://hg.orthanc-server.com/orthanc-tests/file/default/Plugins/CGet/Run.py

I hope this fixes all the issues you have reported. Feedback is more than welcome!

Regards,
Sébastien-

Hello,

what would be the right action in that scenario?
Orthanc doesn’t expose the DIMSE status when a job fails, and it seems the latest version of Orthanc won’t retry automatically.

We also have a problem recently and I don’t know if it’s related to this update.

We have a lot of errors regarding query/retrieve, where the PACS doesn’t send some series. It wasn’t happening with version 1.6.
Some PACS send a DIMSE, so we know that it’s “normal” if we don’t receive something in this case.

But some PACS don’t send DIMSE, the job complete successfully, but we don’t receive one of the series.
We request each series one by one.

Any ideas which part of the code would produce this error, so I can look into it?

Hello,

We would need a minimal working example to understand what your problem is:
https://book.orthanc-server.com/users/support.html#discussing-a-minimal-working-example

Unfortunately, if we can’t reproduce your issue, we are not able to provide any useful help.

Note that Orthanc 1.9.0 will soon be released, maybe this new version could help.

Regards,
Sébastien-