Loading...
Searching...
No Matches
DicomVFileImage.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26#include "DicomVFileImage.hh"
27#include "DicomFileStructure.hh"
28#include "DicomROI.hh"
29
30#include "G4GeometryTolerance.hh"
31
32#include "dcmtk/dcmdata/dcfilefo.h"
33#include "dcmtk/dcmdata/dcdeftag.h"
34#include "dcmtk/dcmdata/dcpixel.h"
35#include "dcmtk/dcmdata/dcpxitem.h"
36#include "dcmtk/dcmdata/dcpixseq.h"
37#include "dcmtk/dcmrt/drtimage.h"
38
39#include <set>
40
41//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
46
47//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
52
53
54//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
56{
57 std::vector<double> dImagePositionPatient = Read1Data(theDataset, DCM_ImagePositionPatient,3);
58 fLocation = dImagePositionPatient[2];
59 std::vector<double> dSliceThickness = Read1Data(theDataset, DCM_SliceThickness, 1);
60 std::vector<double> dPixelSpacing = Read1Data(theDataset, DCM_PixelSpacing, 2);
61
62 std::vector<double> dRows = Read1Data(theDataset, DCM_Rows, 1);
63 std::vector<double> dColumns = Read1Data(theDataset, DCM_Columns, 1);
64 fNoVoxelsY = dRows[0];
65 fNoVoxelsX = dColumns[0];
66 fNoVoxelsZ = 1;
67
68 fMinX = dImagePositionPatient[0]; // center of upper corner of pixel?
69 fMaxX = dImagePositionPatient[0]+dColumns[0]*dPixelSpacing[0];
70
71 fMinY = dImagePositionPatient[1];
72 fMaxY = dImagePositionPatient[1]+dRows[0]*dPixelSpacing[1];
73
74 fMinZ = dImagePositionPatient[2]-dSliceThickness[0]/2.;
75 fMaxZ = dImagePositionPatient[2]+dSliceThickness[0]/2.;
76 fVoxelDimX = dPixelSpacing[0];
77 fVoxelDimY = dPixelSpacing[1];
78 fVoxelDimZ = dSliceThickness[0];
79
80 if( DicomFileMgr::verbose >= debugVerb ) G4cout << " DicomVFileImage::ReadData: fNoVoxels "
81 << fNoVoxelsX << " " << fNoVoxelsY << " " << fNoVoxelsZ << G4endl;
82 if( DicomFileMgr::verbose >= debugVerb ) G4cout << " DicomVFileImage::ReadData: fMin "
83 << fMinX << " " << fMinY << " " << fMinZ << G4endl;
84 if( DicomFileMgr::verbose >= debugVerb ) G4cout << " DicomVFileImage::ReadData: fMax "
85 << fMaxX << " " << fMaxY << " " << fMaxZ << G4endl;
86 if( DicomFileMgr::verbose >= debugVerb ) G4cout << " DicomVFileImage::ReadData: fVoxelDim "
87 << fVoxelDimX << " " << fVoxelDimY << " " << fVoxelDimZ << G4endl;
88
89 std::vector<double> dImageOrientationPatient =
90 Read1Data(theDataset, DCM_ImageOrientationPatient,6);
91 fOrientationRows = G4ThreeVector(dImageOrientationPatient[0],dImageOrientationPatient[1],
92 dImageOrientationPatient[2]);
93 fOrientationColumns = G4ThreeVector(dImageOrientationPatient[3],dImageOrientationPatient[4],
94 dImageOrientationPatient[5]);
95
96 if( fOrientationRows != G4ThreeVector(1,0,0)
97 || fOrientationColumns != G4ThreeVector(0,1,0) ) {
98 G4cerr << " OrientationRows " << fOrientationRows << " OrientationColumns "
99 << fOrientationColumns << G4endl;
100 G4Exception("DicomVFileImage::ReadData",
101 "DFCT0002",
102 JustWarning,
103 "OrientationRows must be (1,0,0) and OrientationColumns (0,1,0), please contact GAMOS authors");
104 }
105 fBitAllocated = Read1Data(theDataset, DCM_BitsAllocated, 1)[0];
106 if( DicomFileMgr::verbose >= 4 ) G4cout << " BIT ALLOCATED " << fBitAllocated << G4endl;
107
108 std::vector<double> dRescaleSlope = Read1Data(theDataset, DCM_RescaleSlope, 1);
109 if( dRescaleSlope.size() == 1 ) {
110 fRescaleSlope = dRescaleSlope[0];
111 } else {
112 fRescaleSlope = 1;
113 }
114 std::vector<double> dRescaleIntercept = Read1Data(theDataset, DCM_RescaleIntercept, 1);
115 if( dRescaleIntercept.size() == 1 ) {
116 fRescaleIntercept = dRescaleIntercept[0];
117 } else {
119 }
120
122}
123
124
125//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
127{
128 // READING THE PIXELS :
129 OFCondition result = EC_Normal;
130 //---- CHECK IF DATA IS COMPRESSED
131 DcmElement* element = NULL;
132 result = theDataset->findAndGetElement(DCM_PixelData, element);
133 if (result.bad() || element == NULL) {
134 G4Exception("ReadData",
135 "findAndGetElement(DCM_PixelData, ",
136 FatalException,
137 ("Element PixelData not found: " + G4String(result.text())).c_str());
138 }
139 DcmPixelData *dpix = NULL;
140 dpix = OFstatic_cast(DcmPixelData*, element);
141 // If we have compressed data, we must utilize DcmPixelSequence
142 // in order to access it in raw format, e. g. for decompressing it
143 // with an external library.
144 DcmPixelSequence *dseq = NULL;
145 E_TransferSyntax xferSyntax = EXS_Unknown;
146 const DcmRepresentationParameter *rep = NULL;
147 // Find the key that is needed to access the right representation of the data within DCMTK
148 dpix->getOriginalRepresentationKey(xferSyntax, rep);
149 // Access original data representation and get result within pixel sequence
150 result = dpix->getEncapsulatedRepresentation(xferSyntax, rep, dseq);
151 if ( result == EC_Normal ) // COMPRESSED DATA
152 {
153 G4Exception("DicomVFileImage::ReadData()",
154 "DFCT004",
155 FatalException,
156 "Compressed pixel data is not supported");
157
158 if( DicomFileMgr::verbose >= debugVerb ) G4cout
159 << " DicomVFileImage::ReadData: result == EC_Normal Reading compressed data " << std::endl;
160 DcmPixelItem* pixitem = NULL;
161 // Access first frame (skipping offset table)
162 for( int ii = 1; ii < 2; ii++ ) {
163 OFCondition cond = dseq->getItem(pixitem, ii);
164 if( !cond.good()) break;
165 G4cout << ii << " PIX LENGTH " << pixitem->getLength() << G4endl;
166 }
167 if (pixitem == NULL) {
168 G4Exception("ReadData",
169 "dseq->getItem()",
170 FatalException,
171 "No DcmPixelItem in DcmPixelSequence");
172 }
173 Uint8* pixData = NULL;
174 // Get the length of this pixel item
175 // (i.e. fragment, i.e. most of the time, the lenght of the frame)
176 Uint32 length = pixitem->getLength();
177 if (length == 0) {
178 G4Exception("ReadData",
179 "pixitem->getLength()",
180 FatalException,
181 "PixelData empty");
182 }
183
184 if( DicomFileMgr::verbose >= debugVerb ) G4cout
185 << " DicomVFileImage::ReadData: number of pixels " << length << G4endl;
186 // Finally, get the compressed data for this pixel item
187 result = pixitem->getUint8Array(pixData);
188 } else { // UNCOMPRESSED DATA
189 if(fBitAllocated == 8) { // Case 8 bits :
190 Uint8* pixData = NULL;
191 if(! (element->getUint8Array(pixData)).good() ) {
192 G4Exception("ReadData",
193 "getUint8Array pixData, ",
194 FatalException,
195 ("PixelData not found: " + G4String(result.text())).c_str());
196 }
197 for( int ir = 0; ir < fNoVoxelsY; ir++ ) {
198 for( int ic = 0; ic < fNoVoxelsX; ic++ ) {
199 fHounsfieldV.push_back(pixData[ic+ir*fNoVoxelsX]*fRescaleSlope + fRescaleIntercept);
200 }
201 }
202 } else if(fBitAllocated == 16) { // Case 16 bits :
203 Uint16* pixData = NULL;
204 if(! (element->getUint16Array(pixData)).good() ) {
205 G4Exception("ReadData",
206 "getUint16Array pixData, ",
207 FatalException,
208 ("PixelData not found: " + G4String(result.text())).c_str());
209 }
210 for( int ir = 0; ir < fNoVoxelsY; ir++ ) {
211 for( int ic = 0; ic < fNoVoxelsX; ic++ ) {
212 fHounsfieldV.push_back(pixData[ic+ir*fNoVoxelsX]*fRescaleSlope + fRescaleIntercept);
213 }
214 }
215 } else if(fBitAllocated == 32) { // Case 32 bits :
216 Uint32* pixData = NULL;
217 if(! (element->getUint32Array(pixData)).good() ) {
218 G4Exception("ReadData",
219 "getUint32Array pixData, ",
220 FatalException,
221 ("PixelData not found: " + G4String(result.text())).c_str());
222 }
223 for( int ir = 0; ir < fNoVoxelsY; ir++ ) {
224 for( int ic = 0; ic < fNoVoxelsX; ic++ ) {
225 fHounsfieldV.push_back(pixData[ic+ir*fNoVoxelsX]*fRescaleSlope + fRescaleIntercept);
226 }
227 }
228 }
229 }
230
231}
232
233//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
235{
236 *this = *this + rhs;
237}
238
239//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
241{
242 //----- Check that both slices has the same dimensions
243 if( fNoVoxelsX != rhs.GetNoVoxelsX()
244 || fNoVoxelsY != rhs.GetNoVoxelsY() ) {
245 G4cerr << "DicomVFileImage error adding two slice headers:\
246 !!! Different number of voxels: "
247 << " X= " << fNoVoxelsX << " =? " << rhs.GetNoVoxelsX()
248 << " Y= " << fNoVoxelsY << " =? " << rhs.GetNoVoxelsY()
249 << " Z= " << fNoVoxelsZ << " =? " << rhs.GetNoVoxelsZ()
250 << G4endl;
251 G4Exception("DicomVFileImage::DicomVFileImage",
252 "",FatalErrorInArgument,"");
253 }
254 //----- Check that both slices has the same extensions
255 if( fMinX != rhs.GetMinX() || fMaxX != rhs.GetMaxX()
256 || fMinY != rhs.GetMinY() || fMaxY != rhs.GetMaxY() ) {
257 G4cerr << "DicomVFileImage error adding two slice headers:\
258 !!! Different extensions: "
259 << " Xmin= " << fMinX << " =? " << rhs.GetMinX()
260 << " Xmax= " << fMaxX << " =? " << rhs.GetMaxX()
261 << " Ymin= " << fMinY << " =? " << rhs.GetMinY()
262 << " Ymax= " << fMaxY << " =? " << rhs.GetMaxY()
263 << G4endl;
264 G4Exception("DicomVFileImage::operator+","",
265 FatalErrorInArgument,"");
266 }
267
268 //----- Check that both slices has the same orientations
271 G4cerr << "DicomVFileImage error adding two slice headers: !!!\
272 Slices have different orientations "
273 << " Orientation Rows = " << fOrientationRows << " & " << rhs.GetOrientationRows()
274 << " Orientation Columns " << fOrientationColumns << " & "
275 << rhs.GetOrientationColumns() << G4endl;
276 G4Exception("DicomVFileImage::operator+","",
277 FatalErrorInArgument,"");
278 }
279
280 //----- Check that the slices are contiguous in Z
281 if( std::fabs( fMinZ - rhs.GetMaxZ() ) >
282 G4GeometryTolerance::GetInstance()->GetRadialTolerance() &&
283 std::fabs( fMaxZ - rhs.GetMinZ() ) >
284 G4GeometryTolerance::GetInstance()->GetRadialTolerance() ){
285 G4cerr << "DicomVFileImage error adding two slice headers: !!!\
286 Slices are not contiguous in Z "
287 << " Zmin= " << fMinZ << " & " << rhs.GetMinZ()
288 << " Zmax= " << fMaxZ << " & " << rhs.GetMaxZ()
289 << G4endl;
290 G4Exception("DicomVFileImage::operator+","",
291 JustWarning,"");
292 }
293
294 //----- Build slice header copying first one
295 DicomVFileImage temp( *this );
296
297 //----- Add data from second slice header
298 temp.SetMinZ( std::min( fMinZ, rhs.GetMinZ() ) );
299 temp.SetMaxZ( std::max( fMaxZ, rhs.GetMaxZ() ) );
300 temp.SetNoVoxelsZ( fNoVoxelsZ + rhs.GetNoVoxelsZ() );
301
302 return temp;
303}
304
305//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
307{
308 if( DicomFileMgr::verbose >= warningVerb ) G4cout << fLocation << " DumpHeaderToTextFile "
309 << fFileName << " " << fHounsfieldV.size() << G4endl;
310
311 G4String fName = fFileName.substr(0,fFileName.length()-3) + "g4dcm";
312 std::ofstream out(fName.c_str());
313
314 if( DicomFileMgr::verbose >= warningVerb ) G4cout
315 << "### DicomVFileImage::Dumping Z Slice header to Text file " << G4endl;
316
317 G4int fCompress = theFileMgr->GetCompression();
318 fout << fNoVoxelsX/fCompress << " " << fNoVoxelsY/fCompress << " " << fNoVoxelsZ << std::endl;
319 fout << fMinX << " " << fMaxX << std::endl;
320 fout << fMinY << " " << fMaxY << std::endl;
321 fout << fMinZ << " " << fMaxZ << std::endl;
322
323}
324
325//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
326void DicomVFileImage::Print(std::ostream& out )
327{
328 G4int fCompress = theFileMgr->GetCompression();
329 out << "@@ CT Slice " << fLocation << G4endl;
330
331 out << "@ NoVoxels " << fNoVoxelsX/fCompress << " " << fNoVoxelsY/fCompress << " "
332 << fNoVoxelsZ << G4endl;
333 out << "@ DIM X: " << fMinX << " " << fMaxX
334 << " Y: " << fMinY << " " << fMaxY
335 << " Z: " << fMinZ << " " << fMaxZ << G4endl;
336}
337
@ debugVerb
@ warningVerb
static G4int verbose
static DicomFileMgr * GetInstance()
G4int GetCompression() const
G4ThreeVector fOrientationRows
void DumpHeaderToTextFile(std::ofstream &fout)
G4ThreeVector GetOrientationRows() const
G4int GetNoVoxelsY() const
G4ThreeVector GetOrientationColumns() const
G4int GetNoVoxelsZ() const
G4ThreeVector fOrientationColumns
G4double fRescaleIntercept
G4double GetMinY() const
virtual void ReadData()
DicomVFileImage operator+(const DicomVFileImage &rhs)
G4int GetNoVoxelsX() const
G4double GetMaxZ() const
void SetMinZ(const G4double &val)
G4double GetMaxX() const
G4double GetMinZ() const
G4double GetMinX() const
void SetNoVoxelsZ(const G4int &val)
void SetMaxZ(const G4double &val)
DicomFileMgr * theFileMgr
G4double GetMaxY() const
void Print(std::ostream &out)
std::vector< int > fHounsfieldV
void operator+=(const DicomVFileImage &rhs)
G4String fFileName
Definition DicomVFile.hh:55
DcmDataset * theDataset
Definition DicomVFile.hh:52
virtual std::vector< G4double > Read1Data(DcmDataset *dset, DcmTagKey tagKey, G4int nData)
Definition DicomVFile.cc:40

Applications | User Support | Publications | Collaboration