Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
DicomHandler Class Reference

#include <Doxymodules_medical.h>

Public Member Functions

 ~DicomHandler ()
 
G4int ReadFile (FILE *, char *)
 
G4int ReadData (FILE *, char *)
 
void CheckFileFormat ()
 

Static Public Member Functions

static DicomHandlerInstance ()
 
static G4String GetDicomDataPath ()
 
static G4String GetDicomDataFile ()
 

Private Member Functions

 DicomHandler ()
 
template<class Type >
void GetValue (char *, Type &)
 
void ReadCalibration ()
 
void GetInformation (G4int &, char *)
 
G4float Pixel2density (G4int pixel)
 
void ReadMaterialIndices (std::ifstream &finData)
 
unsigned int GetMaterialIndex (G4float density)
 
void StoreData (std::ofstream &foutG4DCM)
 
void StoreData (DicomPhantomZSliceHeader *dcmPZSH)
 
G4int read_defined_nested (FILE *, G4int)
 
void read_undefined_nested (FILE *)
 
void read_undefined_item (FILE *)
 

Private Attributes

const G4int DATABUFFSIZE
 
const G4int LINEBUFFSIZE
 
const G4int FILENAMESIZE
 
short fCompression
 
G4int fNFiles
 
short fRows
 
short fColumns
 
short fBitAllocated
 
G4int fMaxPixelValue
 
G4int fMinPixelValue
 
G4double fPixelSpacingX
 
G4double fPixelSpacingY
 
G4double fSliceThickness
 
G4double fSliceLocation
 
G4int fRescaleIntercept
 
G4int fRescaleSlope
 
G4bool fLittleEndian
 
G4bool fImplicitEndian
 
short fPixelRepresentation
 
G4int ** fTab
 
std::map< G4float, G4StringfMaterialIndices
 
G4int fNbrequali
 
G4double * fValueDensity
 
G4double * fValueCT
 
G4bool fReadCalibration
 
DicomPhantomZSliceMergedfMergedSlices
 
G4String fDriverFile
 
G4String fCt2DensityFile
 

Static Private Attributes

static DicomHandlerfInstance = 0
 DicomHandler.cc :
 

Detailed Description

Definition at line 21 of file Doxymodules_medical.h.

Constructor & Destructor Documentation

◆ ~DicomHandler()

DicomHandler::~DicomHandler ( )

Definition at line 164 of file DicomHandler.cc.

165{}

◆ DicomHandler()

DicomHandler::DicomHandler ( )
private

Definition at line 148 of file DicomHandler.cc.

149:DATABUFFSIZE(8192), LINEBUFFSIZE(5020), FILENAMESIZE(512),
150 fCompression(0), fNFiles(0), fRows(0), fColumns(0),
155 fNbrequali(0),fValueDensity(NULL),fValueCT(NULL),
156 fReadCalibration(false),fMergedSlices(NULL),
157 fDriverFile("Data.dat"),fCt2DensityFile("CT2Density.dat")
158{
160}
DicomPhantomZSliceMerged * fMergedSlices
G4double fSliceThickness
G4bool fReadCalibration
G4String fCt2DensityFile
G4double fPixelSpacingX
G4String fDriverFile
G4double * fValueCT
const G4int LINEBUFFSIZE
const G4int FILENAMESIZE
G4bool fLittleEndian
const G4int DATABUFFSIZE
G4double fSliceLocation
G4double * fValueDensity
G4double fPixelSpacingY
G4int fRescaleIntercept
G4bool fImplicitEndian
short fPixelRepresentation

Member Function Documentation

◆ Instance()

DicomHandler * DicomHandler::Instance ( )
static

Definition at line 71 of file DicomHandler.cc.

72{
73 if (fInstance == 0)
74 {
75 static DicomHandler dicomhandler;
76 fInstance = &dicomhandler;
77 }
78 return fInstance;
79}
static DicomHandler * fInstance
DicomHandler.cc :

◆ ReadFile()

G4int DicomHandler::ReadFile ( FILE *  dicom,
char *  filename2 
)

Definition at line 169 of file DicomHandler.cc.

170{
171 G4cout << " ReadFile " << filename2 << G4endl;
172
173 G4int returnvalue = 0; size_t rflag = 0;
174 char * buffer = new char[LINEBUFFSIZE];
175
176 fImplicitEndian = false;
177 fLittleEndian = true;
178
179 rflag = std::fread( buffer, 1, 128, dicom ); // The first 128 bytes
180 //are not important
181 // Reads the "DICOM" letters
182 rflag = std::fread( buffer, 1, 4, dicom );
183 // if there is no preamble, the FILE pointer is rewinded.
184 if(std::strncmp("DICM", buffer, 4) != 0) {
185 std::fseek(dicom, 0, SEEK_SET);
186 fImplicitEndian = true;
187 }
188
189 short readGroupId; // identify the kind of input data
190 short readElementId; // identify a particular type information
191 short elementLength2; // deal with element length in 2 bytes
192 //unsigned int elementLength4;
193 // deal with element length in 4 bytes
194 unsigned long elementLength4; // deal with element length in 4 bytes
195
196 char * data = new char[DATABUFFSIZE];
197
198 // Read information up to the pixel data
199 while(true) {
200
201 //Reading groups and elements :
202 readGroupId = 0;
203 readElementId = 0;
204 // group ID
205 rflag = std::fread(buffer, 2, 1, dicom);
206 GetValue(buffer, readGroupId);
207 // element ID
208 rflag = std::fread(buffer, 2, 1, dicom);
209 GetValue(buffer, readElementId);
210
211 // Creating a tag to be identified afterward
212 G4int tagDictionary = readGroupId*0x10000 + readElementId;
213
214 // beginning of the pixels
215 if(tagDictionary == 0x7FE00010) {
216 // Following 2 fread's are modifications to original DICOM example
217 // (Jonathan Madsen)
218 if(!fImplicitEndian)
219 rflag = std::fread(buffer,2,1,dicom); // Reserved 2 bytes
220 // (not used for pixels)
221 rflag = std::fread(buffer,4,1,dicom); // Element Length
222 // (not used for pixels)
223 break; // Exit to ReadImageData()
224 }
225
226 // VR or element length
227 rflag = std::fread(buffer,2,1,dicom);
228 GetValue(buffer, elementLength2);
229
230 // If value representation (VR) is OB, OW, SQ, UN, added OF and UT
231 //the next length is 32 bits
232 if((elementLength2 == 0x424f || // "OB"
233 elementLength2 == 0x574f || // "OW"
234 elementLength2 == 0x464f || // "OF"
235 elementLength2 == 0x5455 || // "UT"
236 elementLength2 == 0x5153 || // "SQ"
237 elementLength2 == 0x4e55) && // "UN"
238 !fImplicitEndian ) { // explicit VR
239
240 rflag = std::fread(buffer, 2, 1, dicom); // Skip 2 reserved bytes
241
242 // element length
243 rflag = std::fread(buffer, 4, 1, dicom);
244 GetValue(buffer, elementLength4);
245
246 if(elementLength2 == 0x5153)
247 {
248 if(elementLength4 == 0xFFFFFFFF)
249 {
250 read_undefined_nested( dicom );
251 elementLength4=0;
252 } else{
253 if(read_defined_nested( dicom, elementLength4 )==0){
254 G4Exception("DicomHandler::ReadFile",
255 "DICOM001",
256 FatalException,
257 "Function read_defined_nested() failed!");
258 }
259 }
260 } else {
261 // Reading the information with data
262 rflag = std::fread(data, elementLength4,1,dicom);
263 }
264
265 } else {
266
267 // explicit with VR different than previous ones
268 if(!fImplicitEndian || readGroupId == 2) {
269
270 //G4cout << "Reading DICOM files with Explicit VR"<< G4endl;
271 // element length (2 bytes)
272 rflag = std::fread(buffer, 2, 1, dicom);
273 GetValue(buffer, elementLength2);
274 elementLength4 = elementLength2;
275
276 rflag = std::fread(data, elementLength4, 1, dicom);
277
278 } else { // Implicit VR
279
280 //G4cout << "Reading DICOM files with Implicit VR"<< G4endl;
281
282 // element length (4 bytes)
283 if(std::fseek(dicom, -2, SEEK_CUR) != 0) {
284 G4Exception("DicomHandler::ReadFile",
285 "DICOM001",
286 FatalException,
287 "fseek failed");
288 }
289
290 rflag = std::fread(buffer, 4, 1, dicom);
291 GetValue(buffer, elementLength4);
292
293 //G4cout << std::hex<< elementLength4 << G4endl;
294
295 if(elementLength4 == 0xFFFFFFFF)
296 {
298 elementLength4=0;
299 } else{
300 rflag = std::fread(data, elementLength4, 1, dicom);
301 }
302
303 }
304 }
305
306 // NULL termination
307 data[elementLength4] = '\0';
308
309 // analyzing information
310 GetInformation(tagDictionary, data);
311 }
312
313 G4String fnameG4DCM = G4String(filename2) + ".g4dcm";
314
315 // Perform functions originally written straight to file
316 DicomPhantomZSliceHeader* zslice = new DicomPhantomZSliceHeader(fnameG4DCM);
317 for(auto ite = fMaterialIndices.cbegin();
318 ite != fMaterialIndices.cend(); ++ite)
319 {
320 zslice->AddMaterial(ite->second);
321 }
322
325 zslice->SetNoVoxelsZ(1);
326
327 zslice->SetMinX(-fPixelSpacingX*fColumns/2.);
328 zslice->SetMaxX(fPixelSpacingX*fColumns/2.);
329
330 zslice->SetMinY(-fPixelSpacingY*fRows/2.);
331 zslice->SetMaxY(fPixelSpacingY*fRows/2.);
332
335
336 //===
337
338 ReadData( dicom, filename2 );
339
340 // DEPRECIATED
341 //StoreData( foutG4DCM );
342 //foutG4DCM.close();
343
344 StoreData( zslice );
345
346 // Dumped 2 file after DicomPhantomZSliceMerged has checked for consistency
347 //zslice->DumpToFile();
348
349 fMergedSlices->AddZSlice(zslice);
350
351 //
352 delete [] buffer;
353 delete [] data;
354
355 if (rflag) return returnvalue;
356 return returnvalue;
357}
void StoreData(std::ofstream &foutG4DCM)
G4int ReadData(FILE *, char *)
void GetValue(char *, Type &)
std::map< G4float, G4String > fMaterialIndices
void read_undefined_nested(FILE *)
G4int read_defined_nested(FILE *, G4int)
void GetInformation(G4int &, char *)
DicomPhantomZSliceHeader class.
void SetMinZ(const G4double &val)
void AddMaterial(const G4String &val)
void SetMinX(const G4double &val)
void SetNoVoxelsX(const G4int &val)
void SetMaxX(const G4double &val)
void SetMaxY(const G4double &val)
void SetNoVoxelsY(const G4int &val)
void SetMinY(const G4double &val)
void SetNoVoxelsZ(const G4int &val)
void SetMaxZ(const G4double &val)
void AddZSlice(DicomPhantomZSliceHeader *val)

◆ ReadData()

G4int DicomHandler::ReadData ( FILE *  dicom,
char *  filename2 
)

Definition at line 679 of file DicomHandler.cc.

680{
681 G4int returnvalue = 0; size_t rflag = 0;
682
683 // READING THE PIXELS
684
685 fTab = new G4int*[fRows];
686 for ( G4int i = 0; i < fRows; ++i )
687 {
688 fTab[i] = new G4int[fColumns];
689 }
690
691 if(fBitAllocated == 8) { // Case 8 bits :
692
693 std::printf("@@@ Error! Picture != 16 bits...\n");
694 std::printf("@@@ Error! Picture != 16 bits...\n");
695 std::printf("@@@ Error! Picture != 16 bits...\n");
696
697 unsigned char ch = 0;
698
699 for(G4int j = 0; j < fRows; ++j) {
700 for(G4int i = 0; i < fColumns; ++i) {
701 rflag = std::fread( &ch, 1, 1, dicom);
703 }
704 }
705 returnvalue = 1;
706
707 } else { // from 12 to 16 bits :
708 char sbuff[2];
709 short pixel;
710 for( G4int j = 0; j < fRows; ++j) {
711 for( G4int i = 0; i < fColumns; ++i) {
712 rflag = std::fread(sbuff, 2, 1, dicom);
713 GetValue(sbuff, pixel);
714 fTab[j][i] = pixel*fRescaleSlope + fRescaleIntercept;
715 }
716 }
717 }
718
719 // Creation of .g4 files wich contains averaged density data
720 G4String nameProcessed = filename2 + G4String(".g4dcmb");
721 FILE* fileOut = std::fopen(nameProcessed.c_str(),"w+b");
722
723 G4cout << "### Writing of "<< nameProcessed << " ###\n";
724
725 unsigned int nMate = fMaterialIndices.size();
726 rflag = std::fwrite(&nMate, sizeof(unsigned int), 1, fileOut);
727 //--- Write materials
728 for( auto ite = fMaterialIndices.cbegin();
729 ite != fMaterialIndices.cend(); ++ite )
730 {
731 G4String mateName = (*ite).second;
732 for( std::size_t ii = (*ite).second.length(); ii < 40; ++ii )
733 {
734 mateName += " ";
735 } //mateName = const_cast<char*>(((*ite).second).c_str());
736
737 const char* mateNameC = mateName.c_str();
738 rflag = std::fwrite(mateNameC, sizeof(char),40, fileOut);
739 }
740
741 unsigned int fRowsC = fRows/fCompression;
742 unsigned int fColumnsC = fColumns/fCompression;
743 unsigned int planesC = 1;
744 G4float pixelLocationXM = -G4float(fPixelSpacingX*fColumns/2.);
745 G4float pixelLocationXP = G4float(fPixelSpacingX*fColumns/2.);
746 G4float pixelLocationYM = -G4float(fPixelSpacingY*fRows/2.);
747 G4float pixelLocationYP = G4float(fPixelSpacingY*fRows/2.);
748 G4float fSliceLocationZM = G4float(fSliceLocation-fSliceThickness/2.);
749 G4float fSliceLocationZP = G4float(fSliceLocation+fSliceThickness/2.);
750 //--- Write number of voxels (assume only one voxel in Z)
751 rflag = std::fwrite(&fRowsC, sizeof(unsigned int), 1, fileOut);
752 rflag = std::fwrite(&fColumnsC, sizeof(unsigned int), 1, fileOut);
753 rflag = std::fwrite(&planesC, sizeof(unsigned int), 1, fileOut);
754 //--- Write minimum and maximum extensions
755 rflag = std::fwrite(&pixelLocationXM, sizeof(G4float), 1, fileOut);
756 rflag = std::fwrite(&pixelLocationXP, sizeof(G4float), 1, fileOut);
757 rflag = std::fwrite(&pixelLocationYM, sizeof(G4float), 1, fileOut);
758 rflag = std::fwrite(&pixelLocationYP, sizeof(G4float), 1, fileOut);
759 rflag = std::fwrite(&fSliceLocationZM, sizeof(G4float), 1, fileOut);
760 rflag = std::fwrite(&fSliceLocationZP, sizeof(G4float), 1, fileOut);
761 // rflag = std::fwrite(&fCompression, sizeof(unsigned int), 1, fileOut);
762
763 std::printf("%8i %8i\n",fRows,fColumns);
764 std::printf("%8f %8f\n",fPixelSpacingX,fPixelSpacingY);
765 std::printf("%8f\n", fSliceThickness);
766 std::printf("%8f\n", fSliceLocation);
767 std::printf("%8i\n", fCompression);
768
769 G4int compSize = fCompression;
770 G4int mean;
771 G4float density;
772 G4bool overflow = false;
773
774 //----- Write index of material for each pixel
775 if(compSize == 1) { // no fCompression: each pixel has a density value)
776 for( G4int ww = 0; ww < fRows; ++ww) {
777 for( G4int xx = 0; xx < fColumns; ++xx) {
778 mean = fTab[ww][xx];
779 density = Pixel2density(mean);
780 unsigned int mateID = GetMaterialIndex( density );
781 rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
782 }
783 }
784
785 } else {
786 // density value is the average of a square region of
787 // fCompression*fCompression pixels
788 for(G4int ww = 0; ww < fRows ;ww += compSize ) {
789 for(G4int xx = 0; xx < fColumns ;xx +=compSize ) {
790 overflow = false;
791 mean = 0;
792 for(G4int sumx = 0; sumx < compSize; ++sumx) {
793 for(G4int sumy = 0; sumy < compSize; ++sumy) {
794 if(ww+sumy >= fRows || xx+sumx >= fColumns) overflow = true;
795 mean += fTab[ww+sumy][xx+sumx];
796 }
797 if(overflow) break;
798 }
799 mean /= compSize*compSize;
800
801 if(!overflow) {
802 density = Pixel2density(mean);
803 unsigned int mateID = GetMaterialIndex( density );
804 rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
805 }
806 }
807
808 }
809 }
810
811 //----- Write density for each pixel
812 if(compSize == 1) { // no fCompression: each pixel has a density value)
813 for( G4int ww = 0; ww < fRows; ++ww) {
814 for( G4int xx = 0; xx < fColumns; ++xx) {
815 mean = fTab[ww][xx];
816 density = Pixel2density(mean);
817 rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
818 }
819 }
820
821 } else {
822 // density value is the average of a square region of
823 // fCompression*fCompression pixels
824 for(G4int ww = 0; ww < fRows ;ww += compSize ) {
825 for(G4int xx = 0; xx < fColumns ;xx +=compSize ) {
826 overflow = false;
827 mean = 0;
828 for(G4int sumx = 0; sumx < compSize; ++sumx) {
829 for(G4int sumy = 0; sumy < compSize; ++sumy) {
830 if(ww+sumy >= fRows || xx+sumx >= fColumns) overflow = true;
831 mean += fTab[ww+sumy][xx+sumx];
832 }
833 if(overflow) break;
834 }
835 mean /= compSize*compSize;
836
837 if(!overflow) {
838 density = Pixel2density(mean);
839 rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
840 }
841 }
842
843 }
844 }
845
846 rflag = std::fclose(fileOut);
847
848 delete [] nameProcessed;
849
850 /* for ( G4int i = 0; i < fRows; i ++ ) {
851 delete [] fTab[i];
852 }
853 delete [] fTab;
854 */
855
856 if (rflag) return returnvalue;
857 return returnvalue;
858}
G4float Pixel2density(G4int pixel)
unsigned int GetMaterialIndex(G4float density)

◆ CheckFileFormat()

void DicomHandler::CheckFileFormat ( )

Definition at line 962 of file DicomHandler.cc.

963{
964 std::ifstream checkData(fDriverFile.c_str());
965 char * oneLine = new char[128];
966
967 if(!(checkData.is_open())) { //Check existance of Data.dat
968
970 "\nDicomG4 needs Data.dat (or another driver file specified";
971 message += " in command line):\n";
972 message += "\tFirst line: number of image pixel for a voxel (G4Box)\n";
973 message += "\tSecond line: number of images (CT slices) to read\n";
974 message += "\tEach following line contains the name of a Dicom image";
975 message += " except for the .dcm extension";
976 G4Exception("DicomHandler::ReadFile",
977 "DICOM001",
978 FatalException,
979 message.c_str());
980 }
981
982 checkData >> fCompression;
983 checkData >> fNFiles;
984 G4String oneName;
985 checkData.getline(oneLine,100);
986 std::ifstream testExistence;
987 G4bool existAlready = true;
988 for(G4int rep = 0; rep < fNFiles; ++rep) {
989 checkData.getline(oneLine,100);
990 oneName = oneLine;
991 oneName += ".g4dcm"; // create dicomFile.g4dcm
992 G4cout << fNFiles << " test file " << oneName << G4endl;
993 testExistence.open(oneName.data());
994 if(!(testExistence.is_open())) {
995 existAlready = false;
996 testExistence.clear();
997 testExistence.close();
998 }
999 testExistence.clear();
1000 testExistence.close();
1001 }
1002
1003 ReadMaterialIndices( checkData );
1004
1005 checkData.close();
1006 delete [] oneLine;
1007
1008 if( existAlready == false ) { // The files *.g4dcm have to be created
1009
1010 G4cout << "\nAll the necessary images were not found in processed form "
1011 << ", starting with .dcm images\n";
1012
1013 FILE * dicom;
1014 FILE * lecturePref;
1015 char * fCompressionc = new char[LINEBUFFSIZE];
1016 char * maxc = new char[LINEBUFFSIZE];
1017 //char name[300], inputFile[300];
1018 char * inputFile = new char[FILENAMESIZE];
1019 G4int rflag;
1020 lecturePref = std::fopen(fDriverFile.c_str(),"r");
1021
1022 rflag = std::fscanf(lecturePref,"%s",fCompressionc);
1023 fCompression = atoi(fCompressionc);
1024 rflag = std::fscanf(lecturePref,"%s",maxc);
1025 fNFiles = atoi(maxc);
1026 G4cout << " fNFiles " << fNFiles << G4endl;
1027
1028/////////////////////
1029
1030#ifdef DICOM_USE_HEAD
1031 for( G4int i = 1; i <= fNFiles; ++i )
1032 { // Begin loop on filenames
1033 rflag = std::fscanf(lecturePref,"%s",inputFile);
1034 G4String path = GetDicomDataPath() + "/";
1035
1036 G4String name = inputFile + G4String(".dcm");
1037 //Writes the results to a character string buffer.
1038
1039 G4String name2 = path + name;
1040 // Open input file and give it to gestion_dicom :
1041 G4cout << "### Opening " << name2 << " and reading :\n";
1042 dicom = std::fopen(name2.c_str(),"rb");
1043 // Reading the .dcm in two steps:
1044 // 1. reading the header
1045 // 2. reading the pixel data and store the density in Moyenne.dat
1046 if( dicom != 0 ) {
1047 ReadFile(dicom,inputFile);
1048 } else {
1049 G4cout << "\nError opening file : " << name2 << G4endl;
1050 }
1051 rflag = std::fclose(dicom);
1052 }
1053#else
1054
1055 for( G4int i = 1; i <= fNFiles; ++i )
1056 { // Begin loop on filenames
1057 rflag = std::fscanf(lecturePref,"%s",inputFile);
1058
1059 G4String name = inputFile + G4String(".dcm");
1060 //Writes the results to a character string buffer.
1061
1062 //G4cout << "check: " << name << G4endl;
1063 // Open input file and give it to gestion_dicom :
1064 G4cout << "### Opening " << name << " and reading :\n";
1065 dicom = std::fopen(name.c_str(),"rb");
1066 // Reading the .dcm in two steps:
1067 // 1. reading the header
1068 // 2. reading the pixel data and store the density in Moyenne.dat
1069 if( dicom != 0 ) {
1070 ReadFile(dicom,inputFile);
1071 } else {
1072 G4cout << "\nError opening file : " << name << G4endl;
1073 }
1074 rflag = std::fclose(dicom);
1075 }
1076#endif
1077
1078 rflag = std::fclose(lecturePref);
1079
1080 // Checks the spacing is correct. Dumps to files
1082
1083 delete [] fCompressionc;
1084 delete [] maxc;
1085 delete [] inputFile;
1086 if (rflag) return;
1087
1088 }
1089
1090 if(fValueDensity) { delete [] fValueDensity; }
1091 if(fValueCT) { delete [] fValueCT; }
1092 if(fMergedSlices) { delete fMergedSlices; }
1093
1094}
G4int ReadFile(FILE *, char *)
void ReadMaterialIndices(std::ifstream &finData)
static G4String GetDicomDataPath()
void message(G4RunManager *runmanager)
ts_scorers example shows how to use global scorers.
Definition ts_scorers.cc:71

◆ GetDicomDataPath()

G4String DicomHandler::GetDicomDataPath ( )
static

Definition at line 83 of file DicomHandler.cc.

84{
85 // default is current directory
86 G4String driverPath = ".";
87 // check environment
88 const char* path = std::getenv("DICOM_PATH");
89
90 if(path)
91 {
92 // if is set in environment
93 return G4String(path);
94 }
95 else
96 {
97 // if DICOM_USE_HEAD, look for data installation
98#ifdef DICOM_USE_HEAD
99 G4cerr << "Warning! DICOM was compiled with DICOM_USE_HEAD option but "
100 << "the DICOM_PATH was not set!" << G4endl;
101 G4String datadir = G4GetEnv<G4String>("G4ENSDFSTATEDATA", "");
102 if(datadir.length() > 0)
103 {
104 auto _last = datadir.rfind("/");
105 if(_last != std::string::npos)
106 datadir.erase(_last);
107 driverPath = datadir + "/DICOM1.1/DICOM_HEAD_TEST";
108 G4int rc = setenv("DICOM_PATH", driverPath.c_str(), 0);
109 G4cerr << "\t --> Using '" << driverPath << "'..." << G4endl;
110 G4ConsumeParameters(rc);
111 }
112#endif
113 }
114 return driverPath;
115}

◆ GetDicomDataFile()

G4String DicomHandler::GetDicomDataFile ( )
static

Definition at line 119 of file DicomHandler.cc.

120{
121#if defined(DICOM_USE_HEAD) && defined(G4_DCMTK)
122 return GetDicomDataPath() + "/Data.dat.new";
123#else
124 return GetDicomDataPath() + "/Data.dat";
125#endif
126}

◆ GetValue()

template<class Type >
void DicomHandler::GetValue ( char *  _val,
Type &  _rval 
)
private

Definition at line 1204 of file DicomHandler.cc.

1204 {
1205
1206#if BYTE_ORDER == BIG_ENDIAN
1207 if(fLittleEndian) { // little endian
1208#else // BYTE_ORDER == LITTLE_ENDIAN
1209 if(!fLittleEndian) { // big endian
1210#endif
1211 const G4int SIZE = sizeof(_rval);
1212 char ctemp;
1213 for(G4int i = 0; i < SIZE/2; ++i) {
1214 ctemp = _val[i];
1215 _val[i] = _val[SIZE - 1 - i];
1216 _val[SIZE - 1 - i] = ctemp;
1217 }
1218 }
1219 _rval = *(Type *)_val;
1220 }

◆ ReadCalibration()

void DicomHandler::ReadCalibration ( )
private

Definition at line 876 of file DicomHandler.cc.

877{
878 fNbrequali = 0;
879// CT2Density.dat contains the calibration curve to convert CT (Hounsfield)
880// number to physical density
881 std::ifstream calibration(fCt2DensityFile.c_str());
882 calibration >> fNbrequali;
883 fValueDensity = new G4double[fNbrequali];
884 fValueCT = new G4double[fNbrequali];
885
886 if(!calibration) {
887 G4Exception("DicomHandler::ReadFile","DICOM001", FatalException,
888 "@@@ No value to transform pixels in density!");
889 }
890 else { // calibration was successfully opened
891 for(G4int i = 0; i < fNbrequali; ++i)
892 { // Loop to store all the pts in CT2Density.dat
893 calibration >> fValueCT[i] >> fValueDensity[i];
894 }
895 }
896calibration.close();
897fReadCalibration = true;
898}

◆ GetInformation()

void DicomHandler::GetInformation ( G4int &  tagDictionary,
char *  data 
)
private

Definition at line 361 of file DicomHandler.cc.

362{
363 if(tagDictionary == 0x00280010 ) { // Number of Rows
364 GetValue(data, fRows);
365 std::printf("[0x00280010] Rows -> %i\n",fRows);
366
367 } else if(tagDictionary == 0x00280011 ) { // Number of fColumns
368 GetValue(data, fColumns);
369 std::printf("[0x00280011] Columns -> %i\n",fColumns);
370
371 } else if(tagDictionary == 0x00280102 ) { // High bits ( not used )
372 short highBits;
373 GetValue(data, highBits);
374 std::printf("[0x00280102] High bits -> %i\n",highBits);
375
376 } else if(tagDictionary == 0x00280100 ) { // Bits allocated
377 GetValue(data, fBitAllocated);
378 std::printf("[0x00280100] Bits allocated -> %i\n", fBitAllocated);
379
380 } else if(tagDictionary == 0x00280101 ) { // Bits stored ( not used )
381 short bitStored;
382 GetValue(data, bitStored);
383 std::printf("[0x00280101] Bits stored -> %i\n",bitStored);
384
385 } else if(tagDictionary == 0x00280106 ) { // Min. pixel value
387 std::printf("[0x00280106] Min. pixel value -> %i\n", fMinPixelValue);
388
389 } else if(tagDictionary == 0x00280107 ) { // Max. pixel value
391 std::printf("[0x00280107] Max. pixel value -> %i\n", fMaxPixelValue);
392
393 } else if(tagDictionary == 0x00281053) { // Rescale slope
394 fRescaleSlope = atoi(data);
395 std::printf("[0x00281053] Rescale Slope -> %d\n", fRescaleSlope);
396
397 } else if(tagDictionary == 0x00281052 ) { // Rescalse intercept
398 fRescaleIntercept = atoi(data);
399 std::printf("[0x00281052] Rescale Intercept -> %d\n",
401
402 } else if(tagDictionary == 0x00280103 ) {
403 // Pixel representation ( functions not design to read signed bits )
404 fPixelRepresentation = atoi(data); // 0: unsigned 1: signed
405 std::printf("[0x00280103] Pixel Representation -> %i\n",
407 if(fPixelRepresentation == 1 ) {
408 std::printf("### PIXEL REPRESENTATION = 1, BITS ARE SIGNED, ");
409 std::printf("DICOM READING SCAN FOR UNSIGNED VALUE, POSSIBLE ");
410 std::printf("ERROR !!!!!! -> \n");
411 }
412
413 } else if(tagDictionary == 0x00080006 ) { // Modality
414 std::printf("[0x00080006] Modality -> %s\n", data);
415
416 } else if(tagDictionary == 0x00080070 ) { // Manufacturer
417 std::printf("[0x00080070] Manufacturer -> %s\n", data);
418
419 } else if(tagDictionary == 0x00080080 ) { // Institution Name
420 std::printf("[0x00080080] Institution Name -> %s\n", data);
421
422 } else if(tagDictionary == 0x00080081 ) { // Institution Address
423 std::printf("[0x00080081] Institution Address -> %s\n", data);
424
425 } else if(tagDictionary == 0x00081040 ) { // Institution Department Name
426 std::printf("[0x00081040] Institution Department Name -> %s\n", data);
427
428 } else if(tagDictionary == 0x00081090 ) { // Manufacturer's Model Name
429 std::printf("[0x00081090] Manufacturer's Model Name -> %s\n", data);
430
431 } else if(tagDictionary == 0x00181000 ) { // Device Serial Number
432 std::printf("[0x00181000] Device Serial Number -> %s\n", data);
433
434 } else if(tagDictionary == 0x00080008 ) { // Image type ( not used )
435 std::printf("[0x00080008] Image Types -> %s\n", data);
436
437 } else if(tagDictionary == 0x00283000 ) { //Modality LUT Sequence(not used)
438 std::printf("[0x00283000] Modality LUT Sequence SQ 1 -> %s\n", data);
439
440 } else if(tagDictionary == 0x00283002 ) { // LUT Descriptor ( not used )
441 std::printf("[0x00283002] LUT Descriptor US or SS 3 -> %s\n", data);
442
443 } else if(tagDictionary == 0x00283003 ) { // LUT Explanation ( not used )
444 std::printf("[0x00283003] LUT Explanation LO 1 -> %s\n", data);
445
446 } else if(tagDictionary == 0x00283004 ) { // Modality LUT ( not used )
447 std::printf("[0x00283004] Modality LUT Type LO 1 -> %s\n", data);
448
449 } else if(tagDictionary == 0x00283006 ) { // LUT Data ( not used )
450 std::printf("[0x00283006] LUT Data US or SS -> %s\n", data);
451
452 } else if(tagDictionary == 0x00283010 ) { // VOI LUT ( not used )
453 std::printf("[0x00283010] VOI LUT Sequence SQ 1 -> %s\n", data);
454
455 } else if(tagDictionary == 0x00280120 ) { // Pixel Padding Value (not used)
456 std::printf("[0x00280120] Pixel Padding Value US or SS 1 -> %s\n", data);
457
458 } else if(tagDictionary == 0x00280030 ) { // Pixel Spacing
459 G4String datas(data);
460 G4int iss = G4int(datas.find('\\'));
461 fPixelSpacingX = atof( datas.substr(0,iss).c_str() );
462 fPixelSpacingY = atof( datas.substr(iss+1,datas.length()).c_str() );
463
464 } else if(tagDictionary == 0x00200037 ) { // Image Orientation ( not used )
465 std::printf("[0x00200037] Image Orientation (Phantom) -> %s\n", data);
466
467 } else if(tagDictionary == 0x00200032 ) { // Image Position ( not used )
468 std::printf("[0x00200032] Image Position (Phantom,mm) -> %s\n", data);
469
470 } else if(tagDictionary == 0x00180050 ) { // Slice Thickness
471 fSliceThickness = atof(data);
472 std::printf("[0x00180050] Slice Thickness (mm) -> %f\n", fSliceThickness);
473
474 } else if(tagDictionary == 0x00201041 ) { // Slice Location
475 fSliceLocation = atof(data);
476 std::printf("[0x00201041] Slice Location -> %f\n", fSliceLocation);
477
478 } else if(tagDictionary == 0x00280004 ) { // Photometric Interpretation
479 // ( not used )
480 std::printf("[0x00280004] Photometric Interpretation -> %s\n", data);
481
482 } else if(tagDictionary == 0x00020010) { // Endian
483 if(strcmp(data, "1.2.840.10008.1.2") == 0)
484 fImplicitEndian = true;
485 else if(strncmp(data, "1.2.840.10008.1.2.2", 19) == 0)
486 fLittleEndian = false;
487 //else 1.2.840..10008.1.2.1 (explicit little endian)
488
489 std::printf("[0x00020010] Endian -> %s\n", data);
490 }
491
492 // others
493 else {
494 //std::printf("[0x%x] -> %s\n", tagDictionary, data);
495 ;
496 }
497
498}

◆ Pixel2density()

G4float DicomHandler::Pixel2density ( G4int  pixel)
private

Definition at line 929 of file DicomHandler.cc.

930{
932
933 G4float density = -1.;
934 G4double deltaCT = 0;
935 G4double deltaDensity = 0;
936
937
938 for(G4int j = 1; j < fNbrequali; ++j) {
939 if( pixel >= fValueCT[j-1] && pixel < fValueCT[j]) {
940
941 deltaCT = fValueCT[j] - fValueCT[j-1];
942 deltaDensity = fValueDensity[j] - fValueDensity[j-1];
943
944 // interpolating linearly
945 density = G4float(fValueDensity[j]
946 -((fValueCT[j] - pixel)*deltaDensity/deltaCT ));
947 break;
948 }
949 }
950
951 if(density < 0.) {
952 std::printf("@@@ Error density = %f && Pixel = %i \
953 (0x%x) && deltaDensity/deltaCT = %f\n",density,pixel,pixel,
954 deltaDensity/deltaCT);
955 }
956
957 return density;
958}
void ReadCalibration()

◆ ReadMaterialIndices()

void DicomHandler::ReadMaterialIndices ( std::ifstream &  finData)
private

Definition at line 640 of file DicomHandler.cc.

641{
642 unsigned int nMate;
643 G4String mateName;
644 G4float densityMax;
645 finData >> nMate;
646 if( finData.eof() ) return;
647
648 G4cout << " ReadMaterialIndices " << nMate << G4endl;
649 for( unsigned int ii = 0; ii < nMate; ++ii )
650 {
651 finData >> mateName >> densityMax;
652 fMaterialIndices[densityMax] = mateName;
653 // G4cout << ii << " ReadMaterialIndices " << mateName << " "
654 // << densityMax << G4endl;
655 }
656
657}

◆ GetMaterialIndex()

unsigned int DicomHandler::GetMaterialIndex ( G4float  density)
private

Definition at line 661 of file DicomHandler.cc.

662{
663 std::map<G4float,G4String>::const_reverse_iterator ite;
664 std::size_t ii = fMaterialIndices.size();
665
666 for( ite = fMaterialIndices.crbegin(); ite != fMaterialIndices.crend();
667 ++ite, ii-- )
668 {
669 if( density >= (*ite).first ) { break; }
670 }
671
672 if(ii == fMaterialIndices.size()) { ii = fMaterialIndices.size()-1; }
673
674 return unsigned(ii);
675}

◆ StoreData() [1/2]

void DicomHandler::StoreData ( std::ofstream &  foutG4DCM)
private

Definition at line 556 of file DicomHandler.cc.

557{
558 G4int mean;
559 G4double density;
560 G4bool overflow = false;
561
562 //----- Print indices of material
563 if(fCompression == 1) { // no fCompression: each pixel has a density value)
564 for( G4int ww = 0; ww < fRows; ++ww) {
565 for( G4int xx = 0; xx < fColumns; ++xx) {
566 mean = fTab[ww][xx];
567 density = Pixel2density(mean);
568 foutG4DCM << GetMaterialIndex( G4float(density) ) << " ";
569 }
570 foutG4DCM << G4endl;
571 }
572
573 } else {
574 // density value is the average of a square region of
575 // fCompression*fCompression pixels
576 for(G4int ww = 0; ww < fRows ;ww += fCompression ) {
577 for(G4int xx = 0; xx < fColumns ;xx +=fCompression ) {
578 overflow = false;
579 mean = 0;
580 for(G4int sumx = 0; sumx < fCompression; ++sumx) {
581 for(G4int sumy = 0; sumy < fCompression; ++sumy) {
582 if(ww+sumy >= fRows || xx+sumx >= fColumns) overflow = true;
583 mean += fTab[ww+sumy][xx+sumx];
584 }
585 if(overflow) break;
586 }
588
589 if(!overflow) {
590 density = Pixel2density(mean);
591 foutG4DCM << GetMaterialIndex( G4float(density) ) << " ";
592 }
593 }
594 foutG4DCM << G4endl;
595 }
596
597 }
598
599 //----- Print densities
600 if(fCompression == 1) { // no fCompression: each pixel has a density value)
601 for( G4int ww = 0; ww < fRows; ww++) {
602 for( G4int xx = 0; xx < fColumns; xx++) {
603 mean = fTab[ww][xx];
604 density = Pixel2density(mean);
605 foutG4DCM << density << " ";
606 if( xx%8 == 3 ) foutG4DCM << G4endl; // just for nicer reading
607 }
608 }
609
610 } else {
611 // density value is the average of a square region of
612 // fCompression*fCompression pixels
613 for(G4int ww = 0; ww < fRows ;ww += fCompression ) {
614 for(G4int xx = 0; xx < fColumns ;xx +=fCompression ) {
615 overflow = false;
616 mean = 0;
617 for(G4int sumx = 0; sumx < fCompression; ++sumx) {
618 for(G4int sumy = 0; sumy < fCompression; ++sumy) {
619 if(ww+sumy >= fRows || xx+sumx >= fColumns) overflow = true;
620 mean += fTab[ww+sumy][xx+sumx];
621 }
622 if(overflow) break;
623 }
625
626 if(!overflow) {
627 density = Pixel2density(mean);
628 foutG4DCM << density << " ";
629 if( xx/fCompression%8 == 3 ) foutG4DCM << G4endl; // just for nicer
630 // reading
631 }
632 }
633 }
634
635 }
636
637}

◆ StoreData() [2/2]

void DicomHandler::StoreData ( DicomPhantomZSliceHeader dcmPZSH)
private

Definition at line 502 of file DicomHandler.cc.

503{
504 G4int mean;
505 G4double density;
506 G4bool overflow = false;
507
508 if(!dcmPZSH) { return; }
509
511
512 //----- Print indices of material
513 if(fCompression == 1) { // no fCompression: each pixel has a density value)
514 for( G4int ww = 0; ww < fRows; ++ww) {
515 dcmPZSH->AddRow();
516 for( G4int xx = 0; xx < fColumns; ++xx) {
517 mean = fTab[ww][xx];
518 density = Pixel2density(mean);
519 dcmPZSH->AddValue(density);
520 dcmPZSH->AddMateID(GetMaterialIndex(G4float(density)));
521 }
522 }
523
524 } else {
525 // density value is the average of a square region of
526 // fCompression*fCompression pixels
527 for(G4int ww = 0; ww < fRows ;ww += fCompression ) {
528 dcmPZSH->AddRow();
529 for(G4int xx = 0; xx < fColumns ;xx +=fCompression ) {
530 overflow = false;
531 mean = 0;
532 for(G4int sumx = 0; sumx < fCompression; ++sumx) {
533 for(G4int sumy = 0; sumy < fCompression; ++sumy) {
534 if(ww+sumy >= fRows || xx+sumx >= fColumns) overflow = true;
535 mean += fTab[ww+sumy][xx+sumx];
536 }
537 if(overflow) break;
538 }
540
541 if(!overflow) {
542 density = Pixel2density(mean);
543 dcmPZSH->AddValue(density);
544 dcmPZSH->AddMateID(GetMaterialIndex(G4float(density)));
545 }
546 }
547 }
548 }
549
550 dcmPZSH->FlipData();
551}
void SetSliceLocation(const G4double &val)

◆ read_defined_nested()

G4int DicomHandler::read_defined_nested ( FILE *  nested,
G4int  SQ_Length 
)
private

Definition at line 1098 of file DicomHandler.cc.

1099{
1100 // VARIABLES
1101 unsigned short item_GroupNumber;
1102 unsigned short item_ElementNumber;
1103 G4int item_Length;
1104 G4int items_array_length=0;
1105 char * buffer= new char[LINEBUFFSIZE];
1106 size_t rflag = 0;
1107
1108 while(items_array_length < SQ_Length)
1109 {
1110 rflag = std::fread(buffer, 2, 1, nested);
1111 GetValue(buffer, item_GroupNumber);
1112
1113 rflag = std::fread(buffer, 2, 1, nested);
1114 GetValue(buffer, item_ElementNumber);
1115
1116 rflag = std::fread(buffer, 4, 1, nested);
1117 GetValue(buffer, item_Length);
1118
1119 rflag = std::fread(buffer, item_Length, 1, nested);
1120
1121 items_array_length= items_array_length+8+item_Length;
1122 }
1123
1124 delete [] buffer;
1125
1126 if( SQ_Length>items_array_length )
1127 return 0;
1128 else
1129 return 1;
1130 if (rflag) return 1;
1131}

◆ read_undefined_nested()

void DicomHandler::read_undefined_nested ( FILE *  nested)
private

Definition at line 1135 of file DicomHandler.cc.

1136{
1137 // VARIABLES
1138 unsigned short item_GroupNumber;
1139 unsigned short item_ElementNumber;
1140 unsigned int item_Length;
1141 char * buffer= new char[LINEBUFFSIZE];
1142 size_t rflag = 0;
1143
1144 do
1145 {
1146 rflag = std::fread(buffer, 2, 1, nested);
1147 GetValue(buffer, item_GroupNumber);
1148
1149 rflag = std::fread(buffer, 2, 1, nested);
1150 GetValue(buffer, item_ElementNumber);
1151
1152 rflag = std::fread(buffer, 4, 1, nested);
1153 GetValue(buffer, item_Length);
1154
1155 if(item_Length!=0xffffffff)
1156 rflag = std::fread(buffer, item_Length, 1, nested);
1157 else
1158 read_undefined_item(nested);
1159
1160
1161 } while(item_GroupNumber!=0xFFFE || item_ElementNumber!=0xE0DD
1162 || item_Length!=0);
1163
1164 delete [] buffer;
1165 if (rflag) return;
1166}
void read_undefined_item(FILE *)

◆ read_undefined_item()

void DicomHandler::read_undefined_item ( FILE *  nested)
private

Definition at line 1170 of file DicomHandler.cc.

1171{
1172 // VARIABLES
1173 unsigned short item_GroupNumber;
1174 unsigned short item_ElementNumber;
1175 G4int item_Length; size_t rflag = 0;
1176 char *buffer= new char[LINEBUFFSIZE];
1177
1178 do
1179 {
1180 rflag = std::fread(buffer, 2, 1, nested);
1181 GetValue(buffer, item_GroupNumber);
1182
1183 rflag = std::fread(buffer, 2, 1, nested);
1184 GetValue(buffer, item_ElementNumber);
1185
1186 rflag = std::fread(buffer, 4, 1, nested);
1187 GetValue(buffer, item_Length);
1188
1189
1190 if(item_Length!=0)
1191 rflag = std::fread(buffer,item_Length,1,nested);
1192
1193 }
1194 while(item_GroupNumber!=0xFFFE || item_ElementNumber!=0xE00D
1195 || item_Length!=0);
1196
1197 delete [] buffer;
1198 if (rflag) return;
1199}

Member Data Documentation

◆ fInstance

DicomHandler * DicomHandler::fInstance = 0
staticprivate

DicomHandler.cc :

  • Handling of DICM images
    • Reading headers and pixels
  • Transforming pixel to density and creating *.g4dcm files

Definition at line 97 of file DicomHandler.hh.

◆ DATABUFFSIZE

const G4int DicomHandler::DATABUFFSIZE
private

Definition at line 99 of file DicomHandler.hh.

◆ LINEBUFFSIZE

const G4int DicomHandler::LINEBUFFSIZE
private

Definition at line 100 of file DicomHandler.hh.

◆ FILENAMESIZE

const G4int DicomHandler::FILENAMESIZE
private

Definition at line 101 of file DicomHandler.hh.

◆ fCompression

short DicomHandler::fCompression
private

Definition at line 114 of file DicomHandler.hh.

◆ fNFiles

G4int DicomHandler::fNFiles
private

Definition at line 115 of file DicomHandler.hh.

◆ fRows

short DicomHandler::fRows
private

Definition at line 116 of file DicomHandler.hh.

◆ fColumns

short DicomHandler::fColumns
private

Definition at line 117 of file DicomHandler.hh.

◆ fBitAllocated

short DicomHandler::fBitAllocated
private

Definition at line 118 of file DicomHandler.hh.

◆ fMaxPixelValue

G4int DicomHandler::fMaxPixelValue
private

Definition at line 119 of file DicomHandler.hh.

◆ fMinPixelValue

G4int DicomHandler::fMinPixelValue
private

Definition at line 119 of file DicomHandler.hh.

◆ fPixelSpacingX

G4double DicomHandler::fPixelSpacingX
private

Definition at line 121 of file DicomHandler.hh.

◆ fPixelSpacingY

G4double DicomHandler::fPixelSpacingY
private

Definition at line 121 of file DicomHandler.hh.

◆ fSliceThickness

G4double DicomHandler::fSliceThickness
private

Definition at line 122 of file DicomHandler.hh.

◆ fSliceLocation

G4double DicomHandler::fSliceLocation
private

Definition at line 123 of file DicomHandler.hh.

◆ fRescaleIntercept

G4int DicomHandler::fRescaleIntercept
private

Definition at line 125 of file DicomHandler.hh.

◆ fRescaleSlope

G4int DicomHandler::fRescaleSlope
private

Definition at line 125 of file DicomHandler.hh.

◆ fLittleEndian

G4bool DicomHandler::fLittleEndian
private

Definition at line 127 of file DicomHandler.hh.

◆ fImplicitEndian

G4bool DicomHandler::fImplicitEndian
private

Definition at line 127 of file DicomHandler.hh.

◆ fPixelRepresentation

short DicomHandler::fPixelRepresentation
private

Definition at line 128 of file DicomHandler.hh.

◆ fTab

G4int** DicomHandler::fTab
private

Definition at line 130 of file DicomHandler.hh.

◆ fMaterialIndices

std::map<G4float,G4String> DicomHandler::fMaterialIndices
private

Definition at line 131 of file DicomHandler.hh.

◆ fNbrequali

G4int DicomHandler::fNbrequali
private

Definition at line 133 of file DicomHandler.hh.

◆ fValueDensity

G4double* DicomHandler::fValueDensity
private

Definition at line 134 of file DicomHandler.hh.

◆ fValueCT

G4double* DicomHandler::fValueCT
private

Definition at line 135 of file DicomHandler.hh.

◆ fReadCalibration

G4bool DicomHandler::fReadCalibration
private

Definition at line 136 of file DicomHandler.hh.

◆ fMergedSlices

DicomPhantomZSliceMerged* DicomHandler::fMergedSlices
private

Definition at line 137 of file DicomHandler.hh.

◆ fDriverFile

G4String DicomHandler::fDriverFile
private

Definition at line 139 of file DicomHandler.hh.

◆ fCt2DensityFile

G4String DicomHandler::fCt2DensityFile
private

Definition at line 140 of file DicomHandler.hh.


The documentation for this class was generated from the following files:

Applications | User Support | Publications | Collaboration