Should Slicer DICOM storage listener respond to C-ECHO?

Could someone verify whether a Slicer DICOM storage listener should respond to a C-ECHO request? When I try, I do not get a response, instead it immediately aborts (A-ABORT with Abort Source: service-user).

# Minimal C-ECHO test
from pynetdicom import AE, debug_logger  
debug_logger() # make logging messages verbose
storage_addr = "127.0.0.1" # localhost
storage_port = 11112 # port slicer dicom storage listener is on
ae = AE()  
ae.add_requested_context("1.2.840.10008.1.1")  # echo verification context
assoc = ae.associate(storage_addr, storage_port)
if assoc.is_established:
    print('Association successful')
    status = assoc.send_c_echo()
    assoc.release()
else:
    print('Association failed!')

In various guides around the internet, getting a successful C-ECHO response is the first step in troubleshooting because the requirements are minimal (e.g. no search parameters, just a successfully open communication channel), so I expected this to work. In this case, the successful association suggests that the communication channel is open, but the C-ECHO request somehow triggers the connection aborting. There is an idle network timeout which can also trigger a connection abort, but this happens much faster than that 60 second timeout.

For background, I am working with @ezgimercan and our hospital networking team to get DICOM networking communication from Slicer working. Configuration has proceeded to the point that we are able to successfully query the clinical PACS, but retrieval fails (we get a “Success” message, but 0 images/files are transferred). I am trying to figure out exactly where the breakdown is occurring. Using pynetdicom and verbose logging, I can see that association is successful, but sub-operations are failing.

Also, for reference, the same code above with the remote PACS IP address and port works returns a success status to the send_c_echo() call and does not abort. Using an incorrect IP address yields a TCP connection error (as expected), and using an incorrect port yields a TCP connection actively refused error (as expected). Both of those results are distinct from the results for the local Slicer storage listener (and for the clinical PACS).

I would appreciate any help or suggestions anyone can offer.
Following the very helpful troubleshooting guide at Troubleshooting Query/Retrieve SCU **Start Here** · Issue #419 · pydicom/pynetdicom · GitHub, one of the steps is to verify that connecting to the storage provider (SCP), the one running from Slicer, is working. The simplest check is to send a C-ECHO and make sure that it responds. However, when I try this, the communication aborts (A-ABORT with Abort Source: service-user). This seems very odd to me because there are no errors shown in the association process (Verification SOP Class is accepted), only when the C-ECHO is sent. Also, to be clear, the listener I am testing here is the Slicer DICOM storage listener, not the clinical PACS; there is no communication off of the local machine in this test.

The full verbose log of the association, request, and abort from running the code above in Slicer’s python interactor:

The traditional storage provider (listener) in the Slicer release is implemented using dcmtk’s storescp and yes, it responds to echo for me:

$ echoscu -v localhost 11112
I: Requesting Association
I: Association Accepted (Max Send PDV: 16372)
I: Sending Echo Request (MsgID 1)
I: Received Echo Response (Success)
I: Releasing Association

If you use ps on linux I can see the listener running with these arguments. You can just run the same or similar commands outside of Slicer for debugging.

.../Slicer-5.5.0-2023-11-15-linux-amd64/bin/../bin/storescp 11112 --accept-all --output-directory /mnt/timc-batch2/data/db2/incoming --exec-sync --exec-on-reception /mnt/timc-batch2/Slicer-5.5.0-2023-11-15-linux-amd64/bin/../bin/dcmdump --load-short --print-short --print-filename --search PatientName "/mnt/timc-batch2/data/db2/incoming/#f"

You could try echoscu like this from localhost or from a different machine to see if the ports are working.

If pynetdicom had existed when Slicer’s dicom networking was implemented we might have used that, but it’s also kind of nice that these kind of connection issues can be debugged independently with just the command line tools, and also using the separate process makes it event driven (networking doesn’t block the UI). I see that pynetdicom also provides a way to run it’s storescp as a command line tool so that might help for testing. It should also be possible to install pynetdicom directly in Slicer’s python.

Things may be different too with the new dicom browser that’s available in the Preview version of Slicer.

Good luck - debugging these dimse connections can be a pain so ask follow-ups as needed and report back what you find so it will help others in the future.

1 Like

If you are using Slicer preview you can use the new class in ctk (ctkDICOMEcho) that I have introduced for C-ECHO (which uses directly DcmSCU from DCMTK). You can use it directly from the Slicer python console as:

import ctk
echoer = ctk.ctkDICOMEcho()
echoer.host = "localhost"
echoer.calledAETitle = "CTKSTORE"
echoer.port = 11112
echoer.echo()

I have tested it and it works for me, both using the DICOM module storage listener (Python implementation) and the visual DICOM browser one (C++ implementation):

  • visual DICOM browser

  • DICOM module UI

If you have any issue, please let us know.

1 Like

Most clinical PACS only supports C-MOVE and not C-GET, so the IP address of your computer must be set in the PACS configuration (you cannot retrieve from some random IP address; unless you use the proxy feature of the new DICOM browser). When you retrieve an image using C-MOVE you actually just ask the PACS to do a C-STORE sometime in the future. It is not a synchronous operation, so it is normal that the retrieve request returns with success but no files are transferred. Whenever it is convenient for the server, it will start a C-STORE and if that fails you may only see any errors in the PACS logs.

I would not bother with C-ECHO. Instead, I would test if you can successfully perform a DICOM push (C-STORE) initiated from the PACS. Once you configure C-STORE, C-MOVE will work correctly, too.

I would recommend using the new DICOM browser, it implements query/retrieve with a convenient user interface, thumbnails, etc. everything is done in the background (without blocking the application GUI), and C-STORE configuration is properly implemented (I think in the old version you had to set the AE title manually in the Slicer.ini file).

1 Like

Thanks @pieper, using echoscu worked fine, so I’m not sure what was going wrong trying from pynetdicom.

Thanks for the advice, I will try the approach you suggest of sending a C-STORE from the PACS. I also now suspect that the PACS may not support C-GET, despite accepting association and accepting a GETStudyRootQueryRetrieveInformationModel as a presentation context.

Regarding the new DICOM browser, I was planning to try to work up to that by getting the basic connection working first with the older browser, on the assumption that some people had gotten the old version to work with clinical PACS, whereas I was not clear whether anyone had even tried yet with the new version. The introduction of the new DICOM browser was the initial motivation for starting the process of trying to get the connection working, but I wasn’t sure how mature that code was.

The new browser should be much more robust in query/retrieve from PACS. It is tested in hospital environment.

1 Like

We are also actively refining the UI/adding new features to the new browser.
Your feedback would be very welcome too.

For reference, I link here the current roadmap.

1 Like

Thanks for all the help and suggestions. We now have DICOM Query and Retrieve working from Slicer as long as we are on a static IP address within the hospital network. I am typically operating over a VPN, so I am still exploring whether we can make that work also.

The most helpful avenue for troubleshooting was to try pushing from our PACS to the Slicer DICOM listener, as @lassoan suggested above. That allowed our network team to identify the remaining barriers to communication. Once that was working, initiating C-MOVE requests from Slicer was successful (achieved by unchecking the C-GET column in the DICOM Q/R dialog box). We did not find the newer DICOM browser immediately helpful in troubleshooting, but do plan to explore using it in the future now that we have some basic communication verified.

1 Like

The good news is that we have already implemented a solution for this in the new DICOM browser. All you need is to set up a proxy server that supports C-GET and ask IT admins to enable Query/Retrieve for it. In the DICOM configuration settings, you select this proxy server to be used by the hospital PACS.

I would recommend using Orthanc as proxy, it is well established, free, very easy to set up on either Windows or Linux, either running natively or in docker.

How this works is that your laptop queries the hospital PACS for what images are available for the selected patient. If there are any images that are not already on your laptop then Slicer retrieves it from the proxy server (using C-GET, which works well with dynamic IP). If the image is not on the proxy server then Slicer asks the hospital PACS to send the image to the proxy server (using C-MOVE, which all hospital servers support) and then Slicer can retrieve the image from the proxy server. All this communication is performed automatically, seamlessly, in the background.

Thanks for this idea. Would the proxy server be set up on a machine inside the hospital network then?

Yes, on any computer within the hospital network with a static IP address.

1 Like

Thanks for all the support troubleshooting our DICOM networking. I am reporting back with the most bizarre observation.

I have both the stable version (5.6.1) and preview version (5.7.0-2024-04-11) of Slicer. As @mikebind said above, we can query/retrieve using the old DICOM browser. With the preview/advanced version, I cannot query the same PACS. It says: “The query provided no results. Please refine your filters.” I can send DICOM from PACS to the preview OK, but things get interesting here: once one study of a patient is in the local DICOM database (through DICOM send), then the preview can query and retrieve ALL studies of the same patient. But not before the patient is in the database somehow.

We are perfectly happy using the old DICOM browser / python scripts to do our query/retrieve jobs. This is more out of curiosity, do you have an idea what’s happening here? How can I receive data, query other studies of the existing patients but cannot query other patients/studies on the PACS?

There are a number of fixes and improvements for the new browser that will be integrated early next week. If you find any issues in the new browser after that then please report them and they will be fixed.

I dont think anybody will touch the old query/retrieve, it is just very slow and clunky and does not work in a usual research workflow in a hospital environment (the application is running in a docker container or on a laptop, so static IP is not an option).