How can I get the dose value from DRTDoseIOD?

Questions regarding the DCMRT library, a DCMTK add-on that implements support for the various DICOM Radiation Therapy (RT) IODs

Moderator: Moderator Team

Post Reply
Message
Author
lzhang
Posts: 5
Joined: Mon, 2009-09-21, 09:23
Location: Heidelberg, Germany

How can I get the dose value from DRTDoseIOD?

#1 Post by lzhang »

Hallo!

I need to read the dose value of each voxel from a DICOM-RT dose file. I think they are stored in Pixel Data (7FE0,0010). However, there is no public access to pixeldata in the DRTDoseIOD class. How can I read them?

Thanks a lot.

Jörg Riesmeier
ICSMED DICOM Services
ICSMED DICOM Services
Posts: 2217
Joined: Fri, 2004-10-29, 21:38
Location: Oldenburg, Germany

#2 Post by Jörg Riesmeier »

As a background information: The low-level API of the "dcmrt" module is generated automatically from an XML representation of the relevant parts of the DICOM standard. Therefore, some aspects might not (yet) be 100% perfect from a toolkit user's perspective. This should be fixed by a "medium-level" API which will be specified and implemented in the next couple of weeks.

With regard to the Pixel Data element: There is a comment in the header file for the DRTDoseIOD class:

Code: Select all

  // --- all other attributes (without get/set methods) ---

    // - OverlayData (60xx,3000)
    // - PixelData (7fe0,0010)
So, currently you'll have to retrieve the pixel data directly from the DICOM dataset using e.g. DcmDataset::findAndGetUint16Array(). The dataset is the one that you feed into the read() method of the DRTDoseIOD class.

lzhang
Posts: 5
Joined: Mon, 2009-09-21, 09:23
Location: Heidelberg, Germany

#3 Post by lzhang »

Thank you very much! I have got the pixel data.

However, another question:

Dose Units (3004,0002) shows that the dose value is described as GY = Gray, but the pixel data are int values between 0 and 65530.

How can I transform the int value to an absolute dose value in Gy?

Jörg Riesmeier
ICSMED DICOM Services
ICSMED DICOM Services
Posts: 2217
Joined: Fri, 2004-10-29, 21:38
Location: Oldenburg, Germany

#4 Post by Jörg Riesmeier »

Right, this is also something that should be handled by a higher level API (which is still to be defined).

See DICOM part 3 for details on how to interpret the pixel data values ...

Oliver Nix
Posts: 18
Joined: Tue, 2009-09-22, 12:57
Location: DKFZ Heidelberg

#5 Post by Oliver Nix »

Easy to use retrieval of dose data and scaling to Gy values is definitely on the agenda for the mid-level API of the DCMRT DICOM RT implementation. But it will take some time until this will be available.

For now please use the follwing code for retrieving dose data from a DICOM RT Dose file.

Code: Select all


// Open file, get access to the dcmobjects
DcmFileFormat dfile;
OFCondition cond = dfile.loadFile("Your PATH"); 
if (cond.bad()) 
    return -1;

DcmObject *dset = &dfile;
dfile.loadAllDataIntoMemory();
dset = dfile.getDataset();
DcmDataset *d = dfile.getDataset();

DRTDoseIOD *dcmrt_dose = new DRTDoseIOD();
DcmItem &ditem = dynamic_cast<DcmItem&>(*dset);
dcmrt_dose->read(ditem);

// get some properties of the RT Dose Object
Uint16 rows, columns, frames;
Uint16 &rows_ref = rows;
Uint16 &columns_ref = columns;

dcmrt_dose->getRows(rows_ref);
dcmrt_dose->getColumns(columns_ref);

OFString nrframes;
dcmrt_dose->getNumberOfFrames(nrframes);
frames = atoi(nrframes.c_str());

// see Dicom Part 3 p504ff for explanations 
OFString doseunits; 
dcmrt_dose->getDoseUnits(doseunits);

OFString dosetype;
dcmrt_dose->getDoseType(dosetype);

OFString summationtype;
dcmrt_dose->getDoseSummationType(summationtype);

OFString gridscaling;
dcmrt_dose->getDoseGridScaling(gridscaling);
Float32 gridscale = atof(gridscaling.c_str());

const Uint16 *pixelData = NULL;
unsigned long count = 0;

if (d->findAndGetUint16Array(DCM_PixelData, pixelData, &count).good())  
    {     
       for(int k = 0; k < frames; k++){
         for(int i = 0; i < rows; i++){
          for(int j = 0; j < columns; j++){  
            dose(k,i,j) = pixelData[k*rows*columns + i*columns + j];
            // see Dicom part 3, page 507, (3004,000E)
            dose_gray(k,i,j) = static_cast<Float32>(pixelData[k*rows*columns + i*columns + j]) * gridscale;
            }
          } 
        }
     }

I am not sure if this is the most clever way to do but it works for the data sets we have.

lzhang
Posts: 5
Joined: Mon, 2009-09-21, 09:23
Location: Heidelberg, Germany

#6 Post by lzhang »

Thanks for the tips, Oliver, especially the Dose Grid Scaling (3004,000E)! :lol:

Jörg Riesmeier
ICSMED DICOM Services
ICSMED DICOM Services
Posts: 2217
Joined: Fri, 2004-10-29, 21:38
Location: Oldenburg, Germany

#7 Post by Jörg Riesmeier »

Btw, instead of atof() you should better use OFStandard::atof() because atof() depends on the current locale setting (e.g. in Germany the comma and not the point is used as a decimal separator!).

Jason Tang
Posts: 5
Joined: Fri, 2010-07-02, 14:55

#8 Post by Jason Tang »

Just a quick correction to this line to those using Oliver's code, which is very helpful btw:
const Uint16 *pixelData = NULL;

We have to allocate the memory with something like:
const Uint16 *pixelData = new Uint16[rows*columns*frames];

Otherwise the findandgetUint16 will not do anything!

Jörg Riesmeier
ICSMED DICOM Services
ICSMED DICOM Services
Posts: 2217
Joined: Fri, 2004-10-29, 21:38
Location: Oldenburg, Germany

#9 Post by Jörg Riesmeier »

No, that's not true. Read the API documentation of findAndGetUint16Array().

Jason Tang
Posts: 5
Joined: Fri, 2010-07-02, 14:55

#10 Post by Jason Tang »

Thanks Jorg,

On a related note, how would you map this pixel data / dose grid to the image like an overlay? (I want to heat-map this data with a VTK colour map). We would need some data in image coordinates to give this scalar data meaning no?

Is DCM_OverlayData what I need? But I can't seem to extract it. Upon use of DcmDataset::tagExistsWithValue(), it seems that the tag is not there.

Thanks in advance for your assistance.

Regards,
Jason

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

#11 Post by Michael Onken »

Hi,

yes theoretically you could use overlays for that. However, overlays in DICOM only have 1 Bit information per pixel, i.e. this should not be enough for a heatmap since you can only display a pixel black (or any other, single color) or transparent.

One way (the lo-tech solution;) is to render the heatmap onto the image and store it as Secondary Capture Image for example.

The nice (hi-tech) way to superimpose an image over an existing one (e.g. PET over CT) is to create both images and then have a so-called Blending Softcopy Presentation State in order to define how the mapping of both should work. However, this not widely found in products, yet. Also, we don't have any API (except dcmdata, of course) to help you with that.

Best regards,
Michael

Jason Tang
Posts: 5
Joined: Fri, 2010-07-02, 14:55

#12 Post by Jason Tang »

Thanks for the info Michael!

I'm still a little confused on how to make use of the pixel data. We have the z-positions from the Grid Offset Vector, but how do we get the x and y as well?

From my understanding, the pixel data values are in a specific order and map to specific voxels. Is there anyway to extract these coordinates on the CT to which the pixel data/dose values are mapped?

Best,
Jason

Jason Tang
Posts: 5
Joined: Fri, 2010-07-02, 14:55

#13 Post by Jason Tang »

I have figured it out: the dose grid starts at the vector specified in tag "DCM_ImagePositionPatient". From there you generate the grid from the pixel spacing values for X and Y and then you can overlay/heat-map the pixel data using VTK.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest