Tuesday, March 17, 2009

Listing DICOM Header information with dcm4che 2

Hi All,

Some readers have asked me questions regarding how to access DICOM header information by DICOM Tag parameters. On this post I present you a quick tutorial on how to list all header information, including the Tag value, VR (value representation), Tag description, and the values of each field using the great dcm4che 2 toolkit.

(0008,0005) [CS] Specific Character Set [ISO_IR 100]
(0008,0008) [CS] Image Type [ORIGINAL]
(0008,0016) [UI] SOP Class UID [1.2.840.10008.5.1.4.1.1.2]
(0008,0020) [DA] Study Date [20040827]
(0008,0021) [DA] Series Date [20040827]
(0008,0022) [DA] Acquisition Date [20040827]
(0008,0023) [DA] Content Date [20040827]
(0008,0030) [TM] Study Time [100357.953000]
(0008,0031) [TM] Series Time [100607.062000]
(0008,0032) [TM] Acquisition Time [100622.688476]
(0008,0033) [TM] Content Time [100622.688476]
(0008,0050) [SH] Accession Number [null]
(0008,0060) [CS] Modality [CT]
(0008,0070) [LO] Manufacturer [SIEMENS]

Like the previous posts, we start coding a simple class with the default constructor. Let's name it ListDicomHeader.


public class ListDicomHeader {

public ListDicomHeader() {
// TODO Auto-generated method stub
}

public static void main(String[] args) {
// TODO Auto-generated method stub
}
}

The next step is to code the method responsible for extracting the header info. Note that this method is recursive. This is done because some DICOM files bring encoded Items that may hold other DICOM objects denoted by de value representation SQ. So, we are handling also sequence information with this code. The method is written as follows:


public void listHeader(DicomObject object) {
Iterator iter = object.datasetIterator();
while(iter.hasNext()) {
DicomElement element = iter.next();
int tag = element.tag();
try {
String tagName = object.nameOf(tag);
String tagAddr = TagUtils.toString(tag);
String tagVR = object.vrOf(tag).toString();
if (tagVR.equals("SQ")) {
if (element.hasItems()) {
System.out.println(tagAddr +" ["+ tagVR +"] "+ tagName);
listHeader(element.getDicomObject());
continue;
}
}
String tagValue = object.getString(tag);
System.out.println(tagAddr +" ["+ tagVR +"] "+ tagName +" ["+ tagValue+"]");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Looking at the code, first we get an iterator to go through our DICOM dataset. Then we code a while loop to get each DICOM element present in the header. At each iteration a new DicomElement is kept so we can access its values. The tag variable holds the current Tag value. From then on there are some useful functions that may help us a lot. We can use the nameOf method from DicomObject class to get the Tag description as a String. I also suggest you to have a look at the TagUtils class for other great functions. The vrOf function will return the value representation to the current element.

Then comes the recursive part. We test the VR to see if it's a sequence (SQ), if so then we check if this element has any Items. Then if the answer is true we get the new object and call the listHeader function again, starting the recursive loop. Each iteration then prints out the desired information.

Finally, to test this program we must a main method for this class. The method may be written as follows:


public static void main(String[] args) {
DicomObject object = null;
try {
DicomInputStream dis = new DicomInputStream(new File("c:/image.dcm"));
object = dis.readDicomObject();
dis.close();
} catch (Exception e) {
System.out.println(e.getMessage());
System.exit(0);
}
ListDicomHeader list = new ListDicomHeader();
list.listHeader(object);
}


That's it! Now we have a lot of information from our DICOM file header! Enjoy :)

Best regards,

Samuel.

19 comments:

rodrigo said...

Este listing DICOM Header eu consigo pegar informação como operador, hora, data, etc... em tempo de impressão e guardar em uma base de dados

Unknown said...

Oi Rodrigo,

Obrigado por visitar meu blog!

Respondendo à sua questão, uma vez com os dados do cabeçalho Dicom em mãos você pode grava-los em qualquer base de dados desde que também desenvolva um programa para esse fim.

Abraços,

Samuel.

Vagner said...

Primeiramente parabéns pelo seu blog.

Queria saber se tem alguma maneira de buscar esse Header na hora de um DICON print, ou seja, quando for imprimir, eu consigo de alguma forma buscar essas informações??

Tom said...

Hello Samucs,
I would like to ask you, if there is an easy way how to detect if an file is DICOM file?
For example I have 10 files with no suffix .dcm and I want to just detect if the format is DICOM.
Thanks you and good luck.
Tom,Czech rep.

3ARSG4 said...

I want to thank you for your really great Job and for your help and I am lucky that I found your blog.
I successfully retrieve information from dcm4chee using dcmqr ,and now i want
to retrieve the objects (images) and store them in specific folder that i can
show them in my webapplication intreface (Query and retrieve images for
visualization).
I would like to ask you, if there is an easy way how to retrive images?

Kindly regards,

Imen

Matt said...

Hello Samucs,

i have one question , why it doesn't list all tags for example transfer syntax uid (0002,0010)but start from
(0008,0005)

Aurélio Maicá said...

Ola Samuel como eu poderia ler uma pasta com arquivos dicom? a qual tem aquele numero "extenso" chamado "study stance uid" ?
Abraço!

Unknown said...

Oi Aurélio,
Para cada arquivo dentro da pasta, tente da seguinte forma:

FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DicomInputStream dis = null;


DicomObject ds = null;
try {
dis = new DicomInputStream(bis);
ds = dis.readDicomObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
org.dcm4che2.util.CloseUtils.safeClose(dis);
}


O arquivo DICOM estará contido na variável "ds";
Um abraço,

Samuel.

Anonymous said...

Thanks buddy!!!

Anonymous said...

U rocks! Thanks! U save My life

Anonymous said...

null point exception :(

Unknown said...

Let me know how can I help you.

judy said...

Hi, I have a problem whit the Iterator ,
the problem is: "iterator is a raw type. references to generic type iterator should be parametized" and this line DicomElement element = iter.next(); "type dismatch: cannot convert from Object to dicomElement" my solution : DicomElement element = (DicomElement) iter.next(); but when run the program: java.lang.NullPointerException :( please Help, thanks

Unknown said...

Hi judy,

It seems you are have problems with Java Generics. Try to compile this code using Java 6. Here are some information on Generics: http://docs.oracle.com/javase/tutorial/java/generics

Regards,
Samuel.

Ebi said...

Dear Samuel,
Really worthy docs,and the way of explanation is quite cool.

Regards,
Ebi.

João Paraná said...

oi Samuel,

parabéns pelo trabalho. Simples e direto como todo o software deveria ser.

Unknown said...

Thank you!! Your blog is very helpful!

Anonymous said...

Could post on how to get the same using v3 of the library? And thanks for the wonderful tutorials on DICOM.

Anonymous said...

DicomObject dicom = new BasicDicomObject();
showing error that DicomObject and BasicDicomObject cannot be resolved to a type.
DicomOutputStream dos = new DicomOutputStream(bos);showing error on that line that
The constructo DicomOutputStream(BufferedOutputStream) is undefined. please suggest me how can i resolve..