Geant4  10.03.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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), fNbrequali(0),
88  fValueDensity(NULL),fValueCT(NULL),fReadCalibration(false),
89  fMergedSlices(NULL),fDriverFile("Data.dat"),fCt2DensityFile("CT2Density.dat")
90 {
91  fMergedSlices = new DicomPhantomZSliceMerged;
92 }
DicomHandler::~DicomHandler ( )

Definition at line 96 of file DicomHandler.cc.

97 {
98 
99 }

Member Function Documentation

void DicomHandler::CheckFileFormat ( )

Definition at line 863 of file DicomHandler.cc.

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

Here is the call graph for this function:

Here is the caller graph for this function:

DicomHandler * DicomHandler::Instance ( void  )
static

Definition at line 72 of file DicomHandler.cc.

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

Definition at line 613 of file DicomHandler.cc.

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

Here is the caller graph for this function:

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

Definition at line 103 of file DicomHandler.cc.

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

Here is the call graph for this function:

Here is the caller graph for this function:


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