Geant4.10
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions | Static Public Member Functions
DicomHandler Class Reference

#include <DicomHandler.hh>

Public Member Functions

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

Static Public Member Functions

static DicomHandlerInstance ()
 

Detailed Description

Definition at line 71 of file DicomHandler.hh.

Constructor & Destructor Documentation

DicomHandler::DicomHandler ( )

Definition at line 79 of file DicomHandler.cc.

80 : DATABUFFSIZE(8192), LINEBUFFSIZE(5020), FILENAMESIZE(512),
81  fCompression(0), fNFiles(0), fRows(0), fColumns(0),
82  fBitAllocated(0), fMaxPixelValue(0), fMinPixelValue(0),
83  fPixelSpacingX(0.), fPixelSpacingY(0.),
84  fSliceThickness(0.), fSliceLocation(0.),
85  fRescaleIntercept(0), fRescaleSlope(0),
86  fLittleEndian(true), fImplicitEndian(false),
87  fPixelRepresentation(0), nbrequali(0),
88  valuedensity(NULL),valueCT(NULL),readCalibration(false),
89  mergedSlices(NULL),driverFile("Data.dat"),ct2densityFile("CT2Density.dat")
90 {
91  mergedSlices = new DicomPhantomZSliceMerged;
92 }
DicomHandler::~DicomHandler ( )

Definition at line 97 of file DicomHandler.cc.

98 {
99 
100 }

Member Function Documentation

void DicomHandler::CheckFileFormat ( )

Definition at line 871 of file DicomHandler.cc.

References DicomPhantomZSliceMerged::CheckSlices(), G4String::data(), G4cout, G4endl, and ReadFile().

Referenced by main().

872 {
873  std::ifstream checkData(driverFile.c_str());
874  char * oneLine = new char[128];
875 
876  if(!(checkData.is_open())) { //Check existance of Data.dat
877 
878  G4cout << "\nDicomG4 needs Data.dat (or another driver file specified in command line)"
879  << ":\n\tFirst line: number of image pixel for a "
880  << "voxel (G4Box)\n\tSecond line: number of images (CT slices) to "
881  << "read\n\tEach following line contains the name of a Dicom image except "
882  << "for the .dcm extension\n";
883  exit(0);
884  }
885 
886  checkData >> fCompression;
887  checkData >> fNFiles;
888  G4String oneName;
889  checkData.getline(oneLine,100);
890  std::ifstream testExistence;
891  G4bool existAlready = true;
892  for(G4int rep = 0; rep < fNFiles; rep++) {
893  checkData.getline(oneLine,100);
894  oneName = oneLine;
895  oneName += ".g4dcm"; // create dicomFile.g4dcm
896  G4cout << fNFiles << " test file " << oneName << G4endl;
897  testExistence.open(oneName.data());
898  if(!(testExistence.is_open())) {
899  existAlready = false;
900  testExistence.clear();
901  testExistence.close();
902  }
903  testExistence.clear();
904  testExistence.close();
905  }
906 
907  ReadMaterialIndices( checkData );
908 
909  checkData.close();
910  delete [] oneLine;
911 
912  if( existAlready == false ) { // The files *.g4dcm have to be created
913 
914  G4cout << "\nAll the necessary images were not found in processed form, starting "
915  << "with .dcm images\n";
916 
917  FILE * dicom;
918  FILE * lecturePref;
919  char * fCompressionc = new char[LINEBUFFSIZE];
920  char * maxc = new char[LINEBUFFSIZE];
921  //char name[300], inputFile[300];
922  char * name = new char[FILENAMESIZE];
923  char * inputFile = new char[FILENAMESIZE];
924  G4int rflag;
925 
926  lecturePref = std::fopen(driverFile.c_str(),"r");
927  rflag = std::fscanf(lecturePref,"%s",fCompressionc);
928  fCompression = atoi(fCompressionc);
929  rflag = std::fscanf(lecturePref,"%s",maxc);
930  fNFiles = atoi(maxc);
931  G4cout << " fNFiles " << fNFiles << G4endl;
932 
933  for( G4int i = 1; i <= fNFiles; i++ ) { // Begin loop on filenames
934 
935  rflag = std::fscanf(lecturePref,"%s",inputFile);
936  std::sprintf(name,"%s.dcm",inputFile);
937  std::cout << "check 1: " << name << std::endl;
938  // Open input file and give it to gestion_dicom :
939  std::printf("### Opening %s and reading :\n",name);
940  dicom = std::fopen(name,"rb");
941  // Reading the .dcm in two steps:
942  // 1. reading the header
943  // 2. reading the pixel data and store the density in Moyenne.dat
944  if( dicom != 0 ) {
945  ReadFile(dicom,inputFile);
946  } else {
947  G4cout << "\nError opening file : " << name << G4endl;
948  }
949  rflag = std::fclose(dicom);
950  }
951  rflag = std::fclose(lecturePref);
952 
953  // Checks the spacing is correct. Dumps to files
954  mergedSlices->CheckSlices();
955 
956  delete [] fCompressionc;
957  delete [] maxc;
958  delete [] name;
959  delete [] inputFile;
960  if (rflag) return;
961 
962  }
963 
964  if(valuedensity) { delete [] valuedensity; }
965  if(valueCT) { delete [] valueCT; }
966  if(mergedSlices) { delete mergedSlices; }
967 
968 
969 }
const XML_Char * name
int G4int
Definition: G4Types.hh:78
G4GLOB_DLL std::ostream G4cout
bool G4bool
Definition: G4Types.hh:79
G4int ReadFile(FILE *, char *)
const char * data() const
#define G4endl
Definition: G4ios.hh:61
DicomHandler * DicomHandler::Instance ( void  )
static

Definition at line 72 of file DicomHandler.cc.

73 {
74  return fgInstance;
75 }
G4int DicomHandler::ReadData ( FILE *  dicom,
char *  filename2 
)

Definition at line 624 of file DicomHandler.cc.

References density.

Referenced by ReadFile().

625 {
626  G4int returnvalue = 0; size_t rflag = 0;
627 
628  // READING THE PIXELS :
629  G4int w = 0;
630 
631  fTab = new G4int*[fRows];
632  for ( G4int i = 0; i < fRows; i ++ ) {
633  fTab[i] = new G4int[fColumns];
634  }
635 
636  if(fBitAllocated == 8) { // Case 8 bits :
637 
638  std::printf("@@@ Error! Picture != 16 bits...\n");
639  std::printf("@@@ Error! Picture != 16 bits...\n");
640  std::printf("@@@ Error! Picture != 16 bits...\n");
641 
642  unsigned char ch = 0;
643 
644  for(G4int j = 0; j < fRows; j++) {
645  for(G4int i = 0; i < fColumns; i++) {
646  w++;
647  rflag = std::fread( &ch, 1, 1, dicom);
648  fTab[j][i] = ch*fRescaleSlope + fRescaleIntercept;
649  }
650  }
651  returnvalue = 1;
652 
653  } else { // from 12 to 16 bits :
654  char sbuff[2];
655  short pixel;
656  for( G4int j = 0; j < fRows; j++) {
657  for( G4int i = 0; i < fColumns; i++) {
658  w++;
659  rflag = std::fread(sbuff, 2, 1, dicom);
660  GetValue(sbuff, pixel);
661  fTab[j][i] = pixel*fRescaleSlope + fRescaleIntercept;
662  }
663  }
664  }
665 
666  // Creation of .g4 files wich contains averaged density data
667  char * nameProcessed = new char[FILENAMESIZE];
668  FILE* fileOut;
669 
670  std::sprintf(nameProcessed,"%s.g4dcmb",filename2);
671  fileOut = std::fopen(nameProcessed,"w+b");
672  std::printf("### Writing of %s ###\n",nameProcessed);
673 
674  unsigned int nMate = fMaterialIndices.size();
675  rflag = std::fwrite(&nMate, sizeof(unsigned int), 1, fileOut);
676  //--- Write materials
677  std::map<G4float,G4String>::const_iterator ite;
678  for( ite = fMaterialIndices.begin(); ite != fMaterialIndices.end(); ite++ ){
679  G4String mateName = (*ite).second;
680  for( G4int ii = (*ite).second.length(); ii < 40; ii++ ) {
681  mateName += " ";
682  } //mateName = const_cast<char*>(((*ite).second).c_str());
683 
684  const char* mateNameC = mateName.c_str();
685  rflag = std::fwrite(mateNameC, sizeof(char),40, fileOut);
686  }
687 
688  unsigned int fRowsC = fRows/fCompression;
689  unsigned int fColumnsC = fColumns/fCompression;
690  unsigned int planesC = 1;
691  G4float pixelLocationXM = -fPixelSpacingX*fColumns/2.;
692  G4float pixelLocationXP = fPixelSpacingX*fColumns/2.;
693  G4float pixelLocationYM = -fPixelSpacingY*fRows/2.;
694  G4float pixelLocationYP = fPixelSpacingY*fRows/2.;
695  G4float fSliceLocationZM = fSliceLocation-fSliceThickness/2.;
696  G4float fSliceLocationZP = fSliceLocation+fSliceThickness/2.;
697  //--- Write number of voxels (assume only one voxel in Z)
698  rflag = std::fwrite(&fRowsC, sizeof(unsigned int), 1, fileOut);
699  rflag = std::fwrite(&fColumnsC, sizeof(unsigned int), 1, fileOut);
700  rflag = std::fwrite(&planesC, sizeof(unsigned int), 1, fileOut);
701  //--- Write minimum and maximum extensions
702  rflag = std::fwrite(&pixelLocationXM, sizeof(G4float), 1, fileOut);
703  rflag = std::fwrite(&pixelLocationXP, sizeof(G4float), 1, fileOut);
704  rflag = std::fwrite(&pixelLocationYM, sizeof(G4float), 1, fileOut);
705  rflag = std::fwrite(&pixelLocationYP, sizeof(G4float), 1, fileOut);
706  rflag = std::fwrite(&fSliceLocationZM, sizeof(G4float), 1, fileOut);
707  rflag = std::fwrite(&fSliceLocationZP, sizeof(G4float), 1, fileOut);
708  // rflag = std::fwrite(&fCompression, sizeof(unsigned int), 1, fileOut);
709 
710  std::printf("%8i %8i\n",fRows,fColumns);
711  std::printf("%8f %8f\n",fPixelSpacingX,fPixelSpacingY);
712  std::printf("%8f\n", fSliceThickness);
713  std::printf("%8f\n", fSliceLocation);
714  std::printf("%8i\n", fCompression);
715 
716  G4int compSize = fCompression;
717  G4int mean;
719  G4bool overflow = false;
720 
721  //----- Write index of material for each pixel
722  if(compSize == 1) { // no fCompression: each pixel has a density value)
723  for( G4int ww = 0; ww < fRows; ww++) {
724  for( G4int xx = 0; xx < fColumns; xx++) {
725  mean = fTab[ww][xx];
726  density = Pixel2density(mean);
727  unsigned int mateID = GetMaterialIndex( density );
728  rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
729  }
730  }
731 
732  } else {
733  // density value is the average of a square region of
734  // fCompression*fCompression pixels
735  for(G4int ww = 0; ww < fRows ;ww += compSize ) {
736  for(G4int xx = 0; xx < fColumns ;xx +=compSize ) {
737  overflow = false;
738  mean = 0;
739  for(int sumx = 0; sumx < compSize; sumx++) {
740  for(int sumy = 0; sumy < compSize; sumy++) {
741  if(ww+sumy >= fRows || xx+sumx >= fColumns) overflow = true;
742  mean += fTab[ww+sumy][xx+sumx];
743  }
744  if(overflow) break;
745  }
746  mean /= compSize*compSize;
747 
748  if(!overflow) {
749  density = Pixel2density(mean);
750  unsigned int mateID = GetMaterialIndex( density );
751  rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
752  }
753  }
754 
755  }
756  }
757 
758  //----- Write density for each pixel
759  if(compSize == 1) { // no fCompression: each pixel has a density value)
760  for( G4int ww = 0; ww < fRows; ww++) {
761  for( G4int xx = 0; xx < fColumns; xx++) {
762  mean = fTab[ww][xx];
763  density = Pixel2density(mean);
764  rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
765  }
766  }
767 
768  } else {
769  // density value is the average of a square region of
770  // fCompression*fCompression pixels
771  for(G4int ww = 0; ww < fRows ;ww += compSize ) {
772  for(G4int xx = 0; xx < fColumns ;xx +=compSize ) {
773  overflow = false;
774  mean = 0;
775  for(int sumx = 0; sumx < compSize; sumx++) {
776  for(int sumy = 0; sumy < compSize; sumy++) {
777  if(ww+sumy >= fRows || xx+sumx >= fColumns) overflow = true;
778  mean += fTab[ww+sumy][xx+sumx];
779  }
780  if(overflow) break;
781  }
782  mean /= compSize*compSize;
783 
784  if(!overflow) {
785  density = Pixel2density(mean);
786  rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
787  }
788  }
789 
790  }
791  }
792 
793  rflag = std::fclose(fileOut);
794 
795  delete [] nameProcessed;
796 
797  /* for ( G4int i = 0; i < fRows; i ++ ) {
798  delete [] fTab[i];
799  }
800  delete [] fTab;
801  */
802 
803  if (rflag) return returnvalue;
804  return returnvalue;
805 }
float G4float
Definition: G4Types.hh:77
int G4int
Definition: G4Types.hh:78
G4double density
Definition: TRTMaterials.hh:39
bool G4bool
Definition: G4Types.hh:79
G4int DicomHandler::ReadFile ( FILE *  dicom,
char *  filename2 
)

Definition at line 104 of file DicomHandler.cc.

References DicomPhantomZSliceHeader::AddMaterial(), DicomPhantomZSliceMerged::AddZSlice(), buffer, G4cerr, G4cout, G4endl, ReadData(), DicomPhantomZSliceHeader::SetMaxX(), DicomPhantomZSliceHeader::SetMaxY(), DicomPhantomZSliceHeader::SetMaxZ(), DicomPhantomZSliceHeader::SetMinX(), DicomPhantomZSliceHeader::SetMinY(), DicomPhantomZSliceHeader::SetMinZ(), DicomPhantomZSliceHeader::SetNoVoxelX(), DicomPhantomZSliceHeader::SetNoVoxelY(), and DicomPhantomZSliceHeader::SetNoVoxelZ().

Referenced by CheckFileFormat().

105 {
106  G4cout << " ReadFile " << filename2 << G4endl;
107  G4int returnvalue = 0; size_t rflag = 0;
108  char * buffer = new char[LINEBUFFSIZE];
109 
110  fImplicitEndian = false;
111  fLittleEndian = true;
112 
113  rflag = std::fread( buffer, 1, 128, dicom ); // The first 128 bytes
114  //are not important
115  // Reads the "DICOM" letters
116  rflag = std::fread( buffer, 1, 4, dicom );
117  // if there is no preamble, the FILE pointer is rewinded.
118  if(std::strncmp("DICM", buffer, 4) != 0) {
119  std::fseek(dicom, 0, SEEK_SET);
120  fImplicitEndian = true;
121  }
122 
123  short readGroupId; // identify the kind of input data
124  short readElementId; // identify a particular type information
125  short elementLength2; // deal with element length in 2 bytes
126  //unsigned int elementLength4; // deal with element length in 4 bytes
127  unsigned long elementLength4; // deal with element length in 4 bytes
128 
129  char * data = new char[DATABUFFSIZE];
130 
131 
132  // Read information up to the pixel data
133  while(true) {
134 
135  //Reading groups and elements :
136  readGroupId = 0;
137  readElementId = 0;
138  // group ID
139  rflag = std::fread(buffer, 2, 1, dicom);
140  GetValue(buffer, readGroupId);
141  // element ID
142  rflag = std::fread(buffer, 2, 1, dicom);
143  GetValue(buffer, readElementId);
144 
145  // Creating a tag to be identified afterward
146  G4int tagDictionary = readGroupId*0x10000 + readElementId;
147 
148  // beginning of the pixels
149  if(tagDictionary == 0x7FE00010) {
150  // Folling 2 fread's are modifications to original DICOM example (Jonathan Madsen)
151  rflag = std::fread(buffer,2,1,dicom); // Reserved 2 bytes (not used for pixels)
152  rflag = std::fread(buffer,4,1,dicom); // Element Length (not used for pixels)
153  break; // Exit to ReadImageData()
154  }
155 
156  // VR or element length
157  rflag = std::fread(buffer,2,1,dicom);
158  GetValue(buffer, elementLength2);
159 
160  // If value representation (VR) is OB, OW, SQ, UN, added OF and UT
161  //the next length is 32 bits
162  if((elementLength2 == 0x424f || // "OB"
163  elementLength2 == 0x574f || // "OW"
164  elementLength2 == 0x464f || // "OF"
165  elementLength2 == 0x5455 || // "UT"
166  elementLength2 == 0x5153 || // "SQ"
167  elementLength2 == 0x4e55) && // "UN"
168  !fImplicitEndian ) { // explicit VR
169 
170  rflag = std::fread(buffer, 2, 1, dicom); // Skip 2 reserved bytes
171 
172  // element length
173  rflag = std::fread(buffer, 4, 1, dicom);
174  GetValue(buffer, elementLength4);
175 
176  if(elementLength2 == 0x5153)
177  {
178  if(elementLength4 == 0xFFFFFFFF)
179  {
180  read_undefined_nested( dicom );
181  elementLength4=0;
182  } else{
183  if(read_defined_nested( dicom, elementLength4 )==0){
184  G4cerr << "Function read_defined_nested() failed!" << G4endl;
185  exit(-10); }
186  }
187  } else {
188  // Reading the information with data
189  rflag = std::fread(data, elementLength4,1,dicom);
190  }
191 
192 
193  } else {
194 
195  // explicit with VR different than previous ones
196  if(!fImplicitEndian || readGroupId == 2) {
197 
198  //G4cout << "Reading DICOM files with Explicit VR"<< G4endl;
199  // element length (2 bytes)
200  rflag = std::fread(buffer, 2, 1, dicom);
201  GetValue(buffer, elementLength2);
202  elementLength4 = elementLength2;
203 
204  rflag = std::fread(data, elementLength4, 1, dicom);
205 
206  } else { // Implicit VR
207 
208  //G4cout << "Reading DICOM files with Implicit VR"<< G4endl;
209 
210  // element length (4 bytes)
211  if(std::fseek(dicom, -2, SEEK_CUR) != 0) {
212  G4cerr << "[DicomHandler] fseek failed" << G4endl;
213  exit(-10);}
214 
215  rflag = std::fread(buffer, 4, 1, dicom);
216  GetValue(buffer, elementLength4);
217 
218  //G4cout << std::hex<< elementLength4 << G4endl;
219 
220  if(elementLength4 == 0xFFFFFFFF)
221  {
222  read_undefined_nested(dicom);
223  elementLength4=0;
224  } else{
225  rflag = std::fread(data, elementLength4, 1, dicom);
226  }
227 
228  }
229  }
230 
231  // NULL termination
232  data[elementLength4] = '\0';
233 
234  // analyzing information
235  GetInformation(tagDictionary, data);
236  }
237 
238  G4String fnameG4DCM = G4String(filename2) + ".g4dcm";
239 
240  // Perform functions originally written straight to file
241  DicomPhantomZSliceHeader* zslice = new DicomPhantomZSliceHeader(fnameG4DCM);
242 
243  std::map<G4float,G4String>::const_iterator ite;
244  for( ite = fMaterialIndices.begin(); ite != fMaterialIndices.end(); ++ite ){
245  zslice->AddMaterial(ite->second);
246  }
247 
248  zslice->SetNoVoxelX(fColumns/fCompression);
249  zslice->SetNoVoxelY(fRows/fCompression);
250  zslice->SetNoVoxelZ(1);
251 
252  zslice->SetMinX(-fPixelSpacingX*fColumns/2.);
253  zslice->SetMaxX(fPixelSpacingX*fColumns/2.);
254 
255  zslice->SetMinY(-fPixelSpacingY*fRows/2.);
256  zslice->SetMaxY(fPixelSpacingY*fRows/2.);
257 
258  zslice->SetMinZ(fSliceLocation-fSliceThickness/2.);
259  zslice->SetMaxZ(fSliceLocation+fSliceThickness/2.);
260 
261  //=====================================================================
262  // This is depreciated --> Handled by DicomPhantomZSliceHeader
263  /*
264  // Creating files to store information
265  std::ofstream foutG4DCM;
266  foutG4DCM.open(fnameG4DCM);
267  G4cout << "### Writing of " << fnameG4DCM << " ### " << G4endl;
268 
269  foutG4DCM << fMaterialIndices.size() << G4endl;
270  //--- Write materials
271  unsigned int ii = 0;
272  for( ite = fMaterialIndices.begin(); ite != fMaterialIndices.end(); ite++, ii++ ){
273  foutG4DCM << ii << " " << (*ite).second << G4endl;
274  }
275  //--- Write number of voxels (assume only one voxel in Z)
276  foutG4DCM << fColumns/fCompression << " " << fRows/fCompression << " 1 " << G4endl;
277  //--- Write minimum and maximum extensions
278  foutG4DCM << -fPixelSpacingX*fColumns/2. << " " << fPixelSpacingX*fColumns/2. << G4endl;
279  foutG4DCM << -fPixelSpacingY*fRows/2. << " " << fPixelSpacingY*fRows/2. <<
280  G4endl;
281  foutG4DCM << fSliceLocation-fSliceThickness/2. << " "
282  << fSliceLocation+fSliceThickness/2. << G4endl;
283  // foutG4DCM << fCompression << G4endl;
284  */
285  //=====================================================================
286 
287  ReadData( dicom, filename2 );
288 
289  // DEPRECIATED
290  //StoreData( foutG4DCM );
291  //foutG4DCM.close();
292 
293  StoreData( zslice );
294 
295  // Dumped 2 file after DicomPhantomZSliceMerged has checked for consistency
296  //zslice->DumpToFile();
297 
298  mergedSlices->AddZSlice(zslice);
299 
300  //
301  delete [] buffer;
302  delete [] data;
303 
304  if (rflag) return returnvalue;
305  return returnvalue;
306 }
void SetMinZ(const G4double &val)
void SetMinX(const G4double &val)
void SetNoVoxelY(const G4int &val)
void SetNoVoxelX(const G4int &val)
#define buffer
Definition: xmlparse.cc:611
void SetMinY(const G4double &val)
int G4int
Definition: G4Types.hh:78
G4GLOB_DLL std::ostream G4cout
void SetMaxX(const G4double &val)
G4int ReadData(FILE *, char *)
#define G4endl
Definition: G4ios.hh:61
void AddZSlice(DicomPhantomZSliceHeader *val)
void SetMaxZ(const G4double &val)
void SetNoVoxelZ(const G4int &val)
const XML_Char const XML_Char * data
G4GLOB_DLL std::ostream G4cerr
void AddMaterial(const G4String &val)
void SetMaxY(const G4double &val)

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