`
qimo601
  • 浏览: 3418485 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

DCMTK DCMScu和DCMScp 细节讨论

阅读更多


Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page 12345  Next
Author Message
 Post subject: PACS connection
PostPosted: Mon, 2011-11-07, 12:26 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Hello everybody, 
I trying to connect my new application to PACS Network. 
I found this code : 

Code:
connection(QString qipAdress, QString qport, QString qaet)
{

T_ASC_Network *net; // network struct, contains DICOM upper layer FSM etc.
//ASC_initializeNetwork(NET_REQUESTOR, 0, 1000 /* timeout */, &net);
ASC_initializeNetwork(NET_REQUESTOR, 104, 1000, &net);

T_ASC_Parameters *params; // parameters of association request
ASC_createAssociationParameters(&params, ASC_DEFAULTMAXPDU);

// set calling and called AE titles
ASC_setAPTitles(params, "ECHOSCU", "ANY-SCP", NULL);

// the DICOM server accepts connections at server.nowhere.com port 104
QString XXX = "server.nowhere.com:"+qport;
ASC_setPresentationAddresses(params, qipAdress, XXX);

// list of transfer syntaxes, only a single entry here
const char* ts[] = { UID_LittleEndianImplicitTransferSyntax };

// add presentation context to association request
ASC_addPresentationContext(params, 1, UID_VerificationSOPClass, ts, 1);

// request DICOM association
T_ASC_Association *assoc;
if (ASC_requestAssociation(net, params, &assoc).good())
{
   QMessageBox::information(0,"","Parametre ok");
   if (ASC_countAcceptedPresentationContexts(params) == 1)
      {
         QMessageBox::information(0,"","Connexion ok");
         // the remote SCP has accepted the Verification Service Class
         DIC_US id = assoc->nextMsgID++; // generate next message ID
         DIC_US status; // DIMSE status of C-ECHO-RSP will be stored here
         DcmDataset *sd = NULL; // status detail will be stored here
         // send C-ECHO-RQ and handle response
         DIMSE_echoUser(assoc, id, DIMSE_BLOCKING, 0, &status, &sd);
         delete sd; // we don't care about status detail
      }
}
ASC_releaseAssociation(assoc); // release association
ASC_destroyAssociation(&assoc); // delete assoc structure
ASC_dropNetwork(&net); // delete net structure
return 0;
}


But I do not understand it. 
What is "server.nowhere.com" ??? 

I suppose that I need to give who I am and where I want to be connected. So, in my example, "server.nowhere.com" could be qipAdress and qipAdress could be my ip adress ? Isn't it ? 

-------- 
And (AFTER), with this code, how I can ask some question to the server and download some Dicom pictures ??

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-07, 12:32 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

Quote:
I suppose that I need to give who I am and where I want to be connected. So, in my example, "server.nowhere.com" could be qipAdress and qipAdress could be my ip adress ? Isn't it ?


XXX is the server you want to connect to. qipAdress is your own adress. 

This is the original example in the online documentation

Also, instead, you might use the DcmSCU class which is more object-oriented. Anexample can be found in our support wiki

Best regards, 
Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-07, 12:57 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Thanks Michael, 

But I don't understand : 
With : ASC_setPresentationAddresses(params, "120.40.30.99:104", qipAdress+":"+qport); the connection is failded. 

And with : ASC_setPresentationAddresses(params, qipAdress+":"+qport, "120.40.30.99:104"); the connection is done. 

(I mine when it is done, I can read the ok message) 

I will test now with your second option, the class DcmSCU, and I go back to keep you inform 

*************** 
As for me, if I switch the two parameter, my ip address, and the server, the connection is done even if the network is broken. So maybe something listen on my computer, sorry...

_________________
Respectueusement, 
MitMal
 

Last edited by Mitmal on Mon, 2011-11-07, 13:25, edited 1 time in total. 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-07, 13:11 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
And just before, can you explain to me what this line mines: 
ASC_initializeNetwork(NET_REQUESTOR, 0, 1000 /* timeout */, &net); 

0 is it my port or the server port ?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-07, 13:51 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Looking into the header file: 
Code:
/** network instance creation function (constructor)
*  @param role association acceptor, requestor or both
*  @param acceptorPort acceptor port for incoming connections.
*    For association requestors, zero should be passed here.
*  @param timeout timeout for network operations, in seconds
*  @param network T_ASC_Network will be allocated and returned in this parameter
*  @param options network options. Only DUL_FULLDOMAINNAME is currently defined
*    as a possible option.
*  @return EC_Normal if successful, an error code otherwise
*/
OFCondition ASC_initializeNetwork(
    T_ASC_NetworkRole role,
    int acceptorPort,
    int timeout,
    T_ASC_Network ** network,
    unsigned long options = 0);


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-07, 13:54 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Of course, thank you, know I will look every time in the header ;-)

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-08, 12:06 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I trying to use the DcmSCU example, but I don't understand this part : 
Code:
int MedicTool2::connectionPacs(QString serverIpAdress, QString serverPort, QString serverAet, QString myIpAdress, QString myPort, QString myAet)
{
   QProgressDialog progressDialog ("Connecting\nPlease wait...",QString(),0,100);
   progressDialog.setWindowModality(Qt::WindowModal);
   progressDialog.show();

   /* Setup DICOM connection parameters */
   OFLog::configure(OFLogger::DEBUG_LOG_LEVEL);
   DcmTestSCU scu;
progressDialog.setValue(10);

   // set AE titles
   OFString ipAdresse = serverIpAdress;
   Uint16 port = serverPort.toUInt();
   OFString aet = serverAet;

   scu.setAETitle("TEST-SCU" );
   scu.setPeerHostName(ipAdresse);
   scu.setPeerPort(port);
   scu.setPeerAETitle(aet);


In setAETitle, setPeerHostName, setPeerPort, setPeerAETitle what kind of information I need to give ?


**********************
After looking in the header file , I saw:
Code:
/** Set SCU's AETitle to be used in association negotiation
   *  @param myAETtitle [in] The SCU's AETitle to be used
   */
  void setAETitle(const OFString &myAETtitle);

  /** Set SCP's host (hostname or IP address) to talk to in association negotiation
   *  @param peerHostName [in] The SCP's hostname or IP address to be used
   */
  void setPeerHostName(const OFString &peerHostName);

  /** Set SCP's AETitle to talk to in association negotiation
   *  @param peerAETitle [in] The SCP's AETitle to be used
   */
  void setPeerAETitle(const OFString &peerAETitle);


So I add this lines :
Code:
// set AE titles
   OFString OFmyAet = myAet;
   OFString OFipAdresse = serverIpAdress;
   Uint16 OFport = serverPort.toUInt();
   OFString OFaet = serverAet;

   scu.setAETitle(OFmyAet);
   scu.setPeerHostName(OFipAdresse);
   scu.setPeerPort(OFport);
   scu.setPeerAETitle(OFaet);


But the process failed, I can read the display 40 but after it's write "Unable to negotiate association: " :
Code:
   /* Initialize network */ 
   OFCondition result = scu.initNetwork(); 
   if (result.bad()) 
   { 
      QMessageBox::information(0,"","Unable to set up the network: ");
      return 1; 
   }
progressDialog.setValue(40);

   /* Negotiate Association */ 
   result = scu.negotiateAssociation(); 
   if (result.bad()) 
   {
      QMessageBox::information(0,"","Unable to negotiate association: "); 
      return 1; 
   }
progressDialog.setValue(50);


I will search how to add the result.text() but maybe have you some ideas ?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-08, 12:26 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
The message is : 
Quote:
Unable to negociate association: DUL Association Rejected


Can you explain me what is it ? 


*********************** 
Ok, it was my fault (logically), i was make a fault in my AETitle...lol

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-08, 15:14 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Great, now I can run a ECHO test on my connection to the PACS. 
Now I need to search (name, first name, number, date ...) and after download the images on my hard drive. 

Do you know how to do this?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-08, 15:21 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
For those who are interested, my function ECHO is : 
Code:
/***
Connexion et tentative de requete ECHO vers le noeud DICOM spécifié
-serverIpAdress represente l'adresse IP nécéssaire à la connexion
-serverPort represente le numero du port nécéssaire à la connexion, coté serveur
-serverAet represente l'AET nécéssaire à la connexion
-monIpAdress represente l'adresse IP de la machine
-monPort represente le numero du port nécéssaire à la connexion coté client
-monAet represente l'AET de la machine
*/
bool MedicTool2::echoDicomNode(QString serverIpAdress, QString serverPort, QString serverAet, QString monIpAdress, QString monPort, QString monAet)
{
   QProgressDialog progressDialog ("Connexion ECHO en cours\nVeuillez patienter...",QString(),0,60);
   progressDialog.setWindowModality(Qt::WindowModal);
   progressDialog.show();

   //Mise en place des parametre pour établire la connexion DICOM
   OFLog::configure(OFLogger::DEBUG_LOG_LEVEL);
   DcmTestSCU scu;
progressDialog.setValue(10);

   //Mise en place des parametres AET
   OFString OFmonAet = monAet;            scu.setAETitle(OFmonAet);
   OFString OFipAdresse = serverIpAdress;   scu.setPeerHostName(OFipAdresse);
   Uint16 OFport = serverPort.toUInt();   scu.setPeerPort(OFport);
   OFString OFaet = serverAet;            scu.setPeerAETitle(OFaet);
progressDialog.setValue(20);

   //Utilisation du contexte de présentation FIND / MOVE dans la racine des series, pour proposer toutes les syntaxes de transfert compressées (Use presentation context for FIND/MOVE in study root, propose all uncompressed transfer syntaxes)
   OFList<OFString> ts; 
   ts.push_back(UID_LittleEndianExplicitTransferSyntax); 
   ts.push_back(UID_BigEndianExplicitTransferSyntax); 
   ts.push_back(UID_LittleEndianImplicitTransferSyntax); 
   scu.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, ts); 
   scu.addPresentationContext(UID_MOVEStudyRootQueryRetrieveInformationModel, ts); 
   scu.addPresentationContext(UID_VerificationSOPClass, ts);
progressDialog.setValue(30);

   //Initialisation du reseau
   OFCondition result = scu.initNetwork(); 
   if (result.bad()) 
   {//PROBLEME DE CONNEXION
      QString add = result.text();
      QMessageBox::information(0,"Test ECHO","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nImpossible d'initialiser le reseau: "+add);
      return false; 
   }
progressDialog.setValue(40);

   //TENTATIVE D'ASSOCIATION
   result = scu.negotiateAssociation(); 
   if (result.bad()) 
   {//PROBLEME D'IDENTIFICATION
      QString add = result.text();
      QMessageBox::information(0,"Test ECHO","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nImpossible de negocier l'association: "+add);
      return false; 
   }
progressDialog.setValue(50);

   //Voyons si le serveur est en écoute: Contruction et envoi d'une demande C-ECHO (Let's look whether the server is listening: Assemble and send C-ECHO request)
   result = scu.sendECHORequest(0); 
   if (result.bad()) 
   {//PROBLEME, LE SERVER NE REPOND PAS
      QString add = result.text();
      QMessageBox::information(0,"Test ECHO","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nImpossible d'utiliser le processus E-ECHO avec le serveur: "+add);
      return false;
   }
   else return true;
progressDialog.setValue(60);
   return false;
}


I am looking how to add a specific request now, may it be here, right?
Code:
//Construction et envoi d'une requete C-FIND, pour trouver les examens
   FINDResponses findResponses; 
   DcmDataset req; 
   req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "STUDY");
   req.putAndInsertOFStringArray(DCM_StudyInstanceUID, "DUMONT^NICOLAS"); 
   T_ASC_PresentationContextID presID = findUncompressedPC(UID_FINDStudyRootQueryRetrieveInformationModel, scu);
   if (presID == 0) 
   {//PROBLEME avec le contexte de présentation
      QMessageBox::information(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl n'y a pas de contexte de présentation non compressé pour Study Root FIND");
      return 1; 
   }


But that does not work ... I am looking for, if you have ideas :wink:

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-08, 15:23 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Problem, I have FINDResponses but I do not have MOVEResponses...do you know why ???? :cry:

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-08, 19:00 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I tested with: 
Code:
req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "STUDY");
req.putAndInsertOFStringArray(DCM_StudyInstanceUID, "");
   
req.putAndInsertOFStringArray(DCM_PatientName, "DUMONT");
req.putAndInsertOFStringArray(DCM_Modality, "CT");
req.putAndInsertOFStringArray(DCM_PatientID,"001578802");


But that does not seem correct. The results are not correct in with my PACS data (when I use an other viewer)

Can you tell me if this is the right approach?
I want to search according to some criteria:
- Patient's name
- The patient's first name (or name and surname together)
- modality
- Earlier
- Date posterior
- And also the type of sequence can be (but it may be difficult)


************************
Here is my code now:

Code:
//Construction et envoi d'une requete C-FIND, pour trouver les examens
   FINDResponses findResponses;
   DcmDataset req;
   req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "SERIES");
   //req.putAndInsertOFStringArray(DCM_StudyInstanceUID, "");
   
   QString nom = "RADERANIRINA Sendrison";
   nom.replace(" ","^");
   OFString OFNom = nom;
   req.putAndInsertOFStringArray(DCM_PatientName, OFNom);
   //req.putAndInsertOFStringArray(DCM_Modality, "CT");
   //req.putAndInsertOFStringArray(DCM_PatientID,"001578802");


The search takes me back out the number 10, which corresponds to the number of series to my patients the on PACS. 
Only now I wish I could find the patient starting with a beginning, or have a string in their name. 
A little like in SQL, when I try using% xxx% 

Do you know how to do this?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-09, 11:38 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

Quote:
Problem, I have FINDResponses but I do not have MOVEResponses...do you know why ????


Maybe you have a version installed that is not depending on the latest snapshots? See also note at the end of the DcmSCU example on the wiki.

Quote:
Can you tell me if this is the right approach?


Query/Retrieve requests need to follow specific rules, laid down in part 4 of the DICOM standard. I explained the most basic ones several times in the forum; please try to understand by reading the standard and searching the forum. 

Best regards, 
Michael 

P.S: Sorry to interrupt your thread :-)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-09, 12:53 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
hum hum thank you Michael but it does not help me ^ ^ 
But that's OK, here is my code with which I can get my info: 
Code:
req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "STUDY");
   //req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "SERIES");
   
   //CONSTRUCTION DE LA REQUETE
   //AVEC LES CHAMPS DU FILTRE
   QString nom = MedicUi.m_lineEditName->text()+"*"; nom.replace(" ","^"); OFString OFNom = nom; req.putAndInsertOFStringArray(DCM_PatientName, OFNom);
   QString d1 =  MedicUi.m_lineEditExamD1->text();
   QString d2 =  MedicUi.m_lineEditExamD1->text();

   //CHAMPS INDISPENSEMBLE
   req.putAndInsertOFStringArray(DCM_Modality, "MR");
   //req.putAndInsertOFStringArray(DCM_SeriesDescription, "PERFUSION");

   //INFORMATIONS NECESSAIRE POUR IDENTIFIER L'EXAMEN
   DcmElement *dcmelementStudyDate = new DcmAttributeTag(DCM_StudyDate); req.insert(dcmelementStudyDate);
   DcmElement *dcmelementPatientName = new DcmAttributeTag(DCM_PatientName); req.insert(dcmelementPatientName);
   DcmElement *dcmelementModality = new DcmAttributeTag(DCM_Modality); req.insert(dcmelementModality);
   DcmElement *dcmelementNaissancePatient = new DcmAttributeTag(DCM_PatientBirthDate); req.insert(dcmelementNaissancePatient);
   DcmElement *dcmelementIDPatient = new DcmAttributeTag(DCM_PatientID); req.insert(dcmelementIDPatient);
   DcmElement *dcmelementStudyDescription = new DcmAttributeTag(DCM_StudyDescription); req.insert(dcmelementStudyDescription);
   DcmElement *dcmelementCommentairePatient = new DcmAttributeTag(DCM_PatientComments); req.insert(dcmelementCommentairePatient);
   DcmElement *dcmelementSexePatient = new DcmAttributeTag(DCM_PatientSex); req.insert(dcmelementSexePatient);
   DcmElement *dcmelementStudyId = new DcmAttributeTag(DCM_StudyID); req.insert(dcmelementStudyId);

   T_ASC_PresentationContextID presID = findUncompressedPC(UID_FINDStudyRootQueryRetrieveInformationModel, scu);
   if (presID == 0)
   {//PROBLEME avec le contexte de présentation
      QMessageBox::information(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl n'y a pas de contexte de présentation non compressé pour Study Root FIND");
      return res;
   }
progressDialog.setValue(70);

   result = scu.sendFINDRequest(presID, &req, &findResponses);
   if (result.bad())
   {//PROBLEME AVEC LE RESULTAT DE LA RECHERCHE, il n'y a pas de serie disponnible
      QString add = result.text();
      QMessageBox::information(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl n'y a pas de series disponnibles: "+add);
      return res;
   }
   else
   { //La connexion est opérationnelle et il y a des series à récupérer
      //QMessageBox::information(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl y a des series disponnibles");
   }
progressDialog.setValue(80);

   //Construction et envoi d'une requete C-MOVE, pour tous les examens identifiés au dessus
   presID = findUncompressedPC(UID_MOVEStudyRootQueryRetrieveInformationModel, scu);
   if (presID == 0)
   {//PROBLEME avec le contexte de présentation
      QMessageBox::information(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl n'y a pas de contexte de présentation non compressé pour Study Root MOVE");
      return res;
   }
progressDialog.setValue(90);

   OFListIterator(FINDResponse*) study = findResponses.begin();
   Uint32 studyCount = 1;
   OFBool failed = OFFalse;
   int nbr = 0;
   while (study != findResponses.end() && result.good())
   {
      
      //Chaque boucle exécuté récupère toutes l'image
      //MOVEResponses moveResponses;

      //Etre sûr que ce n'est pas la dernière réponse, car elle n'a pas de données
      if ( (*study)->m_dataset != NULL)
      {
         OFString studyInstanceUID;
         result = (*study)->m_dataset->findAndGetOFStringArray(DCM_StudyInstanceUID, studyInstanceUID);
         //On essaye seulement de récupérer la série si il y a effectivement un ID d'instance de série, sinon on l'ignore
         if (result.good())
         {
            //req.putAndInsertOFStringArray(DCM_StudyInstanceUID, studyInstanceUID);
            // On récupère toutes les images de cette série particulière
            QString val = "";
            OFString OFStrin; 
            (*study)->m_dataset->findAndGetOFString(DCM_StudyDate, OFStrin); val = val +"Date examen: "+OFStrin.c_str()+""+Outils::separateur;
            (*study)->m_dataset->findAndGetOFString(DCM_PatientName, OFStrin); val = val +"Nom patient: "+OFStrin.c_str()+""+Outils::separateur;
            (*study)->m_dataset->findAndGetOFString(DCM_Modality, OFStrin); val = val +"Modalité: "+OFStrin.c_str()+"\n";
            (*study)->m_dataset->findAndGetOFString(DCM_PatientBirthDate, OFStrin); val = val +"Date de Naissance patient: "+OFStrin.c_str()+"\n";
            (*study)->m_dataset->findAndGetOFString(DCM_PatientID, OFStrin); val = val +"ID patient: "+OFStrin.c_str()+"\n";
            (*study)->m_dataset->findAndGetOFString(DCM_StudyDescription, OFStrin); val = val +"Description Examen: "+OFStrin.c_str()+"\n";
            (*study)->m_dataset->findAndGetOFString(DCM_PatientComments, OFStrin); val = val +"Commentaire patient: "+OFStrin.c_str()+"\n";
            (*study)->m_dataset->findAndGetOFString(DCM_PatientSex, OFStrin); val = val +"Sexe: "+OFStrin.c_str()+"\n";
            (*study)->m_dataset->findAndGetOFString(DCM_StudyID, OFStrin); val = val +"ID examen: "+OFStrin.c_str()+"\n";
            res = res + val;
            QMessageBox::information(0,"RESULTAT",val);

            /*result = scu.sendMOVERequest(presID, "MOVESCP", &req, &moveResponses);
            if (result.good())
            {
               QMessageBox::information(0,"","Received study #");
               studyCount++;
            }*/

            nbr++;
            if (nbr>1000) break;
         }
      } 
      study++; 
   }
   //QString val = ""; val.sprintf("%d",nbr); QMessageBox::information(0,"CONNEXION","Il y a "+val+" réponse");

   if (result.bad()) 


I must specify in the request what attributes I want it back. 
(As QSL, after the SELECT, I must say what I want fields to return) 

------------- 

For MOVEResponses I saw the comment at the bottom of the wiki, only it does not explain (or I do not understand) what to do

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-09, 12:58 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
For the MOVEResponse: If it is not part of your DCMTK installation, then you need to get a newer version, e.g. the latest snapshot

Michael


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous: All posts 1 day 7 days 2 weeks 1 month 3 months 6 months 1 year Sort by Author Post time Subject Ascending Descending 
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page 12345  Next

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: Google [Bot]qimo601 and 2 guests


You can post new topics in this forum
You can reply to topics in this forum
You can edit your posts in this forum
You can delete your posts in this forum

Search for:  
Jump to:   Select a forum  ------------------  General     Announcements     Imprint / Impressum     Off-topic  DCMTK     DCMTK - FAQ     DCMTK - Installation     DCMTK - General     Third-Party DCMTK Applications  DICOMscope     DICOMscope - Installation     DICOMscope - General     IHE MESA CPI Test Suite  Other Tools     DCMPRINT     DCMCHECK     DCMJP2K     DCMRT     Other DICOM Tools  DRG CD-Test (in German language)     Allgemeine Diskussion / General Discussion     Anforderungskatalog / CD Specification     Leitfaden für Patienten-CDs / Guidelines for Handling Patient CDs     CD-Prüfung / CD Validation     
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

DICOM @ OFFIS

Discussion Forum for OFFIS DICOM Tools - For registration, send email with desired username to the OFFIS DICOM team
Last visit was: Thu, 2012-09-13, 03:27 It is currently Thu, 2012-09-13, 09:16

All times are UTC + 1 hour [ DST ]




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page Previous  12345  Next
Author Message
 Post subject:
PostPosted: Wed, 2011-11-09, 13:18 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
It should be possible to make image retrieval with my current version (3.6.0) 
I guess it was possible before, right?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-09, 15:44 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

yes but you have to derive your own class from DcmSCU and add functions sendMOVERequest() yourself. 

Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-09, 15:54 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Arf ... Do you have an example for me?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-09, 16:17 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Yes, look into the current version of DcmSCU which already contains such a function as I said ;) E.g. either check the snapshot I posted above or browse/clone the DCMTK git repository

Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-11-10, 14:48 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Is it possible to add one, or two, Date in my request ?? 
( For example, if I search all the examen after 1986/01/28 but before 1986/12/31 )

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-11-10, 15:19 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
You can specify date and time ranges. e.g. for study date send "19860128- 19861231". Details are in the standard, part 4 in the chapter about query/retrieve. 

All the best, 
Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-11-10, 16:15 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I tested with this code but it does not work : 
Code:
req.putAndInsertOFStringArray(DCM_StudyDate, "2003/10/01-2003/10/05");

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-14, 12:52 
Offline
DCMTK Developer

Joined: Tue, 2011-05-03, 15:38
Posts: 706
What about following the DICOM standard (and what my colleague suggested): remove the "/" from the element value. "20031001-20031005" would be correct in terms of range matching.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-14, 14:38 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Perfect, it works fine. 
I would like now specify a series in my study is in perfusion, is it possible? 
May be looking at the number of images ...

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-16, 16:48 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Now that I changed my version of DCMTK with the latest snapshothttp://dicom.offis.de/download/dcmtk/snapshot/ 
I have a new error:
Code:
1> Application.cpp (431): error C2065: 'FINDResponses': undeclared identifier

And line 431 there is just : FINDResponses findResponses; 

But I have not changed anything other than DCMTK ... And with the old version it works well. 

Do you know why?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-16, 19:32 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
And when I look in the directory DCMTK where it says the word FINDResponses there is no response .... strange ....

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-11-18, 16:34 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Nobody can help me? 
No solution? 
I really need to retrieve images from the network

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-11-18, 19:29 
Offline
DCMTK Developer

Joined: Tue, 2011-05-03, 15:38
Posts: 706
What about helping yourself by looking at the source code or documentation? The DcmSCU and DcmSCP classes are experimental, so there are still many incompatible changes ...


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-21, 23:33 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
In fact, if I understand correctly, the old uses an object FINDResponses scu, scu the new does not use this object, but uses MOVEResponses ... So the example (DcmSCU example program) is what ????? 

Because I'm lost ... I try to make a mix of the two classes but I can not. Can anyone help me? 
I would like to replace the class scu by a mix of both ... To use the example given on the site :-(

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-22, 00:14 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I am looking MOVEResponses in the directory of the "new" DCMTK (last snapshot) 
And I find nothing more than scu.cc 
So until now I thought the statement was in MOVEResponses scu.cc, but not at all ... There is just a comment that talks about MOVEResponses ... 

So I'm lost, where the MOVEResponses should be exactly?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
Display posts from previous: All posts 1 day 7 days 2 weeks 1 month 3 months 6 months 1 year Sort by Author Post time Subject Ascending Descending 
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page Previous  12345  Next

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: qimo601 and 1 guest


You can post new topics in this forum
You can reply to topics in this forum
You can edit your posts in this forum
You can delete your posts in this forum

Search for:  
Jump to:   Select a forum  ------------------  General     Announcements     Imprint / Impressum     Off-topic  DCMTK     DCMTK - FAQ     DCMTK - Installation     DCMTK - General     Third-Party DCMTK Applications  DICOMscope     DICOMscope - Installation     DICOMscope - General     IHE MESA CPI Test Suite  Other Tools     DCMPRINT     DCMCHECK     DCMJP2K     DCMRT     Other DICOM Tools  DRG CD-Test (in German language)     Allgemeine Diskussion / General Discussion     Anforderungskatalog / CD Specification     Leitfaden für Patienten-CDs / Guidelines for Handling Patient CDs     CD-Prüfung / CD Validation     
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

DICOM @ OFFIS

Discussion Forum for OFFIS DICOM Tools - For registration, send email with desired username to the OFFIS DICOM team
Last visit was: Thu, 2012-09-13, 03:27 It is currently Thu, 2012-09-13, 09:16

All times are UTC + 1 hour [ DST ]




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page Previous  12345  Next
Author Message
 Post subject:
PostPosted: Tue, 2011-11-22, 00:48 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I finally replaced by MOVEResponses OFList <RetrieveResponse*>, but now all the virtual methods in scuN.h (N means that it is the last version of the snapshot) are problematic. 

For example: 

Code:
1>XXX.obj : error LNK2019: unresolved external symbol "public: __thiscall DcmSCUN::DcmSCUN(void)" (??0DcmSCUN@@QAE@XZ) referenced in function "public: __thiscall DcmTestSCUN::DcmTestSCUN(void)" (??0DcmTestSCUN@@QAE@XZ)

Code:
1>XXX.obj : error LNK2001: unresolved external symbol "public: virtual class OFCondition __thiscall DcmSCUN::initNetwork(void)" (?initNetwork@DcmSCUN@@UAE?AVOFCondition@@XZ)

Code:
1>XXX.obj : error LNK2001: unresolved external symbol "public: virtual class OFCondition __thiscall DcmSCUN::negotiateAssociation(void)" (?negotiateAssociation@DcmSCUN@@UAE?AVOFCondition@@XZ)

Code:
1>XXX.obj : error LNK2001: unresolved external symbol "public: virtual class OFCondition __thiscall DcmSCUN::sendECHORequest(unsigned char)" (?sendECHORequest@DcmSCUN@@UAE?AVOFCondition@@E@Z)

Code:
1>XXX.obj : error LNK2001: unresolved external symbol "public: virtual class OFCondition __thiscall DcmSCUN::sendSTORERequest(unsigned char,class OFString const &,class DcmDataset *,class DcmDataset * &,class DcmDataset * &,unsigned short &)" (?sendSTORERequest@DcmSCUN@@UAE?AVOFCondition@@EABVOFString@@PAVDcmDataset@@AAPAV4@2AAG@Z)

Code:
1>XXX.obj : error LNK2001: unresolved external symbol "public: virtual class OFCondition __thiscall DcmSCUN::sendMOVERequest(unsigned char,class OFString const &,class DcmDataset *,class OFList<class RetrieveResponse *> *)" (?sendMOVERequest@DcmSCUN@@UAE?AVOFCondition@@EABVOFString@@PAVDcmDataset@@PAV?$OFList@PAVRetrieveResponse@@@@@Z)

Code:
1>XXX.obj : error LNK2001: unresolved external symbol "public: virtual class OFCondition __thiscall DcmSCUN::handleMOVEResponse(unsigned char,class RetrieveResponse *,bool &)" (?handleMOVEResponse@DcmSCUN@@UAE?AVOFCondition@@EPAVRetrieveResponse@@AA_N@Z)

Code:
1>XXX.obj : error LNK2001: unresolved external symbol "public: virtual class OFCondition __thiscall DcmSCUN::sendCGETRequest(unsigned char,class DcmDataset *,class OFList<class RetrieveResponse *> *)" (?sendCGETRequest@DcmSCUN@@UAE?AVOFCondition@@EPAVDcmDataset@@PAV?$OFList@PAVRetrieveResponse@@@@@Z)


I'm really bothered by this problem. I really need your help :-(

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-22, 01:47 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
ok, here I finally found a solution. I import the latest snapshot of dcmnet.lib IN ADDITION to the original version. (in the properties of my project of course) (Adding an N at the end of the name.) 

I just been obliged to comment out the function: virtual void closeAssociation (const DcmCloseAssociationType closeType) and in scuN.h and scuN.cc 

But now it works, the principal. 

It remains to understand how to retrieve the images now. I use, as in the example, sendMOVERequest, but where do I specify the destination folder of images??

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-22, 01:56 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
So here, I have a problem when I use: 
Code:
result = scuN.sendMOVERequest (chaired, OFmonAet, & req, & moveResponses)

OFmonAet is my AET.

Here is the error message:
Code:
Passed in year DIMS Caller illegal association


Do you understand why?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-22, 15:10 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
This is really the error message?! Looks weird. 

Anyway, did you start the association? 

Do you know that MOVE will not send the images on a different connection? You may setup storescp to receive the images on your machine. Also have configured the destination AE title on the PACS to point to your machine and to your storage receiver's IP and port (e.g. storescp). 

Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-23, 11:09 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I do not understand, can you give me a more telling example please?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-23, 11:50 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

the code in the DcmSCU howto (showing a C-MOVE client) does not retrieve any images since this is not how C-MOVE works. C-MOVE (and the code examples) initiates transfer which the PACS starts on a separate connection, where the receiver might be your computer or any other one. 

Please look into the standard (part 4 on Q/R, maybe also part 7 on C-MOVE) in order to fully understand how this works. Also, I explained it several times in the forum, you may search for it. 

Best regards, 
Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-23, 13:02 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I still do not understand. Why should I use sendMOVERequest while you tell me that I should use STORESCP? Can you give me a link, or more, please? 

Is not it possible to have a link explaining how to retrieve images from the PACS? The full procedure? 
Is there a sample code to do this? My connection works fine, but I do not know how to use STORESCP. 

thank you

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-23, 13:36 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Mitmal, please read what I pointed you to; I cannot explain to you how to use a hammer when you do not try to understand the concept of nails first. 

Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-23, 15:00 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I do not understand what you want me to learn. 
Here is my code: 

Code:
/***
Charge sur le disque les series qui sont demandées depuis la zone d'importation
-serverIpAdress represente l'adresse IP nécéssaire à la connexion
-serverPort represente le numero du port nécéssaire à la connexion, coté serveur
-serverAet represente l'AET nécéssaire à la connexion
-monIpAdress represente l'adresse IP de la machine
-monPort represente le numero du port nécéssaire à la connexion coté client
-monAet represente l'AET de la machine
-listeStudyIDGet représente la liste des DCM_StudyInstanceUID des Study à charger sur le disque
*/
bool MedicTool2::getImagePacs(QString serverIpAdress, QString serverPort, QString serverAet, QString monIpAdress, QString monPort, QString monAet, QStringList listeStudyIDGet)
{
   for (int numeroStudy=0; numeroStudy<listeStudyIDGet.size();numeroStudy++) //Idéalement cette boucle devrait etre placée plus en profondeur pour ne pas redemander une connexion à chaque fois au serveur
   {
      //Récupération de l'examen courant
      QString numeroIDStudy = listeStudyIDGet[numeroStudy];
      
      QProgressDialog progressDialog (tr("Récuperation en cours :")+" "+numeroIDStudy+"\n"+tr("Veuillez patienter..."),QString(),0,100);
      progressDialog.setWindowModality(Qt::WindowModal);
      progressDialog.show();

      //Mise en place des parametre pour établire la connexion DICOM
      OFLog::configure(OFLogger::DEBUG_LOG_LEVEL);
      DcmTestSCU scu;
      DcmTestSCUN scuN;
   progressDialog.setValue(10);

      //Mise en place des parametres AET
      OFString OFmonAet = monAet;            scu.setAETitle(OFmonAet);         scuN.setAETitle(OFmonAet);
      OFString OFipAdresse = serverIpAdress;   scu.setPeerHostName(OFipAdresse);   scuN.setPeerHostName(OFipAdresse);
      Uint16 OFport = serverPort.toUInt();   scu.setPeerPort(OFport);         scuN.setPeerPort(OFport);
      OFString OFaet = serverAet;            scu.setPeerAETitle(OFaet);         scuN.setPeerAETitle(OFaet);
   progressDialog.setValue(20);

      //Utilisation du contexte de présentation FIND / MOVE dans la racine des series, pour proposer toutes les syntaxes de transfert compressées (Use presentation context for FIND/MOVE in study root, propose all uncompressed transfer syntaxes)
      OFList<OFString> ts; 
      ts.push_back(UID_LittleEndianExplicitTransferSyntax); 
      ts.push_back(UID_BigEndianExplicitTransferSyntax); 
      ts.push_back(UID_LittleEndianImplicitTransferSyntax); 
      scu.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, ts); scu.addPresentationContext(UID_MOVEStudyRootQueryRetrieveInformationModel, ts); scu.addPresentationContext(UID_VerificationSOPClass, ts);
      scuN.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, ts); scuN.addPresentationContext(UID_MOVEStudyRootQueryRetrieveInformationModel, ts); scuN.addPresentationContext(UID_VerificationSOPClass, ts);
   progressDialog.setValue(30);

      //Initialisation du reseau
      OFCondition result = scu.initNetwork();
      result = scuN.initNetwork();
      if (result.bad()) 
      {//PROBLEME DE CONNEXION
         QString add = result.text();
         QMessageBox::warning(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nImpossible d'initialiser le reseau: "+add);
         return false; 
      }
   progressDialog.setValue(40);

      //TENTATIVE D'ASSOCIATION
      result = scu.negotiateAssociation();
      result = scuN.negotiateAssociation();
      if (result.bad()) 
      {//PROBLEME D'IDENTIFICATION
         QString add = result.text();
         QMessageBox::warning(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nImpossible de negocier l'association: "+add);
         return false; 
      }
   progressDialog.setValue(50);

      //Voyons si le serveur est en écoute: Contruction et envoi d'une demande C-ECHO (Let's look whether the server is listening: Assemble and send C-ECHO request)
      result = scu.sendECHORequest(0);
      result = scuN.sendECHORequest(0);
      if (result.bad()) 
      {//PROBLEME, LE SERVER NE REPOND PAS
         QString add = result.text();
         QMessageBox::warning(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nImpossible d'utiliser le processus E-ECHO avec le serveur: "+add);
         return false;
      }
   progressDialog.setValue(60);

      //Construction et envoi d'une requete C-FIND, pour trouver les examens
      FINDResponses findResponses;
      OFList<QRResponse*> OFfindResponses;
   
      DcmDataset req;
      req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "STUDY");
   
      //CONSTRUCTION DE LA REQUETE
      //Avec les numéro ID des series selectionnées
      OFString OFNumeroIDStudy = numeroIDStudy;
      req.putAndInsertOFStringArray(DCM_StudyInstanceUID, OFNumeroIDStudy);

      T_ASC_PresentationContextID presID = findUncompressedPC(UID_FINDStudyRootQueryRetrieveInformationModel, scu);
      presID = findUncompressedPC(UID_FINDStudyRootQueryRetrieveInformationModel, scuN);
      if (presID == 0)
      {//PROBLEME avec le contexte de présentation
         QMessageBox::warning(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl n'y a pas de contexte de présentation non compressé pour Study Root FIND");
         return false;
      }
   progressDialog.setValue(70);

      result = scu.sendFINDRequest(presID, &req, &findResponses);
      result = scuN.sendFINDRequest(presID, &req, &OFfindResponses);
      if (result.bad())
      {//PROBLEME AVEC LE RESULTAT DE LA RECHERCHE, il n'y a pas de serie disponnible
         QString add = result.text();
         QMessageBox::warning(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl n'y a pas de series disponnibles: "+add);
         return false;
      }
      else
      { //La connexion est opérationnelle et il y a des series à récupérer
         //QMessageBox::information(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl y a des series disponnibles");
      }
    progressDialog.setValue(80);

      //Construction et envoi d'une requete C-MOVE, pour tous les examens identifiés au dessus
      presID = findUncompressedPC(UID_MOVEStudyRootQueryRetrieveInformationModel, scu);
      presID = findUncompressedPC(UID_MOVEStudyRootQueryRetrieveInformationModel, scuN);
      if (presID == 0)
      {//PROBLEME avec le contexte de présentation
         QMessageBox::warning(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nIl n'y a pas de contexte de présentation non compressé pour Study Root MOVE");
         return false;
      }
   progressDialog.setValue(90);

      //OFListIterator(FINDResponse*) study = findResponses.begin();
      OFListIterator(QRResponse*) study = OFfindResponses.begin();
      Uint32 studyCount = 1; 
      OFBool failed = OFFalse; 
      while (study != OFfindResponses.end() && result.good()) 
      { 
         // Pour chaque boucle en réponse, soit chaque examen, toutes les images seront récupérées
         OFList<RetrieveResponse*> moveResponses;//MOVEResponses moveResponses; 

         if ( (*study)->m_dataset != NULL) //Il faut etre certain que ce n'est pas la derniere réponse, elle ne contient pas d'information
         { 
            OFString studyInstanceUID;
            result = (*study)->m_dataset->findAndGetOFStringArray(DCM_StudyInstanceUID, studyInstanceUID); 
            // only try to get study if we actually have study instance uid, otherwise skip it 
            if (result.good()) 
            {
               req.putAndInsertOFStringArray(DCM_StudyInstanceUID, studyInstanceUID); 
               // fetches all images of this particular study 
               OFString OFmonAet = monAet;
               result = scuN.sendMOVERequest(presID, OFmonAet, &req, &moveResponses); 
               if (result.good()) 
               { 
                  QMessageBox::information(0,"CONNEXION","YES MA POULE");
                  studyCount++; 
               }
               else
               {
                  QString add = result.text();
                  QMessageBox::warning(0,"Recuperation depuis noeud DICOM","A) Problème : Impossible de récupérer l'examen distant : "+add);
                  return false;
               }
            }
            else
            {
               QString add = result.text();
               QMessageBox::warning(0,"Recuperation depuis noeud DICOM","B) Problème ; impossible de récupérer l'instance ID de l'examen récupéré sur le reseau : "+add);
               return false;
            }
         }
         else
         {
            QMessageBox::warning(0,"Recuperation depuis noeud DICOM","C) Problème : pionteur vers examen récupéré NULL");
            return false;
         }
         study++; 
      }

      if (result.bad()) 
      { 
         QString add = result.text();
         QMessageBox::warning(0,"CONNEXION","TENTATIVE DE CONNEXION :\nJe suis : "+monIpAdress+":"+monPort+" ("+monAet+")\nEt je veux parler à : "+serverIpAdress+":"+serverPort+" ("+serverAet+")\n\nImpossible de récupérer toutes les séries: "+add);
         return false;
      }
   progressDialog.setValue(99);

      // Release association
      //scu.closeAssociation(DCMSCU_RELEASE_ASSOCIATION); 
      QMessageBox::warning(0,"Recuperation depuis noeud DICOM","FIN D'UNE RECUPERATION");
   progressDialog.setValue(100);
   //*/
      //Fin de l'importation d'UN examen
   }
   //Fin de l'importation de tous les examens demandés
   return true;
}


My question is simple yet how to retrieve images from PACS (for examens that I ask). 
How STORESCP work? Do I need an object of type STORSCP??

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed, 2011-11-23, 15:55 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Mitmal wrote:
I do not understand what you want me to learn.

My question is simple yet how to retrieve images from PACS (for examens that I ask).


Ah, I can answer that question :-) As I wrote: 

Quote:
Please look into the standard (part 4 on Q/R, maybe also part 7 on C-MOVE) in order to fully understand how this works. Also, I explained it several times in the forum, you may search for it. 


Quote:
How STORESCP work?


Google knows better (first match!) and more comprehensive than I can write in the forum.
Quote:
Do I need an object of type STORSCP??


As I said, in case of C-MOVE, the PACS will open a separate connection to send files. You have to listen for that connection. One way to do this is to start the tool storescp, which is part of DCMTK. 

Best regards, 
Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-11-24, 10:17 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
ok, I understand better now. 
So by running STORESCP, a console appears and I have to keep it open. I get the images directly in the directory where STORESCP.exe runs. Thing I do not want. 

So I wonder if it is possible to start the listening port (STORESCP) directly from my program and if I can specify the destination folder as well?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-11-24, 10:39 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

not with DcmSCU, or, not without extending the code in a derived class. You could start another process or thread that uses DcmSCP to listen for images. 

Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-11-24, 19:01 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I can not implement the class STORESCP.cc in my program, can you tell me how to do?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-11-24, 20:22 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
For now my only solution is to use a command. My code is: 
Code:
QString commande = "storescp.exe --aetitle \""+monAet+"\" -od \""+"C:/Users/ARNGDC2/Desktop/Recuperation"+"\" "+monPort;
   system(commande);



But that's not really nice, especially to the firewire confirmation which is requested each time. 
In addition I should run the command in another thread because it froze my whole application, you know how you do that?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-11-25, 10:31 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

In order to implement it yourself, look at the DcmSCP class (dcmnet/libsrc/scp.cc), derive from it, and overwrite the function handleIncomingCommand() to handle also C-STORE (msg->CommandField == DIMSE_C_STORE_RQ) and then do something with the incoming dataset. 

Michael


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous: All posts 1 day 7 days 2 weeks 1 month 3 months 6 months 1 year Sort by Author Post time Subject Ascending Descending 
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page Previous  12345  Next

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: qimo601 and 1 guest


You can post new topics in this forum
You can reply to topics in this forum
You can edit your posts in this forum
You can delete your posts in this forum

Search for:  
Jump to:   Select a forum  ------------------  General     Announcements     Imprint / Impressum     Off-topic  DCMTK     DCMTK - FAQ     DCMTK - Installation     DCMTK - General     Third-Party DCMTK Applications  DICOMscope     DICOMscope - Installation     DICOMscope - General     IHE MESA CPI Test Suite  Other Tools     DCMPRINT     DCMCHECK     DCMJP2K     DCMRT     Other DICOM Tools  DRG CD-Test (in German language)     Allgemeine Diskussion / General Discussion     Anforderungskatalog / CD Specification     Leitfaden für Patienten-CDs / Guidelines for Handling Patient CDs     CD-Prüfung / CD Validation     
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

DICOM @ OFFIS

Discussion Forum for OFFIS DICOM Tools - For registration, send email with desired username to the OFFIS DICOM team
Last visit was: Thu, 2012-09-13, 03:27 It is currently Thu, 2012-09-13, 09:16

All times are UTC + 1 hour [ DST ]




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page Previous  12345  Next
Author Message
 Post subject:
PostPosted: Fri, 2011-11-25, 10:56 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Ahhh yes, it's a very good way which I will follow, thank you

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-11-25, 14:33 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Perfect, it's even wrote: 
Code:
This function is most likely to be implemented by a derived class implementing a specific SCP behaviour

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-11-25, 15:03 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Yes, I know, I wrote it :-)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-11-25, 15:30 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Arf, I am lost, I created a class inheriting: 
Code:
#ifndef SCPPERSO_H
#define SCPPERSO_H
#include "scp.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/config/osconfig.h"

class ScpPerso : public DcmSCP
{
/*
   ScpPerso();
   ~ScpPerso();
*/
   OFCondition handleIncomingCommand(T_DIMSE_Message *incomingMsg, const DcmPresentationContextInfo &presContextInfo);
}
#endif // SCPPERSO_H


But I'm a little lost in how to change the function:
Code:
#include "scpPerso.h"

/*
ScpPerso::ScpPerso() 
{
}

ScpPerso::~DcmSCP()
{
}
*/

OFCondition ScpPerso::handleIncomingCommand(T_DIMSE_Message *msg, const DcmPresentationContextInfo &info)
{
   OFCondition cond;
   if( msg->CommandField == DIMSE_C_ECHO_RQ )
   {
      cond = handleECHORequest( msg->msg.CEchoRQ, info.presentationContextID );
   } 
   else 
   {
      OFString tempStr;
      DCMNET_ERROR("Cannot handle this kind of DIMSE command (0x"   << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4)   << OFstatic_cast(unsigned int, msg->CommandField) << ")");
      DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, *msg, DIMSE_INCOMING));
      cond = DIMSE_BADCOMMANDTYPE;
   }
   return cond;
}


Can I get help?
I would give the AET, the port of destination and the path of the images to the server.
Like to execute the command: storescp.exe --aetitle "AETxxx" -od "pathxxx" PORTxxx

What about the idea:
Code:
DcmSCP *storescp = new DcmSCP();
   OFString OFaet = aet;            storescp->setAETitle(OFaet);
   UINT16 Uint16port = port.toInt();   storescp->setPort(Uint16port);

With a command to simulate the path and another to start the server? 
Is it not possible?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-11-25, 20:38 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I am not progressing with the class ScpPerso, I do not see at all what to do. 
In what should I change? 

I do not understand the link between class and scp.cc storescp, can still help me??

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 09:34 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

They are not interrelated but can implement the same functionality, i.e. a DICOM storage service. 

Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 10:38 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Can you help me with an example please??

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 11:32 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

sorry, no...you really have to understand DICOM first, then the usage of the classes is really 99% self-explanatory. Don't get me wrong, I like to help you but I cannot understand the topic for you or write the code. 

Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 11:42 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
I understand, only I do not know where to look to understand. 
Do you have a link for me?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 11:46 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Michael Onken wrote:
Hi,

They are not interrelated but can implement the same functionality, i.e. a DICOM storage service.

Michael


Ok, but how? There is no start or hand function, then start the server? 
I look in the class STORESCP.cc, I wanted to take the code for the main function, but it does not work. Is it a good idea?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 15:43 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
My solution is as follows (it does not work). 
ScpPerso.h a file: 
Code:
#ifndef SCPPERSO_H
#define SCPPERSO_H
#include <QtGui>
#include "scp.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/ofstdinc.h"

class ScpPerso : public DcmSCP
{
public :
   /** Permet de manipuler un ensemble de commandes entrantes et de réagir en conséquence, par exemple \ réponse envoi via DIMSE_sendXXXResponse (). 
   Le gestionnaire de la norme ne connaît que la façon de traiter une demande d'écho en appelant handleEchoRequest (). 
   (Cette fonction est plus susceptible d'être mis en œuvre par une Classe dérivée mise en œuvre d'un comportement spécifique SCP.)
   */
   OFCondition handleIncomingCommand(T_DIMSE_Message *incomingMsg, const DcmPresentationContextInfo &presContextInfo);
   int startSTORESCP(int argc, char *argv[]);
};
#endif // SCPPERSO_H


And the ScpPerso.cc (with handleIncomingCommand + start methode found in storescp.cc ):
Code:
#include "scpPerso.h"

OFCondition ScpPerso::handleIncomingCommand(T_DIMSE_Message *msg, const DcmPresentationContextInfo &info) {...}
///////////////////////////////////////////////////////////////////////
int ScpPerso::startSTORESCP(int argc, char *argv[]) {...}


Finally, the method is called in my program using the function:
Code:
bool MedicTool2::initServiceStore(QString port, QString aet, QString path)
{
   //DcmSCP *storescp = new DcmSCP();
   //OFString OFaet = aet;            storescp->setAETitle(OFaet);
   //Uint16 Uint16port = port.toInt();   storescp->setPort(Uint16port);
   ScpPerso *scpP = new ScpPerso();
   path.replace("\\","/");
   //La commande doit etre du type : storescp.exe --aetitle "NEUROGDC2" -od "C:\Users\ARNGDC2\Desktop\Recuperation" 104
   int nbr = 3;
   char **commande = new char*[3];
   
   char commande1[256]; sprintf(commande1,"%s%s%s","--aetitle \"",aet,"\"");
   commande[0] = commande1;
   
   char commande2[256]; sprintf(commande2,"%s%s%s","-od \"",path,"\"");
   commande[1] = commande2;

   char* sport = new char[port.size() + 1]; strcpy(sport, port.toStdString().c_str());// pour le caractère de fin de chaine '\0'
   commande[2] = sport;

   scpP->startSTORESCP(nbr, commande);
   return true;
}


But the execution does not work.
The error is on line (In the start function) :
Code:
prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);


What do you think about my idea ??

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 17:28 
Offline

Joined: Mon, 2010-06-14, 17:41
Posts: 44
Read the 2nd and the 3rd post 

http://forum.dcmtk.org/viewtopic.php?t=3043&highlight=receivedimsedataset 

remove the DIMSE_storeProvider 'part' (and below) but 
leave the lines between bzero and DIMSE_store... 
for the sendSTOREResponse (which line you have to insert for 
sending the positve or negative response). 

Frank


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 18:19 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Great, but now I look how I should call the function: handleIncomingCommand. 
How do I retrieve parameters T_DIMSE_Message * incomingMsg and const DcmPresentationContextInfo & presContextInfo?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 18:31 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Is it just with scpP->listen(); ???

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 18:47 
Offline

Joined: Mon, 2010-06-14, 17:41
Posts: 44
Yes, with scp->listen you start the service. 

Quote:
How do I retrieve parameters T_DIMSE_Message * incomingMsg and 
const DcmPresentationContextInfo & presContextInfo?

Well i am using the storescp.cfg from the etc directory so in configure there which sop class and transfer syntax i want to accept. 

Frank


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous: All posts 1 day 7 days 2 weeks 1 month 3 months 6 months 1 year Sort by Author Post time Subject Ascending Descending 
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page Previous  12345  Next

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: qimo601 and 1 guest


You can post new topics in this forum
You can reply to topics in this forum
You can edit your posts in this forum
You can delete your posts in this forum

Search for:  
Jump to:   Select a forum  ------------------  General     Announcements     Imprint / Impressum     Off-topic  DCMTK     DCMTK - FAQ     DCMTK - Installation     DCMTK - General     Third-Party DCMTK Applications  DICOMscope     DICOMscope - Installation     DICOMscope - General     IHE MESA CPI Test Suite  Other Tools     DCMPRINT     DCMCHECK     DCMJP2K     DCMRT     Other DICOM Tools  DRG CD-Test (in German language)     Allgemeine Diskussion / General Discussion     Anforderungskatalog / CD Specification     Leitfaden für Patienten-CDs / Guidelines for Handling Patient CDs     CD-Prüfung / CD Validation     
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

DICOM @ OFFIS

Discussion Forum for OFFIS DICOM Tools - For registration, send email with desired username to the OFFIS DICOM team
Last visit was: Thu, 2012-09-13, 03:27 It is currently Thu, 2012-09-13, 09:16

All times are UTC + 1 hour [ DST ]




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 65 posts ]  Go to page Previous  12345
Author Message
 Post subject:
PostPosted: Mon, 2011-11-28, 19:00 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
my mistake, just with scp-> listen the service starts fine. 
Now it only remains for me to find how to change the destination address of the images. 
(And optionally, how to change the file names)

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 19:54 
Offline

Joined: Mon, 2010-06-14, 17:41
Posts: 44
Quote:
how to change the file names


with 
Code:
if (receiveDIMSEDataset(&presID, &dataObject,NULL,NULL).good())
{..
// receive and responding code here ....
if (dataObject->findAndGetOFString(DCM_SOPInstanceUID, dateiname,0, true).good())
                    qDebug() << "SOP IUID: "<< filename.c_str();
else {// some else code here otherwise you'll overwrite a file}
// save to file
dcmdataset->save(filename.c_str()); 
}

you get a dcmdataset and you can save it with 
dcmdataset->save(filename.c_str()); where filename is a OFString


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-11-28, 20:34 
Offline

Joined: Mon, 2011-04-18, 20:36
Posts: 112
Location: France
Fine, but I do not know where to put this code?

_________________
Respectueusement, 
MitMal
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject: Your storescp here!
PostPosted: Mon, 2011-11-28, 21:46 
Offline

Joined: Mon, 2010-06-14, 17:41
Posts: 44
For all who don't know c++ and don't understand a bit of the dcmtk and 
posts above and where unable to read the linked posts: 

This is the code for receiving C-StoreRequests, saving files and sending the C-StoreResponse: 

// DICOMEMPFANGEN.H 
Code:
#ifndef DICOMEMPFANGEN_H
#define DICOMEMPFANGEN_H


#include <dcmtk/dcmimage/diregist.h>      /* include to support color images */
#include "dcmtk/dcmjpeg/djdecode.h" /* for jpeg decoder */
#include "dcmtk/dcmdata/dcrledrg.h"
#include <dcmtk/ofstd/ofstring.h>
#include <dcmtk/ofstd/ofconsol.h>
#include <dcmtk/dcmdata/dcdeftag.h>
#include <dcmtk/dcmdata/dcfilefo.h>
#include <dcmtk/dcmimgle/dcmimage.h>
#include "dcmtk/dcmdata/dctk.h"
#include "dcmtk/dcmdata/dcistrmf.h"
#include "dcmtk/dcmnet/dimse.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/scp.h"

class DicomEmpfangen : public DcmSCP
{
public:
    DicomEmpfangen();



    /* ***********************************************************************
     *  Functions particularly interesting for overwriting in derived classes
     * ***********************************************************************
     */

    /** Handle incoming command set and react accordingly, e.g.\ sending response via
     *  DIMSE_sendXXXResponse(). The standard handler only knows how to handle an Echo request
     *  by calling handleEchoRequest(). This function is most likely to be implemented by a
     *  derived class implementing a specific SCP behaviour.
     *  @param TODO
     *  @return TODO
     */
    OFCondition handleIncomingCommand(T_DIMSE_Message *incomingMsg,
                                              const DcmPresentationContextInfo &presContextInfo);

private:
    OFString pname;
    OFString dateiname;
};

#endif // DICOMEMPFANGEN_H



// DICOMEMPFANGEN.CPP - CPP file:
Code:
#include "dicomempfangen.h"
#include <QDebug>
#include <QTime>

DicomEmpfangen::DicomEmpfangen()
{
}


OFCondition DicomEmpfangen::handleIncomingCommand(T_DIMSE_Message *msg,
                                          const DcmPresentationContextInfo &info)
{
    OFCondition cond;
    switch(msg->CommandField)
    {
    case DIMSE_C_ECHO_RQ :{
        // Process C-ECHO request
        cond = handleECHORequest( msg->msg.CEchoRQ, info.presentationContextID );
        break;
    }// ende DIMSE_C_ECHO_RQ

    case DIMSE_C_STORE_RQ:{

        qDebug() << "data/files to save ... !!! :-)";

        T_DIMSE_C_StoreRSP response;
        T_DIMSE_C_StoreRQ request = msg->msg.CStoreRQ;
        DcmDataset *statusDetail = NULL;

        T_ASC_PresentationContextID presID = info.presentationContextID;
        DcmDataset *dataObject = new DcmDataset();

        if (receiveDIMSEDataset(&presID, &dataObject,NULL,NULL).good())
        {
            if (dataObject != NULL)
            {
                qDebug() << "Daten empfangen: " << QTime::currentTime();
                dateiname.clear();
                if (dataObject->findAndGetOFString(DCM_SOPInstanceUID, dateiname,0, true).good())
                    qDebug() << "SOP IUID: "<< dateiname.c_str();

                dataObject->saveFile(dateiname.c_str());

                bzero((char*)&response, sizeof(response));
                response.DimseStatus = STATUS_Success;  /* assume */
                response.MessageIDBeingRespondedTo = request.MessageID;
                response.DataSetType = DIMSE_DATASET_NULL;  /* always for C-STORE-RSP */
                strcpy(response.AffectedSOPClassUID, request.AffectedSOPClassUID);
                strcpy(response.AffectedSOPInstanceUID, request.AffectedSOPInstanceUID);
                response.opts = (O_STORE_AFFECTEDSOPCLASSUID | O_STORE_AFFECTEDSOPINSTANCEUID);
                if (request.opts & O_STORE_RQ_BLANK_PADDING) response.opts |= O_STORE_RSP_BLANK_PADDING;
                if (dcmPeerRequiresExactUIDCopy.get()) response.opts |= O_STORE_PEER_REQUIRES_EXACT_UID_COPY;

                OFCondition cond = sendSTOREResponse(presID, request, response, statusDetail);
                if( cond.bad() ) DCMNET_INFO("Cannot send C-Store Response: " );
                else DCMNET_INFO("C-STORE Response successfully sent");

            }
            else qDebug() << "no data received";
        }
        else qDebug() << "no dcmdataset.";
        break;
    }
    default:{
        // We cannot handle this kind of message. Note that the condition will be returned
        // and that the caller is responsible to end the association if desired.
        OFString tempStr;
        DCMNET_ERROR("Cannot handle this kind of DIMSE command (0x"
          << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4)
                     << OFstatic_cast(unsigned int, msg->CommandField) << ")");
        DCMNET_DEBUG(DIMSE_dumpMessage(tempStr, *msg, DIMSE_INCOMING));
        cond = DIMSE_BADCOMMANDTYPE;
    }// Ende default
    }// Ende case
  return cond;
}


Then you need a main function
where you did the following:
Code:
int main(int argc, char *argv[])
{

    //scp = new DcmSCP();
    DicomEmpfangen *scp; // put this in a headerfile if you use a class and not a main!
    scp = new DicomEmpfangen();
    scp->setPort(104);
    scp->setAETitle("CHANGEAETITLE"); 
    //scp->loadAssociationCfgFile("storescp.cfg");

    if (scp->loadAssociationCfgFile("storescp.cfg").good())
    {
        qDebug() << "SCP-Config-File gefunden :-)";
        qDebug() << "dime-timeout: " << scp->getDIMSETimeout();
        if (scp->setAndCheckAssociationProfile("Default").good())
        {
            qDebug() << "listen gestartet um: "<< QTime::currentTime();
            //scp->setDIMSETimeout(ULONG_MAX);
            if (scp->getDIMSEBlockingMode() == DIMSE_NONBLOCKING )
            {
                qDebug() << "scp is in non-blocking mode: ";
                scp->setConnnectionTimeout(ULONG_MAX);
                scp->setDIMSEBlockingMode(DIMSE_BLOCKING);
                if (scp->getDIMSEBlockingMode() == DIMSE_BLOCKING )
                    qDebug() << "2nd try: scp is in blocking mode: ";
                else qDebug() << "scp is still in non-blocking mode: ";
            }
            else {
                qDebug() << "scp is in blocking mode: ";
            }

            if (scp->listen().bad())
            {
                qDebug() << "error during listening!";
            }
            qDebug() << "listen stops at: " << QTime::currentTime();
        }
    }
    else
        qDebug() << "SCP-Config file not found :-(";
}



Now you have all for a storescp - please close this thread. 
For the german comments - use google translator. 

Be patient to this thread if you use the code above: 
http://forum.dcmtk.org/viewtopic.php?t=3234 

btw: I am using the switch case not if () else because there are more 
than two T_DIMSE_Command's and you want only handle echo and receive requests - other should be implemented later or give an error. 

btw2: you should have the storescp.cfg from the dcmtk/etc/ directory and 
i had to comment out line 96. 
#PresentationContext28 = OphthalmicThicknessMapStorage\AnyTransferSyntax 

Well i know there are memory leaks - so fix them or post a better code here. 



Frank


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue, 2011-11-29, 11:14 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Thanks Frank :)


Report this post
Top
 Profile  
Reply with quote  

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics