Continuation of closed topic

All other questions regarding DCMTK

Moderator: Moderator Team

Message
Author
Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

Continuation of closed topic

#1 Post by Mitmal »

Thank you for your last post (although it is a bit inquisitive).
Your explanation is very clear, only I have one problem. I use MedicTool2: scuN-> sendMOVERequest (MedicTool2:: chair, "monAET", & req, & MedicTool2: moveResponses) to ask the server images.
But this function is blocking. Moreover scp.listen () is blocking too.
So it nothing happens and the application freezes

PS: I've always said that I just look for help and I know nothing, either in C++ or in DCMTK. Thank you for understanding
Respectueusement,
MitMal

Roadrunner
Posts: 56
Joined: Mon, 2010-06-14, 16:41

#2 Post by Roadrunner »

You have to use either fork() (under linux) or creating process with the win32 api where you handle the listen/storescp part and another process for your scuMoveRequest.
Or better you create a thread (they are faster than a process to create) for each 'thing' (listen() and scumoverequest) ... but you should know what you are doing otherwise you'll shoot your self in your feed - so should inform and play around with threads communication with your main program (- if the move request successfully, - are there files incoming, -adding dcmdatasets to a queue, protect the queue for deleting an entry while another thread is writing (mutex or semaphore) and so on....).
It depends on what you wanna do with the files.

System programming is the keyword here.

Frank

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#3 Post by Mitmal »

Super thank you.
(I looked on the side of DIMSE_NONBLOCKING)
It gives me Code:

Code: Select all

scuN->setDIMSEBlockingMode(DIMSE_NONBLOCKING);
result = scuN->sendMOVERequest(presID, OFmonAet, &req, &moveResponses);
bool initialisationSTORE = initServiceStore(monPort, monAet);
(Where initServiceStore used to start the function listen)

I have two question (before you finish, I believe, with the connection PACS)
The images of the series is well load (via the the chosen rerptoire saveFile function), but only one series is downloaded when I run the operation several times.

In fact, the above code is in a loop that runs through all the series I want to recover (identified by their ID). Would you help me?

Finally, when all the images are downloaded, the service does not stop and the application is blocked. How should we do to stop the service started via listen?
Respectueusement,
MitMal

Roadrunner
Posts: 56
Joined: Mon, 2010-06-14, 16:41

#4 Post by Roadrunner »

Finally, when all the images are downloaded, the service does not stop and the application is blocked. How should we do to stop the service started via listen?
As i mentioned above - I would use another thread for storing the images; so if i want to stop the service I send a kill/terminate command to the thread.

2nd way: you overwrite the function

Code: Select all

bool YourDcmSCP::stopAfterCurrentAssociation()
{
  return OFTrue;
}
This will stop the scp service after receiving images; but this will also stop if an scu sends an image by image with connect and disconnect between every image.

There are some disadvantages if you use the non-blocking mode;
First: the default time-out is set to 1000 seconds (well you can set it higher with

Code: Select all

scp->setConnnectionTimeout(ULONG_MAX);
ULONG_MAX means >100 years) .

Second: if you don't receive an image while waiting for the time-out and the time-out appears and you use it together with stopAfterCurrentAssociation() - what was the reason for stopping listen() - receiving an image or time out.
You never know if there is an image or not - so you need a counter or another solution - it doesn't sounds like a good solution.

Third: during waiting for the time-out the listen code blocks your application again ... and this is what you don't want. ;-)
In fact, the above code is in a loop that runs through all the series I want to recover (identified by their ID). Would you help me?
You've the receiveDIMSEDataset... and there was the line if (dataObject->findAndGetOFString(DCM_SOPInstanceUID, dateiname,0, true).good())
...
Change the DCM_SOPInstanceUID to DCM_SeriesInstanceUID and you have the id of your series. dcmtk/dcmdata/dcdeftag.h is your friend for all tags (or nearly all - you never know what will change tomorrow).

Frank

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#5 Post by Mitmal »

Ok, it's great.
Now to do all what I wanted.
I get all my series. I build destination directories based on the nature of the sequences. I rename the files based on their nature and I release the connection after the download is complete.

(Indeed, I put the function listen in another thread, thank you for advice. Besides, I also put the scu sendMOVERequest mode-locked, always on your advice)

But now I see a problem. Using saveFile function (in handleIncomingCommand) I get a lot of files but they are not in DICOM format. (I can not read them, nor with DICOMWorks, or with other players). Is this normal? Have I forgotten anything else?
Respectueusement,
MitMal

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#6 Post by Mitmal »

I do not understand this comment :

Code: Select all

  /** save object to a DICOM file.
     *  This method only supports DICOM objects stored as a dataset, i.e. without meta header.
     *  Use DcmFileFormat::saveFile() to save files with meta header.
     *  @param fileName name of the file to save
     *  @param writeXfer transfer syntax used to write the data (EXS_Unknown means use current)
     *  @param encodingType flag, specifying the encoding with undefined or explicit length
     *  @param groupLength flag, specifying how to handle the group length tags
     *  @param padEncoding flag, specifying how to handle the padding tags
     *  @param padLength number of bytes used for the dataset padding (has to be an even number)
     *  @param subPadLength number of bytes used for the item padding (has to be an even number)
     *  @return status, EC_Normal if successful, an error code otherwise
     */
I do not understand, what should I do to retrieve the original DICOM files?
Respectueusement,
MitMal

Roadrunner
Posts: 56
Joined: Mon, 2010-06-14, 16:41

#7 Post by Roadrunner »

The code was to remember me where it is coming from - the scp.h. ;-)

And the posted code with the dcmdataset->save(..) does really work because I am working with that code successfully.

Right now (not the published code) I am creating the dataset in the constructor of the class and moved some parts in the header file because creating the dcmdataset every time when there comes a new image without freeing creates a memory leaks. ;-)

Well you only need to move the whole class in a thread and you have what you're looking for.

Because of your 'not'-dicom files you can try some tools from the DVTk - and validate the received files. Maybe you find out whats wrong with the saved files.

Frank

Frank

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#8 Post by Mitmal »

Thx Frank, but
Well you only need to move the whole class in a thread and you have what you're looking for.
About what class are speaking before ?? I'm try to understand why my files are not in DICOM format...I don't understand why you want I use another thread... :?

About my "normal" file, when I open one of them with my text editor, I can read some information like : LA11GEPACS, ISO_IR 100, Philips Medical Systems, ANGIO IRM CERVICALE or AX FLAIR...

But when I open my receipt file I can not read anything...Just lot of Chinese symbols...

I use exactly the code :

Code: Select all

dataObject->saveFile(path);
(And I have not dcmdataset->save(..) function like you are proposing, just saveFile, sorry)

Do I fill (then) the other parameters of the function saveFile (...) with information (that I have to get in the request, as I do with the description of the series)?
Respectueusement,
MitMal

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#9 Post by Mitmal »

Up...

My code is now :

Code: Select all

//INSTANCE NUMBER
QString instanceNumber = getInstanceNumber(dataObject);
if (instanceNumber!="") instanceNumber.append("_");

//SLICE NUMBER
QString sliceName = "IMAGE";

//NOM DE LA COPIE
QString copyName = bValueName+""+instanceNumber+""+sliceName;
					
//E_TransferSyntax - SYNTAXE DE TRANSERT
OFString OFwriteXferUID;
//dataObject->findAndGetOFString(DCM_TransferSyntaxUID, OFwriteXferUID,0, true);
E_TransferSyntax writeXfer = EXS_Unknown; //Because OFwriteXferUID is empty

//E_EncodingType - TYPE D'ENCODAGE
OFString OFEncodingType;
//dataObject->findAndGetOFString(DCM_EncodingType, OFEncodingType,0, true);
E_EncodingType encodingType = EET_UndefinedLength;

//E_GrpLenEncoding
OFString OFgroupLength;
//dataObject->findAndGetOFString(DCM_GroupeLenght, OFEncodingType,0, true);
E_GrpLenEncoding groupLength = EGL_recalcGL;

//E_PaddingEncoding
OFString OFpadEncoding;
//dataObject->findAndGetOFString(DCM_paddingEncoding, OFEncodingType,0, true);
E_PaddingEncoding padEncoding = EPD_noChange;

//padLength
OFString OFpadLength;
//dataObject->findAndGetOFString(DCM_paddingEncoding, OFEncodingType,0, true);
Uint32 padLength = 0;

//subPadLength
OFString OFsubPadLength;
//dataObject->findAndGetOFString(DCM_subPadLegth, OFsubPadLength,0, true);
Uint32 subPadLength = 0;

QString path = MedicTool2::pathLoadedSerie+"/"+copyName;
/** save object to a DICOM file.
*  This method only supports DICOM objects stored as a dataset, i.e. without meta header.
*  Use DcmFileFormat::saveFile() to save files with meta header.
*  @param fileName name of the file to save
*  @param writeXfer transfer syntax used to write the data (EXS_Unknown means use current)
*  @param encodingType flag, specifying the encoding with undefined or explicit length
*  @param groupLength flag, specifying how to handle the group length tags
*  @param padEncoding flag, specifying how to handle the padding tags
*  @param padLength number of bytes used for the dataset padding (has to be an even number)
*  @param subPadLength number of bytes used for the item padding (has to be an even number)
*  @return status, EC_Normal if successful, an error code otherwise
*/
dataObject->saveFile(path,writeXfer,encodingType,groupLength,padEncoding,padLength,subPadLength);
But it is just a test. I put all the parameters at the default value...Maybe I have to download the right value from the dcmdata (CF : dataObject->findAndGetOFString) but there are no corresponding information in dcdeftag.h (according your advice)...

And do I had this parameters in my request ?? Like :

Code: Select all

DcmElement *dcmelementStudyDate = new DcmAttributeTag(DCM_StudyDate); req.insert(dcmelementStudyDate);
Thank you two
Respectueusement,
MitMal

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#10 Post by Mitmal »

up...Nobody can help me ??
Respectueusement,
MitMal

J. Riesmeier
DCMTK Developer
Posts: 2506
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

#11 Post by J. Riesmeier »

Sorry if I disturb you, but to me it seems that you should first of all ...
  1. Learn how to help yourself. This includes: Learn how to search the Internet for information.
  2. Read the DICOM standard or a good introduction on it in order to understand the basics.
  3. Read the documentation and check the example applications that are shipped with the DCMTK.
You should not start with programming unless you really know what you are doing!

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#12 Post by Mitmal »

You do not help me at all here!
I am looking for precisely information on the Internet via this forum because it seems to be most appropriate.
The DICOM Standard is just enormous and it is not at all easy to access. So I started directly in the programming and it is not so bad, I met some problems but overall, I go out (thanks to you).

I know what I want to do, I do not know how to do.
I would like to know why my code does not give me a DICOM file, since I get many files. Maybe you have an example or explanation.
Respectueusement,
MitMal

J. Riesmeier
DCMTK Developer
Posts: 2506
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

#13 Post by J. Riesmeier »

I will not comment on that. Only one question: Why don't you just follow the very simple examples from the documentation or the Wiki?
Furthermore, the DCMTK is full of more elaborated examples (mainly in the "apps" directories) on how to use this library and its functions.

Of course, if you have specific questions we are always willing to help (if we can) ...

Mitmal
Posts: 112
Joined: Mon, 2011-04-18, 19:36
Location: France

#14 Post by Mitmal »

Why not then tell me where to find these examples?
I'm no expert and I can not find the information or the examples in the book to be and the wiki ....

Since the beginning I announce clearly my questions and I have not changed my goal!
The codes I have found (outside this forum) never let me helped, I will see your links, but I do not understand why it's so hard to help me!?
Respectueusement,
MitMal

Rautenberg_ES
Posts: 6
Joined: Wed, 2011-09-28, 13:50

#15 Post by Rautenberg_ES »

Go here:

http://dicom.offis.de/dcmtk.php.en

There, download dcmtk 3.6.0 source code and extract... then check the "apps" folders in the contained directories.

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 1 guest