5

I am trying to get DICOMS from a server using gdcm's CompositeNetworkFunctions. My test server is set up using "Orthanc".

When I run the Move request, I get:

terminate called after throwing an instance of 'gdcm::Exception'

what(): /home/myname/Builds/GDCM/Source/Source/Common/gdcmException.h:74 ():

When I catch that Exception, I find that it is an "unhandled exception", no more info. So instead of catching it, I run the program using gdb. Here's what I get:

0x00007ffff3e4dcc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56  ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff3e4dcc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff3e510d8 in __GI_abort () at abort.c:89
#2  0x00007ffff44526b5 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff4450836 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff4450863 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff4450aa2 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x0000000000781772 in std::istream& gdcm::DataSet::ReadWithLength<gdcm::ExplicitDataElement, gdcm::SwapperNoOp>(std::istream&, gdcm::VL&) ()
#7  0x00000000007cd268 in gdcm::network::PresentationDataValue::ConcatenatePDVBlobsAsExplicit(std::vector<gdcm::network::PresentationDataValue, std::allocator<gdcm::network::PresentationDataValue> > const&) ()
#8  0x00000000007d6af1 in gdcm::network::ULConnectionManager::RunEventLoop(gdcm::network::ULEvent&, gdcm::network::ULConnection*, gdcm::network::ULConnectionCallback*, bool const&) ()
#9  0x00000000007d5190 in gdcm::network::ULConnectionManager::RunMoveEventLoop(gdcm::network::ULEvent&, gdcm::network::ULConnectionCallback*) ()
#10 0x00000000007d4acf in gdcm::network::ULConnectionManager::SendMove(gdcm::BaseRootQuery const*, gdcm::network::ULConnectionCallback*) ()
#11 0x00000000007c1750 in gdcm::CompositeNetworkFunctions::CMove(char const*, unsigned short, gdcm::BaseRootQuery const*, unsigned short, char const*, char const*, char const*) ()
#12 0x0000000000666c5c in PACSCMove::run (this=0x25a9dd0) at /home/myname/Projects/Hiwi/Source/src/PACSCMove.cpp:67
#13 0x00007ffff4798384 in ?? () from /home/myname/Qt/5.4/gcc_64/lib/libQt5Core.so.5
#14 0x00007ffff70fa182 in start_thread (arg=0x7fffd8cf5700) at pthread_create.c:312
#15 0x00007ffff3f1147d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Here's my code:

mQuery.InitializeDataSet( mQueryLevel );
setSearchParameter( gdcm::Tag( 0x20, 0x000d ), studyUID.toStdString() );    // Study UID
setSearchParameter( gdcm::Tag( 0x20, 0x000e ), seriesUID.toStdString() );   // Series UID

std::cout << "New Move Query: " << mQuery.ValidateQuery(true) << std::endl;


mQuery.WriteQuery("MoveQuery.dcm");


bool res = gdcm::CompositeNetworkFunctions::CMove(
                "localhost", 4242,
                &mQuery,
                11110,
                "IMHOTEP",
                NULL,
                "/home/myname/TestPatient" );

mQueryLevel is gdcm::eSeries

The interesting thing is that with the written Query File "MoveQuery.dcm", I can download the file just fine using movescu:

movescu -v -p -aet IMHOTEP -od /home/myname/TestPatient/ --port 11110 localhost 4242 MoveQuery.dcm

I've tried:

  • Different values for AET and CALL
  • Relative and absolute paths
  • Different ports (although that shouldn't be it - my movescu call uses the same ports, after all!)
  • mQuery is currently of type gdcm::MovePatientRootQuery, but I've tried MoveStudyRootQuery, FindPatientRootQuery, FindStudyRootQuery
  • Diving into the GDCM code, following the stacktrace - but I don't understand enough of what's going on
  • Adding the value for "PatientID" to the query as well, or only supplying the "SeriesUID" (same result)

With PatientID also added to the query, here's the contents of the MoveQuery.dcm:

$ dcmdump MoveQuery.dcm 

# Dicom-File-Format

# Dicom-Meta-Information-Header
# Used TransferSyntax: Unknown Transfer Syntax

# Dicom-Data-Set
# Used TransferSyntax: Little Endian Implicit
(0008,0052) CS [SERIES]                                 #   6, 1 QueryRetrieveLevel
(0010,0020) LO [4589301]                                #   8, 1 PatientID
(0020,000d) UI [1.2.840.113619.2.55.1.1762893669.2104.1060778173.267] #  52, 1 StudyInstanceUID
(0020,000e) UI [1.2.840.113619.2.55.1.1762893669.2104.1060778173.271] #  52, 1 SeriesInstanceUID
Germanunkol
  • 231
  • 1
  • 3
  • 13
  • Can someone maybe confirm that the DICOM Move request is of the right format for retrieving all images of this series? I always assumed it was, because movescu worked with it. But maybe that's the source of the error? Still, it shouldn't crash... – Germanunkol Mar 23 '15 at 07:54
  • 1
    What is the “Calling AE” (the requester), "Called AE" (service provider SCP, the server) and Destination AE (C-Move destination SCP)? The Destination AE should already be configured in C-Move service provider (Destination AE Title, IP address and listening port) application. – LEADTOOLS Support Mar 23 '15 at 14:00
  • Calling AE: "IMHOTEP" (orthanc.json contains: "IMHOTEP" : [ "IMHOTEP", "localhost", 11110 ]) Called AE: "ORTHANC" (the orthanc.json config says "DicomAet" : "ORTHANC" ) Destination AE is - from what I gather from the gdcm docs - the same as the calling AE: "NOTE that this functionality is essentially equivalent to C-GET in the DICOM standard; however, C-GET has been deprecated, so this function allows for the user to ask a remote server for files matching a query and return them to the local machine." So it should be configured for ORTHANC with what I wrote for "Calling AE'". – Germanunkol Mar 23 '15 at 15:33
  • All that said - wrong AETs should not crash the function? – Germanunkol Mar 23 '15 at 15:52
  • I would fill a bug report at https://sourceforge.net/p/gdcm/bugs/ if I were you – malat Apr 02 '15 at 14:05

1 Answers1

3

C-GET service is not retired in DICOM standard. C-GET uses the same connection to retrieve the image from SCP but C-MOVE uses a parallel connection where server switches its role to SCU (client) and will try to connect to move Destination AE (destination server). In this case, you need to have a DICOM listener (SCP) on your side to handle incoming connection.

I think you are saying Calling AE Title (C-Move service requester) is "IMHOTEP" and you should have a DICOM listener listening on port “11110”. You are requesting Remote AE “ORTHANC” (Called AE) to move the series to C-Move Destination AE ( this should be your side DICOM listener (SCP) that is "IMHOTEP").

LEADTOOLS Support
  • 2,755
  • 1
  • 12
  • 12
  • Thanks, I understand the difference between C-GET and C-MOVE, but I think I misunderstood the documentation! I thought that the command itself also listens on a the port and acts as the initiator (caller) and the destination at once (otherwise, why would I have to give a output directory?!) But when I have a third program listening on a port, then I can use the CompositeNetworkFunctions::CMove to initialte the transfer of DICOMs to that third party. So that works and solves my problem (I'll just have to spawn an extra process/thread, I still don't understand why the original call crashed. – Germanunkol Mar 24 '15 at 07:36
  • ... the [documentation for the CMove function](http://gdcm.sourceforge.net/html/classgdcm_1_1CompositeNetworkFunctions.html#a14da7678977d824df4839f24ec659cb4) explicitly says it works like C-GET. So it _should_ be working the way I intended it to. I'll keep this answer marked as a solution though, because it works when I manually spawn a new storescp which listenes for incoming DICOMs. – Germanunkol Mar 24 '15 at 07:40
  • 3
    The request attribute list for C-MOVE and C-GET are the same for each query retrieve level (patient, Study, Series etc). In the C-GET service, calling AE is both the SCU and SCP and for C-MOVE service, it is only the SCU. It uses separate SCP (Destination AE) to retrieve the images from PACS. – LEADTOOLS Support Mar 31 '15 at 15:27
  • This answer describes things correctly. C-MOVE requires you to have a separate C-STORE SCP up and running. It can be used to request images to be sent to any destination, not just the requestor. – denver Apr 21 '15 at 15:48