connect to PACS system biginner question

All other questions regarding DCMTK

Moderator: Moderator Team

Message
Author
Michael Onken
DCMTK Developer
Posts: 2049
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#16 Post by Michael Onken »

You should read about that in part 3 of the DICOM standard to find out which DICOM attributes (tags) you really need. The ones you quoted do not exist directly.

So read about the Image Pixel Module, especially look for the attributes Bts Allocated, Stored, and High Bit. Start with the module description in section C.7.6.3. Bits Allocated is how many bits do you have reserved for one pixel component, Bits Stored is how many bits you actually use from those, and High Bit says in which bit from Bits Allocated you start from, i.e. how the Bits Stored are aligned within Bits Allocated. The number of components per pixel is in the attribute Samples per Pixel.

If you look into the dcmdata example i have directed you to, just exchange DCM_PatientData with the attributes you are interested in and use a number access method, e.g. (according to the example)

Code: Select all

Uint16 bitsAlloc = 0;
fileformat.getDataset()->findAndGetUint16(DCM_BitsAllocated, bitsAlloc);
// now bitsAlloc contains the content of attribute Bits Allocated
For some examples and figures of various Bits allocated/stored/high bit settings, look into part, read Annex D, especially look at the nice little images in D.2

Best regards,
Michael

moon198831
Posts: 14
Joined: Wed, 2011-03-16, 14:30

#17 Post by moon198831 »

hi Micheal, I'm also a beginner of dicom. can i have your email or google talk. I have some questions need your help. i am using xcode to make an application to retrieve pacs server data. but I'm really stuck here. your help will be best appreciated.

Michael Onken
DCMTK Developer
Posts: 2049
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#18 Post by Michael Onken »

Hi,

no sorry I cannot provide you with private help since I have work to do. Any questions about DCMTK can be asked in the forum and will also help other people having similar problems. If you have serious problems to be solved and you need commercial support, you may send us an email to dicom at offis de.

Best regards,
Michael

moon198831
Posts: 14
Joined: Wed, 2011-03-16, 14:30

#19 Post by moon198831 »

hi micheal
I only have some small problems, and i just want the answers instantly, since my project open day is this Thursday. So if you can help me, I will appreciate it very much. It won't cost long time of you...

now i get a problem. I wanna make a button linked to pacs server.
SCU = new DcmSCU (this);

if (SCU != NULL)
{
SCU ->setPeerAETitle(PeerAETitle);
SCU ->setPeerHostName(PeerHostName);
SCU ->setPeerPort(PeerPortNumber);
SCU ->addPresentationContexts(PreferredOutgoingSyntax);
status = SCU ->initNetwork();
status=SCU->negotiateAssociation();
SCU->findPresentationContext(..,..)
//Send Request
...
...

//Close Association
SCU->closeAssociation();
}
Is this code working?
Another question, how to request to pacs server then?
I hope you can reply asap, thanks a million!

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

#20 Post by Mitmal »

Aww the moon198831 answer should be intersting for me too !!
I want to create the same button but this code doesn't work...

So I try with this code, from ctkDICOMDemoSCUMain.cpp :

Code: Select all

int Import::connection(QString qipAdress, QString qport, QString qaet){
  DcmSCU scu;
  OFString host(qipAdress.toAscii());
  scu.setPeerHostName(host);
  unsigned int port = atoi(qport.toAscii());
  scu.setPeerPort(port);
  OFString verificationSOP = UID_VerificationSOPClass;
  OFList<OFString> ts;
  ts.push_back(UID_LittleEndianExplicitTransferSyntax);
  ts.push_back(UID_BigEndianExplicitTransferSyntax);
  ts.push_back(UID_LittleEndianImplicitTransferSyntax);
  scu.addPresentationContext(verificationSOP, ts);
  OFString peerAET = qaet.toAscii();
  if (peerAET != "")
  {
    scu.setPeerAETitle(peerAET);
  }
  OFCondition result = scu.initNetwork();
  if (result.bad())
  {
    std::cerr << "Error setting up SCU: " << result.text() << "\n";
    return 2;
  }
  
  // Negotiate association
  result = scu.negotiateAssociation();
  if (result.bad())
  {
    std::cerr << "Error negotiating association: " << result.text() << "\n";
    return 2;
  }
  
  // Issue ECHO request and let scu find presentation context itself (0)
  result = scu.sendECHORequest(0);
  if (result.bad())
  {
    std::cerr << "Error issuing ECHO request or received rejecting response: " << result.text() << "\n";
    return 2;
  }
  std::cout << "Successfully sent DICOM Echo to host " << host << " on port " << port << "\n";
  return 0;
}
with this import :
  • #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
    #include "dcmtk/dcmnet/scu.h"
    #include "Import.h"
    #include "dcmtk\dcmnet\assoc.h"
    #include "dcmtk\dcmnet\dimse.h"

    #include <cstdlib>
    #include <iostream>
    #include <fstream>
But there is a error message appeared :
Erreur 1 error LNK2019: symbole externe non résolu "public: virtual __thiscall DcmSCU::~DcmSCU(void)" (??1DcmSCU@@UAE@XZ) référencé dans la fonction "public: static int __cdecl Import::connection(class QString,class QString,class QString)" (?connection@Import@@SAHVQString@@00@Z) C:\Users\Nicolas\Documents\Visual Studio 2010\Projects\Importation\Importation\Import.obj Importation
Respectueusement,
MitMal

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

#21 Post by Mitmal »

No idea ???
Respectueusement,
MitMal

Michael Onken
DCMTK Developer
Posts: 2049
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#22 Post by Michael Onken »

Moon: Looking at your code:

- why are you using the copy constructor? It is defined private in DcmSCU, i.e. shall/can not be used. Just say "SCU = new DcmSCU()";
- For adding the presentation context: A presentation context always contains a SOP class and one or more transfer syntaxes. Thus you could do the following (Verification Service with all 3 uncompressed transfer syntaxes):

Code: Select all

OFList<OFString> ts; 
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
  SCU.addPresentationContext(UID_VerificationSOPClass, ts);
The rest looks OK without testing it (but hey, just try it!).


------------8<-------------------8<------------------

Mitmal: DcmSCU actually has a virtual destructor which is also public (implementation does some memory cleanups).

Code: Select all

virtual ~DcmSCU();
Are you sure you actually link your binary with the dcmnet library?

Michael

anjumsk29
Posts: 28
Joined: Tue, 2011-05-17, 14:34

#23 Post by anjumsk29 »

Please give me code snippet to retrieve image from Pacs server using DcmSCU class.

Quick reply would be helpful.

Thanks in advance.

Forward
Posts: 17
Joined: Mon, 2011-05-02, 11:54

#24 Post by Forward »

Try to use DIMSE_moveUser

if you can use findrequest you have all info to use moveUser to retrieve imae from PACS

Michael Onken
DCMTK Developer
Posts: 2049
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#25 Post by Michael Onken »

Hi,

here is code that uses DcmSCU and does the following:

Negotiating Verification (echo), as well as FIND (query) and MOVE (retrieve) SOP Classes with the PACS. Then, send ECHO, send FIND and retrieve all studies that were found within the FIND step by sending a MOVE for each study. Then, release the association.

Best regards,
Michael

Code: Select all

/*
 *
 *  Copyright (C) 2011, OFFIS e.V.
 *  All rights reserved.  See COPYRIGHT file for details.
 *
 *  This software and supporting documentation were developed by
 *
 *    OFFIS e.V.
 *    R&D Division Health
 *    Escherweg 2
 *    D-26121 Oldenburg, Germany
 *
 *
 *  Module:  dcmnet
 *
 *  Author:  Michael Onken
 *
 *  Purpose: Test for move feature of the DcmSCU class
 *
 *  Last Update:      $Author: joergr $
 *  Update Date:      $Date: 2011-03-17 09:46:02 $
 *  CVS/RCS Revision: $Revision: 1.54 $
 *  Status:           $State: Exp $
 *
 *  CVS/RCS Log at end of file
 *
 */

#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
#include "dcmtk/dcmnet/testscu.h"
#include "dcmtk/dcmnet/diutil.h"


#define OFFIS_CONSOLE_APPLICATION "testscu"

static OFLogger echoscuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);

static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
  OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";

// our application entity title used for calling the peer machine
#define APPLICATIONTITLE     "TEST-SCU"

// host name of the peer machine
#define PEERHOSTNAME         "www.dicomserver.co.uk"

// TCP/IP port to connect to on peer machine
#define PEERPORT 11112

// application entity title of the peer machine
#define PEERAPPLICATIONTITLE "MOVESCP"

// MOVE target AE Title
#define MOVEAPPLICATIONTITLE "TEST-SCU"

static Uint8 findUncompressedPC(const OFString& sopClass,
                                DcmSCU& scu)
{
  Uint8 pc;
  pc = scu.findPresentationContextID(sopClass, UID_LittleEndianExplicitTransferSyntax);
  if (pc == 0)
    scu.findPresentationContextID(sopClass, UID_BigEndianExplicitTransferSyntax);
  if (pc == 0)
    scu.findPresentationContextID(sopClass, UID_LittleEndianImplicitTransferSyntax);
  return pc;
}

// ********************************************

int main(int argc, char *argv[])
{
  /* Setup DICOM connection parameters */
  OFLog::configure(OFLogger::DEBUG_LOG_LEVEL);
  DcmTestSCU scu;
  // set AE titles
  scu.setAETitle(APPLICATIONTITLE);
  scu.setPeerHostName(PEERHOSTNAME);
  scu.setPeerPort(PEERPORT);
  scu.setPeerAETitle(PEERAPPLICATIONTITLE);
  // 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);
 
  /* Initialize network */
  OFCondition result = scu.initNetwork();
  if (result.bad())
  {
    DCMNET_ERROR("Unable to set up the network: " << result.text());
    return 1;
  }

  /* Negotiate Association */
  result = scu.negotiateAssociation();
  if (result.bad())
  {
    DCMNET_ERROR("Unable to negotiate association: " << result.text());
    return 1;
  }

  /* Let's look whether the server is listening: 
     Assemble and send C-ECHO request 
   */
  result = scu.sendECHORequest(0);
  if (result.bad())
  {
    DCMNET_ERROR("Could not process C-ECHO with the server: " << result.text());
    return 1;
  }


  /* Assemble and send C-FIND request */
  FINDResponses findResponses;
  DcmDataset req;
  req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "STUDY");
  req.putAndInsertOFStringArray(DCM_StudyInstanceUID, "");
  T_ASC_PresentationContextID presID = findUncompressedPC(UID_FINDStudyRootQueryRetrieveInformationModel, scu);
  if (presID == 0)
  {
    DCMNET_ERROR("There is no uncompressed presentation context for Study Root FIND");
    return 1;
  }
  result = scu.sendFINDRequest(presID, &req, &findResponses);
  if (result.bad())
    return 1;
  else 
    DCMNET_INFO("There are " << findResponses.numResults() << " studies available");

  /* Assemble and send C-MOVE request, for each study identified above*/
  presID = findUncompressedPC(UID_MOVEStudyRootQueryRetrieveInformationModel, scu);
  if (presID == 0)
  {
    DCMNET_ERROR("There is no uncompressed presentation context for Study Root MOVE");
    return 1;
  }
  OFListIterator(FINDResponse*) study = findResponses.begin();
  Uint32 studyCount = 1;
  OFBool failed = OFFalse;
  while (study != findResponses.end() && result.good())
  {
    // Every loop run will get all image for a specific study
    MOVEResponses moveResponses;
    // be sure we are not in the last response which does not have a dataset
    if ( (*study)->m_dataset != NULL)
    {
      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
        result = scu.sendMOVERequest(presID, MOVEAPPLICATIONTITLE, &req, &moveResponses);
        if (result.good())
        {
          DCMNET_INFO("Received study #" << std::setw(7) << studyCount << ": " << studyInstanceUID);
          studyCount++;
        }
      }
    }
    study++;
  }
  if (result.bad())
  {
    DCMNET_ERROR("Unable to retrieve all studies: " << result.text());
  }
  /* Release association */
  scu.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
  return 0;
}
P.S: The header file would be trivial:

Code: Select all

#ifndef TESTSCU_H
#define TESTSCU_H

#include "dcmtk/config/osconfig.h"  /* make sure OS specific configuration is included first */

#include "dcmtk/dcmnet/scu.h"     /* Covers most common dcmdata classes */


class DcmTestSCU : public DcmSCU
{

public:

  DcmTestSCU()  {}
  ~DcmTestSCU() {}

};
 
#endif // TESTSCU_H

manoindia2020
Posts: 28
Joined: Tue, 2011-06-28, 13:36
Location: Chennai
Contact:

Can't find the method scu.sendMOVERequest

#26 Post by manoindia2020 »

Hi,

while I m trying to call the method "sendMOVERequest" it says no such method found. Can you please help me out, what I am missing. I am having my latest dcmtk 3.6.0 version.

Thanks in advance

with regards
Manoj Kumar D
with regards
Manoj Kumar D

Michael Onken
DCMTK Developer
Posts: 2049
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#27 Post by Michael Onken »

Hi,

sendMOVERequest is only in 3.6.1, it was introduced 2011.04.28 and 3.6.1 was released 2011.02.01.

All of this information can be found in the CHANGES file. The latest public version is always accessible on the git web interface. Click on "tree" next to one of the files and then on the CHANGES file.

I recommend you to use the lastest snapshot.

MIchael

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

#28 Post by Roadrunner »

sendMOVERequest is only in 3.6.1, it was introduced 2011.04.28 and 3.6.1 was released 2011.02.01.
You should add this comment on the wiki page. It took me neraly the whole day for finding this forum thread because i used the last stable release and ask my what i did wrong with the "MOVEResponses moveResponses;" and where is it. :?

But on this way - i wanna say thank you for the example and the dcmtk code. :-)

Thank you

Michael Onken
DCMTK Developer
Posts: 2049
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#29 Post by Michael Onken »

Alright, thanks for the hint, done now.

Michael

manoindia2020
Posts: 28
Joined: Tue, 2011-06-28, 13:36
Location: Chennai
Contact:

Getting Will not wait for further C-MOVE responses

#30 Post by manoindia2020 »

Hi,
I am developing the Dicom app for iPhone. I tried DCMTestSCU with storescp but I am getting

I: Send C-MOVE Request
W: Status is 0xc001 (unknown)
W: Will not wait for further C-MOVE responses


The code snippet is this:

Code: Select all

storescp -d 11112

result = scu.sendMOVERequest(presID, "MOVESCP", &req, &moveResponses);
The "APPLICATIONTITLE" in storescp is "MOVESCP"

Please help me out I m a beginner for PACS Server.

Thanx in advance.
with regards
Manoj Kumar D

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest