88 const char* path = std::getenv(
"DICOM_PATH");
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)
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;
121 #if defined(DICOM_USE_HEAD) && defined(G4_DCMTK)
130 #ifdef DICOM_USE_HEAD
132 :DATABUFFSIZE(8192), LINEBUFFSIZE(5020), FILENAMESIZE(512),
133 fCompression(0),fNFiles(0), fRows(0), fColumns(0),
134 fBitAllocated(0), fMaxPixelValue(0),
135 fMinPixelValue(0),fPixelSpacingX(0.),
136 fPixelSpacingY(0.),fSliceThickness(0.),
137 fSliceLocation(0.),fRescaleIntercept(0),
138 fRescaleSlope(0),fLittleEndian(
true),
139 fImplicitEndian(
false),fPixelRepresentation(0),
140 fNbrequali(0),fValueDensity(NULL),fValueCT(NULL),fReadCalibration(
false),
141 fMergedSlices(NULL),fCt2DensityFile(
"null.dat")
149 :DATABUFFSIZE(8192), LINEBUFFSIZE(5020), FILENAMESIZE(512),
150 fCompression(0), fNFiles(0), fRows(0), fColumns(0),
151 fBitAllocated(0), fMaxPixelValue(0), fMinPixelValue(0),
152 fPixelSpacingX(0.), fPixelSpacingY(0.),fSliceThickness(0.),
153 fSliceLocation(0.), fRescaleIntercept(0), fRescaleSlope(0),
154 fLittleEndian(
true),fImplicitEndian(
false),fPixelRepresentation(0),
155 fNbrequali(0),fValueDensity(NULL),fValueCT(NULL),
156 fReadCalibration(
false),fMergedSlices(NULL),
157 fDriverFile(
"Data.dat"),fCt2DensityFile(
"CT2Density.dat")
173 G4int returnvalue = 0;
size_t rflag = 0;
179 rflag = std::fread( buffer, 1, 128, dicom );
182 rflag = std::fread( buffer, 1, 4, dicom );
184 if(std::strncmp(
"DICM", buffer, 4) != 0) {
185 std::fseek(dicom, 0, SEEK_SET);
191 short elementLength2;
194 unsigned long elementLength4;
205 rflag = std::fread(buffer, 2, 1, dicom);
208 rflag = std::fread(buffer, 2, 1, dicom);
212 G4int tagDictionary = readGroupId*0x10000 + readElementId;
215 if(tagDictionary == 0x7FE00010) {
219 rflag = std::fread(buffer,2,1,dicom);
221 rflag = std::fread(buffer,4,1,dicom);
227 rflag = std::fread(buffer,2,1,dicom);
232 if((elementLength2 == 0x424f ||
233 elementLength2 == 0x574f ||
234 elementLength2 == 0x464f ||
235 elementLength2 == 0x5455 ||
236 elementLength2 == 0x5153 ||
237 elementLength2 == 0x4e55) &&
240 rflag = std::fread(buffer, 2, 1, dicom);
243 rflag = std::fread(buffer, 4, 1, dicom);
246 if(elementLength2 == 0x5153)
248 if(elementLength4 == 0xFFFFFFFF)
257 "Function read_defined_nested() failed!");
262 rflag = std::fread(data, elementLength4,1,dicom);
272 rflag = std::fread(buffer, 2, 1, dicom);
274 elementLength4 = elementLength2;
276 rflag = std::fread(data, elementLength4, 1, dicom);
283 if(std::fseek(dicom, -2, SEEK_CUR) != 0) {
290 rflag = std::fread(buffer, 4, 1, dicom);
295 if(elementLength4 == 0xFFFFFFFF)
300 rflag = std::fread(data, elementLength4, 1, dicom);
307 data[elementLength4] =
'\0';
355 if (rflag)
return returnvalue;
363 if(tagDictionary == 0x00280010 ) {
367 }
else if(tagDictionary == 0x00280011 ) {
371 }
else if(tagDictionary == 0x00280102 ) {
374 std::printf(
"[0x00280102] High bits -> %i\n",highBits);
376 }
else if(tagDictionary == 0x00280100 ) {
380 }
else if(tagDictionary == 0x00280101 ) {
383 std::printf(
"[0x00280101] Bits stored -> %i\n",bitStored);
385 }
else if(tagDictionary == 0x00280106 ) {
389 }
else if(tagDictionary == 0x00280107 ) {
393 }
else if(tagDictionary == 0x00281053) {
397 }
else if(tagDictionary == 0x00281052 ) {
399 std::printf(
"[0x00281052] Rescale Intercept -> %d\n",
402 }
else if(tagDictionary == 0x00280103 ) {
405 std::printf(
"[0x00280103] Pixel Representation -> %i\n",
408 std::printf(
"### PIXEL REPRESENTATION = 1, BITS ARE SIGNED, ");
409 std::printf(
"DICOM READING SCAN FOR UNSIGNED VALUE, POSSIBLE ");
413 }
else if(tagDictionary == 0x00080006 ) {
414 std::printf(
"[0x00080006] Modality -> %s\n", data);
416 }
else if(tagDictionary == 0x00080070 ) {
417 std::printf(
"[0x00080070] Manufacturer -> %s\n", data);
419 }
else if(tagDictionary == 0x00080080 ) {
420 std::printf(
"[0x00080080] Institution Name -> %s\n", data);
422 }
else if(tagDictionary == 0x00080081 ) {
423 std::printf(
"[0x00080081] Institution Address -> %s\n", data);
425 }
else if(tagDictionary == 0x00081040 ) {
426 std::printf(
"[0x00081040] Institution Department Name -> %s\n", data);
428 }
else if(tagDictionary == 0x00081090 ) {
429 std::printf(
"[0x00081090] Manufacturer's Model Name -> %s\n", data);
431 }
else if(tagDictionary == 0x00181000 ) {
432 std::printf(
"[0x00181000] Device Serial Number -> %s\n", data);
434 }
else if(tagDictionary == 0x00080008 ) {
435 std::printf(
"[0x00080008] Image Types -> %s\n", data);
437 }
else if(tagDictionary == 0x00283000 ) {
438 std::printf(
"[0x00283000] Modality LUT Sequence SQ 1 -> %s\n", data);
440 }
else if(tagDictionary == 0x00283002 ) {
441 std::printf(
"[0x00283002] LUT Descriptor US or SS 3 -> %s\n", data);
443 }
else if(tagDictionary == 0x00283003 ) {
444 std::printf(
"[0x00283003] LUT Explanation LO 1 -> %s\n", data);
446 }
else if(tagDictionary == 0x00283004 ) {
447 std::printf(
"[0x00283004] Modality LUT Type LO 1 -> %s\n", data);
449 }
else if(tagDictionary == 0x00283006 ) {
450 std::printf(
"[0x00283006] LUT Data US or SS -> %s\n", data);
452 }
else if(tagDictionary == 0x00283010 ) {
453 std::printf(
"[0x00283010] VOI LUT Sequence SQ 1 -> %s\n", data);
455 }
else if(tagDictionary == 0x00280120 ) {
456 std::printf(
"[0x00280120] Pixel Padding Value US or SS 1 -> %s\n", data);
458 }
else if(tagDictionary == 0x00280030 ) {
462 fPixelSpacingY = atof( datas.substr(iss+1,datas.length()).c_str() );
464 }
else if(tagDictionary == 0x00200037 ) {
465 std::printf(
"[0x00200037] Image Orientation (Phantom) -> %s\n", data);
467 }
else if(tagDictionary == 0x00200032 ) {
468 std::printf(
"[0x00200032] Image Position (Phantom,mm) -> %s\n", data);
470 }
else if(tagDictionary == 0x00180050 ) {
474 }
else if(tagDictionary == 0x00201041 ) {
478 }
else if(tagDictionary == 0x00280004 ) {
480 std::printf(
"[0x00280004] Photometric Interpretation -> %s\n", data);
482 }
else if(tagDictionary == 0x00020010) {
483 if(strcmp(data,
"1.2.840.10008.1.2") == 0)
485 else if(strncmp(data,
"1.2.840.10008.1.2.2", 19) == 0)
508 if(!dcmPZSH) {
return; }
534 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
535 mean +=
fTab[ww+sumy][
xx+sumx];
582 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
583 mean +=
fTab[ww+sumy][
xx+sumx];
605 foutG4DCM << density <<
" ";
606 if(
xx%8 == 3 ) foutG4DCM <<
G4endl;
619 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
620 mean +=
fTab[ww+sumy][
xx+sumx];
628 foutG4DCM << density <<
" ";
629 if(
xx/fCompression%8 == 3 ) foutG4DCM <<
G4endl;
646 if( finData.eof() )
return;
649 for(
unsigned int ii = 0; ii < nMate; ++ii )
651 finData >> mateName >> densityMax;
663 std::map<G4float,G4String>::const_reverse_iterator ite;
669 if( density >= (*ite).first ) {
break; }
681 G4int returnvalue = 0;
size_t rflag = 0;
698 unsigned char ch = 0;
703 rflag = std::fread( &ch, 1, 1, dicom);
715 rflag = std::fread(sbuff, 2, 1, dicom);
726 std::sprintf(nameProcessed,
"%s.g4dcmb",filename2);
727 fileOut = std::fopen(nameProcessed,
"w+b");
728 std::printf(
"### Writing of %s ###\n",nameProcessed);
731 rflag = std::fwrite(&nMate,
sizeof(
unsigned int), 1, fileOut);
737 for( std::size_t ii = (*ite).second.length(); ii < 40; ++ii )
742 const char* mateNameC = mateName.c_str();
743 rflag = std::fwrite(mateNameC,
sizeof(
char),40, fileOut);
748 unsigned int planesC = 1;
756 rflag = std::fwrite(&fRowsC,
sizeof(
unsigned int), 1, fileOut);
757 rflag = std::fwrite(&fColumnsC,
sizeof(
unsigned int), 1, fileOut);
758 rflag = std::fwrite(&planesC,
sizeof(
unsigned int), 1, fileOut);
760 rflag = std::fwrite(&pixelLocationXM,
sizeof(
G4float), 1, fileOut);
761 rflag = std::fwrite(&pixelLocationXP,
sizeof(
G4float), 1, fileOut);
762 rflag = std::fwrite(&pixelLocationYM,
sizeof(
G4float), 1, fileOut);
763 rflag = std::fwrite(&pixelLocationYP,
sizeof(
G4float), 1, fileOut);
764 rflag = std::fwrite(&fSliceLocationZM,
sizeof(
G4float), 1, fileOut);
765 rflag = std::fwrite(&fSliceLocationZP,
sizeof(
G4float), 1, fileOut);
786 rflag = std::fwrite(&mateID,
sizeof(
unsigned int), 1, fileOut);
793 for(
G4int ww = 0; ww <
fRows ;ww += compSize ) {
797 for(
G4int sumx = 0; sumx < compSize; ++sumx) {
798 for(
G4int sumy = 0; sumy < compSize; ++sumy) {
799 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
800 mean +=
fTab[ww+sumy][
xx+sumx];
804 mean /= compSize*compSize;
809 rflag = std::fwrite(&mateID,
sizeof(
unsigned int), 1, fileOut);
822 rflag = std::fwrite(&density,
sizeof(
G4float), 1, fileOut);
829 for(
G4int ww = 0; ww <
fRows ;ww += compSize ) {
833 for(
G4int sumx = 0; sumx < compSize; ++sumx) {
834 for(
G4int sumy = 0; sumy < compSize; ++sumy) {
835 if(ww+sumy >= fRows ||
xx+sumx >= fColumns) overflow =
true;
836 mean +=
fTab[ww+sumy][
xx+sumx];
840 mean /= compSize*compSize;
844 rflag = std::fwrite(&density,
sizeof(
G4float), 1, fileOut);
853 delete [] nameProcessed;
861 if (rflag)
return returnvalue;
869 #ifdef DICOM_USE_HEAD
874 G4cout <<
"No calibration curve for the DICOM HEAD needed!" <<
G4endl;
893 "@@@ No value to transform pixels in density!");
906 #ifdef DICOM_USE_HEAD
912 if (pixel == -998.) density = 0.001290;
914 else if ( pixel == 24.) density = 1.00;
916 else if ( pixel == 52.) density = 1.03;
918 else if ( pixel == 92.) density = 1.10;
920 else if ( pixel == 197.) density = 1.18;
922 else if ( pixel == 923.) density = 1.85;
924 else if ( pixel == 1280.) density = 2.14;
926 else if ( pixel == 2310.) density = 2.89;
950 density =
G4float(fValueDensity[j]
951 -((fValueCT[j] - pixel)*deltaDensity/deltaCT ));
957 std::printf(
"@@@ Error density = %f && Pixel = %i \
958 (0x%x) && deltaDensity/deltaCT = %f\n",density,pixel,pixel,
959 deltaDensity/deltaCT);
970 char * oneLine =
new char[128];
972 if(!(checkData.is_open())) {
975 "\nDicomG4 needs Data.dat (or another driver file specified";
976 message +=
" in command line):\n";
977 message +=
"\tFirst line: number of image pixel for a voxel (G4Box)\n";
978 message +=
"\tSecond line: number of images (CT slices) to read\n";
979 message +=
"\tEach following line contains the name of a Dicom image";
980 message +=
" except for the .dcm extension";
990 checkData.getline(oneLine,100);
991 std::ifstream testExistence;
992 G4bool existAlready =
true;
994 checkData.getline(oneLine,100);
997 G4cout << fNFiles <<
" test file " << oneName <<
G4endl;
998 testExistence.open(oneName.
data());
999 if(!(testExistence.is_open())) {
1000 existAlready =
false;
1001 testExistence.clear();
1002 testExistence.close();
1004 testExistence.clear();
1005 testExistence.close();
1013 if( existAlready ==
false ) {
1015 G4cout <<
"\nAll the necessary images were not found in processed form "
1016 <<
", starting with .dcm images\n";
1026 lecturePref = std::fopen(
fDriverFile.c_str(),
"r");
1028 rflag = std::fscanf(lecturePref,
"%s",fCompressionc);
1029 fCompression = atoi(fCompressionc);
1030 rflag = std::fscanf(lecturePref,
"%s",maxc);
1031 fNFiles = atoi(maxc);
1036 #ifdef DICOM_USE_HEAD
1039 rflag = std::fscanf(lecturePref,
"%s",inputFile);
1042 std::sprintf(name,
"%s.dcm",inputFile);
1046 strcpy(name2, path.c_str());
1047 strcat(name2, name);
1049 std::printf(
"### Opening %s and reading :\n",name2);
1050 dicom = std::fopen(name2,
"rb");
1057 G4cout <<
"\nError opening file : " << name2 <<
G4endl;
1065 rflag = std::fscanf(lecturePref,
"%s",inputFile);
1067 std::sprintf(name,
"%s.dcm",inputFile);
1072 std::printf(
"### Opening %s and reading :\n",name);
1073 dicom = std::fopen(name,
"rb");
1091 delete [] fCompressionc;
1094 delete [] inputFile;
1110 unsigned short item_GroupNumber;
1111 unsigned short item_ElementNumber;
1113 G4int items_array_length=0;
1117 while(items_array_length < SQ_Length)
1119 rflag = std::fread(buffer, 2, 1, nested);
1120 GetValue(buffer, item_GroupNumber);
1122 rflag = std::fread(buffer, 2, 1, nested);
1123 GetValue(buffer, item_ElementNumber);
1125 rflag = std::fread(buffer, 4, 1, nested);
1128 rflag = std::fread(buffer, item_Length, 1, nested);
1130 items_array_length= items_array_length+8+item_Length;
1135 if( SQ_Length>items_array_length )
1139 if (rflag)
return 1;
1147 unsigned short item_GroupNumber;
1148 unsigned short item_ElementNumber;
1149 unsigned int item_Length;
1155 rflag = std::fread(buffer, 2, 1, nested);
1156 GetValue(buffer, item_GroupNumber);
1158 rflag = std::fread(buffer, 2, 1, nested);
1159 GetValue(buffer, item_ElementNumber);
1161 rflag = std::fread(buffer, 4, 1, nested);
1164 if(item_Length!=0xffffffff)
1165 rflag = std::fread(buffer, item_Length, 1, nested);
1170 }
while(item_GroupNumber!=0xFFFE || item_ElementNumber!=0xE0DD
1182 unsigned short item_GroupNumber;
1183 unsigned short item_ElementNumber;
1184 G4int item_Length;
size_t rflag = 0;
1189 rflag = std::fread(buffer, 2, 1, nested);
1190 GetValue(buffer, item_GroupNumber);
1192 rflag = std::fread(buffer, 2, 1, nested);
1193 GetValue(buffer, item_ElementNumber);
1195 rflag = std::fread(buffer, 4, 1, nested);
1200 rflag = std::fread(buffer,item_Length,1,nested);
1203 while(item_GroupNumber!=0xFFFE || item_ElementNumber!=0xE00D
1212 template <
class Type>
1215 #if BYTE_ORDER == BIG_ENDIAN
1217 #else // BYTE_ORDER == LITTLE_ENDIAN
1220 const G4int SIZE =
sizeof(_rval);
1222 for(
G4int i = 0; i < SIZE/2; ++i) {
1224 _val[i] = _val[SIZE - 1 - i];
1225 _val[SIZE - 1 - i] = ctemp;
1228 _rval = *(
Type *)_val;