Question

I've got following problem. I have to write small application that connects to pacs and gets images. I decided to use dcm4che toolkit. I've written following code: public class Dcm4 {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    // TODO code application logic here
    DcmQR dcmqr = new MyDcmQR("server");

    dcmqr.setCalledAET("server", true);
    dcmqr.setRemoteHost("213.165.94.158");
    dcmqr.setRemotePort(104);
    dcmqr.getKeys();

    dcmqr.setDateTimeMatching(true);
    dcmqr.setCFind(true);
    dcmqr.setCGet(true);

    dcmqr.setQueryLevel(MyDcmQR.QueryRetrieveLevel.IMAGE);

    dcmqr.addMatchingKey(Tag.toTagPath("PatientID"),"2011");
    dcmqr.addMatchingKey(Tag.toTagPath("StudyInstanceUID"),"1.2.276.0.7230010.3.1.2.669896852.2528.1325171276.917");
    dcmqr.addMatchingKey(Tag.toTagPath("SeriesInstanceUID"),"1.2.276.0.7230010.3.1.3.669896852.2528.1325171276.916");


    dcmqr.configureTransferCapability(true);
    List<DicomObject> result=null;
    byte[] imgTab=null;
    BufferedImage bImage=null;
    try {
        dcmqr.start();
        System.out.println("started");
        dcmqr.open();
        System.out.println("opened");
        result = dcmqr.query();
        System.out.println("queried");
        dcmqr.get(result);
        System.out.println("List Size = " + result.size());

        for(DicomObject dco:result){
            System.out.println(dco);
            dcmTools.toByteArray(dco);
            System.out.println("end parsing");
        }

    } catch (Exception e) {
        System.out.println("error "+e);
    }

    try{
        dcmqr.stop();
        dcmqr.close();
    }catch (Exception e) {

    }

    System.out.println("done");
}
}

Everything seems to be fine until I call dcmTools.toByteArray(dco). Output till calliing toByteArray() looks like this:

List Size = 1
(0008,0052) CS #6 [IMAGE] Query/Retrieve Level
(0008,0054) AE #6 [server] Retrieve AE Title
(0020,000E) UI #54 [1.2.276.0.7230010.3.1.3.669896852.2528.1325171276.916] Series Instance UID

Source of ToByteArray:

public static byte[] toByteArray(DicomObject obj) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    BufferedOutputStream bos = new BufferedOutputStream(baos);
    DicomOutputStream dos = new DicomOutputStream(bos);
    dos.writeDicomFile(obj);
    dos.close();
    byte[] data = baos.toByteArray();
    return data;
}

After calling toByteArray I got output:

error java.lang.IllegalArgumentException: Missing (0002,0010) Transfer Syntax UID

I,ve found some informations in other forums and it seems like DcmQR.get() method doesn't send imgage data. Is it possible to force DcmQR to do it. I've written that problem is in or with DcmQR.createStorageService() method but I haven't found the solution. Please help me!!!

Hello cneller!

I've made some changes you suggested: I've add setMoveDest and setStoreDestination and DicomObject are stored in destination I've added - it looks great. Then I've tried to write response handler based on FutureDimseRSP which is used in Association.cget method:

public class MyDimseRSP extends DimseRSPHandler implements DimseRSP{

private MyEntry entry = new MyEntry(null, null);

private boolean finished;
private int autoCancel;
private IOException ex;

@Override
public synchronized void onDimseRSP(Association as, DicomObject cmd,
                                    DicomObject data) {
    super.onDimseRSP(as, cmd, data);
    MyEntry last = entry;
    while (last.next != null)
        last = last.next;

    last.next = new MyEntry(cmd, data);
    if (CommandUtils.isPending(cmd)) {
        if (autoCancel > 0 && --autoCancel == 0)
            try {
                super.cancel(as);
            } catch (IOException e) {
                ex = e;
            }
    } else {
        finished = true;
    }
    notifyAll();
}

@Override
public synchronized void onClosed(Association as) {
    if (!finished) {
//            ex = as.getException();
        ex = null;
        if (ex == null) {
            ex = new IOException("Association to " + as.getRemoteAET()
                    + " closed before receive of outstanding DIMSE RSP");
        }
        notifyAll();
    }
}

public final void setAutoCancel(int autoCancel) {
    this.autoCancel = autoCancel;
}

@Override
public void cancel(Association a) throws IOException {
    if (ex != null)
        throw ex;
    if (!finished)
        super.cancel(a);
}

public DicomObject getDataset() {
    return entry.command;
}

public DicomObject getCommand() {
    return entry.dataset;
}

public MyEntry getEntry() {
    return entry;
}

public synchronized boolean next() throws IOException, InterruptedException {
    if (entry.next == null) {
        if (finished)
            return false;

        while (entry.next == null && ex == null)
            wait();

        if (ex != null)
            throw ex;
    }
    entry = entry.next;
    return true;
}
}

Here is MyEntry code:

public class MyEntry {

final DicomObject command;
final DicomObject dataset;
MyEntry next;

public MyEntry(DicomObject command, DicomObject dataset) {
    this.command = command;
    this.dataset = dataset;
}

public DicomObject getCommand() {
    return command;
}

public DicomObject getDataset() {
    return dataset;
}

public MyEntry getNext() {
    return next;
}

public void setNext(MyEntry next) {
    this.next = next;
}
}

Then I've retyped get method from Dmcqr as follows:

public void getObject(DicomObject obj, DimseRSPHandler rspHandler)throws IOException, InterruptedException{
    TransferCapability tc = selectTransferCapability(qrlevel.getGetClassUids());
    MyDimseRSP myRsp=new MyDimseRSP();
    if (tc == null)
        throw new NoPresentationContextException(UIDDictionary
                .getDictionary().prompt(qrlevel.getGetClassUids()[0])
                + " not supported by " + remoteAE.getAETitle());
    String cuid = tc.getSopClass();
    String tsuid = selectTransferSyntax(tc);
    DicomObject key = obj.subSet(MOVE_KEYS);
    assoc.cget(cuid, priority, key, tsuid, rspHandler);
    assoc.waitForDimseRSP();
}

In second argument in this method I've used an instance of my response handler (MyDimseRSP). And I run my code I got null value of command and dataset of my response handler. In "next" variable only "command" is not null, and od course it's not DicomObject which I need. What I'm doing wrong!!!!

Was it helpful?

Solution

You're going to have to step through the code a bit (including the DCM4CHE toolkit code). I suspect you are using the default response handler, which just counts the number of completed operations, and doesn't actually store the image data from the get command.

Clearly, your for loop, below, is looping over the results of the find operation, not the get (which needs to be handled in the response handler).

for(DicomObject dco:result)

I expect you will have to override the response handler to write your DICOM files appropriately. See also the DcmRcv class for writing DICOM files from the DicomObject you'll receive.

:

From your edits above, I assume you are just trying to get the raw DICOM instance data (not the command that stored it). What about a response handler roughly like:

List<DicomObject> dataList = new ArrayList<DicomObject>();

@Override
public void onDimseRSP(Association as, DicomObject cmd, DicomObject data) {
    if( shouldAdd(as, cmd) ) {
        dataList.add( data )
    }
}

Watch out for large lists, but it should get you the data in memory.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top