File indexing completed on 2025-02-23 09:21:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 #include "DicomHandler.hh"
0055
0056 #include "DicomPhantomZSliceHeader.hh"
0057 #include "DicomPhantomZSliceMerged.hh"
0058
0059 #include "G4ios.hh"
0060 #include "globals.hh"
0061
0062 #include <cctype>
0063 #include <cstring>
0064 #include <fstream>
0065
0066
0067
0068 DicomHandler* DicomHandler::fInstance = 0;
0069
0070
0071
0072 DicomHandler* DicomHandler::Instance()
0073 {
0074 if (fInstance == 0) {
0075 static DicomHandler dicomhandler;
0076 fInstance = &dicomhandler;
0077 }
0078 return fInstance;
0079 }
0080
0081
0082
0083 G4String DicomHandler::GetDicomDataPath()
0084 {
0085
0086 G4String driverPath = ".";
0087
0088 const char* path = std::getenv("DICOM_PATH");
0089
0090 if (path) {
0091
0092 return G4String(path);
0093 }
0094 else {
0095
0096 #ifdef DICOM_USE_HEAD
0097 G4cerr << "Warning! DICOM was compiled with DICOM_USE_HEAD option but "
0098 << "the DICOM_PATH was not set!" << G4endl;
0099 G4String datadir = G4GetEnv<G4String>("G4ENSDFSTATEDATA", "");
0100 if (datadir.length() > 0) {
0101 auto _last = datadir.rfind("/");
0102 if (_last != std::string::npos) datadir.erase(_last);
0103 driverPath = datadir + "/DICOM1.1/DICOM_HEAD_TEST";
0104 G4int rc = setenv("DICOM_PATH", driverPath.c_str(), 0);
0105 G4cerr << "\t --> Using '" << driverPath << "'..." << G4endl;
0106 G4ConsumeParameters(rc);
0107 }
0108 #endif
0109 }
0110 return driverPath;
0111 }
0112
0113
0114
0115 G4String DicomHandler::GetDicomDataFile()
0116 {
0117 #if defined(DICOM_USE_HEAD) && defined(G4_DCMTK)
0118 return GetDicomDataPath() + "/Data.dat.new";
0119 #else
0120 return GetDicomDataPath() + "/Data.dat";
0121 #endif
0122 }
0123
0124
0125
0126 #ifdef DICOM_USE_HEAD
0127 DicomHandler::DicomHandler()
0128 : DATABUFFSIZE(8192),
0129 LINEBUFFSIZE(5020),
0130 FILENAMESIZE(512),
0131 fCompression(0),
0132 fNFiles(0),
0133 fRows(0),
0134 fColumns(0),
0135 fBitAllocated(0),
0136 fMaxPixelValue(0),
0137 fMinPixelValue(0),
0138 fPixelSpacingX(0.),
0139 fPixelSpacingY(0.),
0140 fSliceThickness(0.),
0141 fSliceLocation(0.),
0142 fRescaleIntercept(0),
0143 fRescaleSlope(0),
0144 fLittleEndian(true),
0145 fImplicitEndian(false),
0146 fPixelRepresentation(0),
0147 fNbrequali(0),
0148 fValueDensity(NULL),
0149 fValueCT(NULL),
0150 fReadCalibration(false),
0151 fMergedSlices(NULL),
0152 fCt2DensityFile("null.dat")
0153 {
0154 fMergedSlices = new DicomPhantomZSliceMerged;
0155 fDriverFile = GetDicomDataFile();
0156 G4cout << "Reading the DICOM_HEAD project " << fDriverFile << G4endl;
0157 }
0158 #else
0159 DicomHandler::DicomHandler()
0160 : DATABUFFSIZE(8192),
0161 LINEBUFFSIZE(5020),
0162 FILENAMESIZE(512),
0163 fCompression(0),
0164 fNFiles(0),
0165 fRows(0),
0166 fColumns(0),
0167 fBitAllocated(0),
0168 fMaxPixelValue(0),
0169 fMinPixelValue(0),
0170 fPixelSpacingX(0.),
0171 fPixelSpacingY(0.),
0172 fSliceThickness(0.),
0173 fSliceLocation(0.),
0174 fRescaleIntercept(0),
0175 fRescaleSlope(0),
0176 fLittleEndian(true),
0177 fImplicitEndian(false),
0178 fPixelRepresentation(0),
0179 fNbrequali(0),
0180 fValueDensity(NULL),
0181 fValueCT(NULL),
0182 fReadCalibration(false),
0183 fMergedSlices(NULL),
0184 fDriverFile("Data.dat"),
0185 fCt2DensityFile("CT2Density.dat")
0186 {
0187 fMergedSlices = new DicomPhantomZSliceMerged;
0188 }
0189 #endif
0190
0191
0192 DicomHandler::~DicomHandler() {}
0193
0194
0195
0196 G4int DicomHandler::ReadFile(FILE* dicom, char* filename2)
0197 {
0198 G4cout << " ReadFile " << filename2 << G4endl;
0199
0200 G4int returnvalue = 0;
0201 size_t rflag = 0;
0202 char* buffer = new char[LINEBUFFSIZE];
0203
0204 fImplicitEndian = false;
0205 fLittleEndian = true;
0206
0207 rflag = std::fread(buffer, 1, 128, dicom);
0208
0209
0210 rflag = std::fread(buffer, 1, 4, dicom);
0211
0212 if (std::strncmp("DICM", buffer, 4) != 0) {
0213 std::fseek(dicom, 0, SEEK_SET);
0214 fImplicitEndian = true;
0215 }
0216
0217 short readGroupId;
0218 short readElementId;
0219 short elementLength2;
0220
0221
0222 unsigned long elementLength4;
0223
0224 char* data = new char[DATABUFFSIZE];
0225
0226
0227 while (true) {
0228
0229 readGroupId = 0;
0230 readElementId = 0;
0231
0232 rflag = std::fread(buffer, 2, 1, dicom);
0233 GetValue(buffer, readGroupId);
0234
0235 rflag = std::fread(buffer, 2, 1, dicom);
0236 GetValue(buffer, readElementId);
0237
0238
0239 G4int tagDictionary = readGroupId * 0x10000 + readElementId;
0240
0241
0242 if (tagDictionary == 0x7FE00010) {
0243
0244
0245 if (!fImplicitEndian) rflag = std::fread(buffer, 2, 1, dicom);
0246
0247 rflag = std::fread(buffer, 4, 1, dicom);
0248
0249 break;
0250 }
0251
0252
0253 rflag = std::fread(buffer, 2, 1, dicom);
0254 GetValue(buffer, elementLength2);
0255
0256
0257
0258 if ((elementLength2 == 0x424f ||
0259 elementLength2 == 0x574f ||
0260 elementLength2 == 0x464f ||
0261 elementLength2 == 0x5455 ||
0262 elementLength2 == 0x5153 ||
0263 elementLength2 == 0x4e55)
0264 &&
0265 !fImplicitEndian)
0266 {
0267
0268 rflag = std::fread(buffer, 2, 1, dicom);
0269
0270
0271 rflag = std::fread(buffer, 4, 1, dicom);
0272 GetValue(buffer, elementLength4);
0273
0274 if (elementLength2 == 0x5153) {
0275 if (elementLength4 == 0xFFFFFFFF) {
0276 read_undefined_nested(dicom);
0277 elementLength4 = 0;
0278 }
0279 else {
0280 if (read_defined_nested(dicom, elementLength4) == 0) {
0281 G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException,
0282 "Function read_defined_nested() failed!");
0283 }
0284 }
0285 }
0286 else {
0287
0288 rflag = std::fread(data, elementLength4, 1, dicom);
0289 }
0290 }
0291 else {
0292
0293 if (!fImplicitEndian || readGroupId == 2) {
0294
0295
0296 rflag = std::fread(buffer, 2, 1, dicom);
0297 GetValue(buffer, elementLength2);
0298 elementLength4 = elementLength2;
0299
0300 rflag = std::fread(data, elementLength4, 1, dicom);
0301 }
0302 else {
0303
0304
0305
0306
0307 if (std::fseek(dicom, -2, SEEK_CUR) != 0) {
0308 G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException, "fseek failed");
0309 }
0310
0311 rflag = std::fread(buffer, 4, 1, dicom);
0312 GetValue(buffer, elementLength4);
0313
0314
0315
0316 if (elementLength4 == 0xFFFFFFFF) {
0317 read_undefined_nested(dicom);
0318 elementLength4 = 0;
0319 }
0320 else {
0321 rflag = std::fread(data, elementLength4, 1, dicom);
0322 }
0323 }
0324 }
0325
0326
0327 data[elementLength4] = '\0';
0328
0329
0330 GetInformation(tagDictionary, data);
0331 }
0332
0333 G4String fnameG4DCM = G4String(filename2) + ".g4dcm";
0334
0335
0336 DicomPhantomZSliceHeader* zslice = new DicomPhantomZSliceHeader(fnameG4DCM);
0337 for (auto ite = fMaterialIndices.cbegin(); ite != fMaterialIndices.cend(); ++ite) {
0338 zslice->AddMaterial(ite->second);
0339 }
0340
0341 zslice->SetNoVoxelsX(fColumns / fCompression);
0342 zslice->SetNoVoxelsY(fRows / fCompression);
0343 zslice->SetNoVoxelsZ(1);
0344
0345 zslice->SetMinX(-fPixelSpacingX * fColumns / 2.);
0346 zslice->SetMaxX(fPixelSpacingX * fColumns / 2.);
0347
0348 zslice->SetMinY(-fPixelSpacingY * fRows / 2.);
0349 zslice->SetMaxY(fPixelSpacingY * fRows / 2.);
0350
0351 zslice->SetMinZ(fSliceLocation - fSliceThickness / 2.);
0352 zslice->SetMaxZ(fSliceLocation + fSliceThickness / 2.);
0353
0354
0355
0356 ReadData(dicom, filename2);
0357
0358
0359
0360
0361
0362 StoreData(zslice);
0363
0364
0365
0366
0367 fMergedSlices->AddZSlice(zslice);
0368
0369
0370 delete[] buffer;
0371 delete[] data;
0372
0373 if (rflag) return returnvalue;
0374 return returnvalue;
0375 }
0376
0377
0378
0379 void DicomHandler::GetInformation(G4int& tagDictionary, char* data)
0380 {
0381 if (tagDictionary == 0x00280010) {
0382 GetValue(data, fRows);
0383 std::printf("[0x00280010] Rows -> %i\n", fRows);
0384 }
0385 else if (tagDictionary == 0x00280011) {
0386 GetValue(data, fColumns);
0387 std::printf("[0x00280011] Columns -> %i\n", fColumns);
0388 }
0389 else if (tagDictionary == 0x00280102) {
0390 short highBits;
0391 GetValue(data, highBits);
0392 std::printf("[0x00280102] High bits -> %i\n", highBits);
0393 }
0394 else if (tagDictionary == 0x00280100) {
0395 GetValue(data, fBitAllocated);
0396 std::printf("[0x00280100] Bits allocated -> %i\n", fBitAllocated);
0397 }
0398 else if (tagDictionary == 0x00280101) {
0399 short bitStored;
0400 GetValue(data, bitStored);
0401 std::printf("[0x00280101] Bits stored -> %i\n", bitStored);
0402 }
0403 else if (tagDictionary == 0x00280106) {
0404 GetValue(data, fMinPixelValue);
0405 std::printf("[0x00280106] Min. pixel value -> %i\n", fMinPixelValue);
0406 }
0407 else if (tagDictionary == 0x00280107) {
0408 GetValue(data, fMaxPixelValue);
0409 std::printf("[0x00280107] Max. pixel value -> %i\n", fMaxPixelValue);
0410 }
0411 else if (tagDictionary == 0x00281053) {
0412 fRescaleSlope = atoi(data);
0413 std::printf("[0x00281053] Rescale Slope -> %d\n", fRescaleSlope);
0414 }
0415 else if (tagDictionary == 0x00281052) {
0416 fRescaleIntercept = atoi(data);
0417 std::printf("[0x00281052] Rescale Intercept -> %d\n", fRescaleIntercept);
0418 }
0419 else if (tagDictionary == 0x00280103) {
0420
0421 fPixelRepresentation = atoi(data);
0422 std::printf("[0x00280103] Pixel Representation -> %i\n", fPixelRepresentation);
0423 if (fPixelRepresentation == 1) {
0424 std::printf("### PIXEL REPRESENTATION = 1, BITS ARE SIGNED, ");
0425 std::printf("DICOM READING SCAN FOR UNSIGNED VALUE, POSSIBLE ");
0426 std::printf("ERROR !!!!!! -> \n");
0427 }
0428 }
0429 else if (tagDictionary == 0x00080006) {
0430 std::printf("[0x00080006] Modality -> %s\n", data);
0431 }
0432 else if (tagDictionary == 0x00080070) {
0433 std::printf("[0x00080070] Manufacturer -> %s\n", data);
0434 }
0435 else if (tagDictionary == 0x00080080) {
0436 std::printf("[0x00080080] Institution Name -> %s\n", data);
0437 }
0438 else if (tagDictionary == 0x00080081) {
0439 std::printf("[0x00080081] Institution Address -> %s\n", data);
0440 }
0441 else if (tagDictionary == 0x00081040) {
0442 std::printf("[0x00081040] Institution Department Name -> %s\n", data);
0443 }
0444 else if (tagDictionary == 0x00081090) {
0445 std::printf("[0x00081090] Manufacturer's Model Name -> %s\n", data);
0446 }
0447 else if (tagDictionary == 0x00181000) {
0448 std::printf("[0x00181000] Device Serial Number -> %s\n", data);
0449 }
0450 else if (tagDictionary == 0x00080008) {
0451 std::printf("[0x00080008] Image Types -> %s\n", data);
0452 }
0453 else if (tagDictionary == 0x00283000) {
0454 std::printf("[0x00283000] Modality LUT Sequence SQ 1 -> %s\n", data);
0455 }
0456 else if (tagDictionary == 0x00283002) {
0457 std::printf("[0x00283002] LUT Descriptor US or SS 3 -> %s\n", data);
0458 }
0459 else if (tagDictionary == 0x00283003) {
0460 std::printf("[0x00283003] LUT Explanation LO 1 -> %s\n", data);
0461 }
0462 else if (tagDictionary == 0x00283004) {
0463 std::printf("[0x00283004] Modality LUT Type LO 1 -> %s\n", data);
0464 }
0465 else if (tagDictionary == 0x00283006) {
0466 std::printf("[0x00283006] LUT Data US or SS -> %s\n", data);
0467 }
0468 else if (tagDictionary == 0x00283010) {
0469 std::printf("[0x00283010] VOI LUT Sequence SQ 1 -> %s\n", data);
0470 }
0471 else if (tagDictionary == 0x00280120) {
0472 std::printf("[0x00280120] Pixel Padding Value US or SS 1 -> %s\n", data);
0473 }
0474 else if (tagDictionary == 0x00280030) {
0475 G4String datas(data);
0476 G4int iss = G4int(datas.find('\\'));
0477 fPixelSpacingX = atof(datas.substr(0, iss).c_str());
0478 fPixelSpacingY = atof(datas.substr(iss + 1, datas.length()).c_str());
0479 }
0480 else if (tagDictionary == 0x00200037) {
0481 std::printf("[0x00200037] Image Orientation (Phantom) -> %s\n", data);
0482 }
0483 else if (tagDictionary == 0x00200032) {
0484 std::printf("[0x00200032] Image Position (Phantom,mm) -> %s\n", data);
0485 }
0486 else if (tagDictionary == 0x00180050) {
0487 fSliceThickness = atof(data);
0488 std::printf("[0x00180050] Slice Thickness (mm) -> %f\n", fSliceThickness);
0489 }
0490 else if (tagDictionary == 0x00201041) {
0491 fSliceLocation = atof(data);
0492 std::printf("[0x00201041] Slice Location -> %f\n", fSliceLocation);
0493 }
0494 else if (tagDictionary == 0x00280004) {
0495
0496 std::printf("[0x00280004] Photometric Interpretation -> %s\n", data);
0497 }
0498 else if (tagDictionary == 0x00020010) {
0499 if (strcmp(data, "1.2.840.10008.1.2") == 0)
0500 fImplicitEndian = true;
0501 else if (strncmp(data, "1.2.840.10008.1.2.2", 19) == 0)
0502 fLittleEndian = false;
0503
0504
0505 std::printf("[0x00020010] Endian -> %s\n", data);
0506 }
0507
0508
0509 else {
0510
0511 ;
0512 }
0513 }
0514
0515
0516
0517 void DicomHandler::StoreData(DicomPhantomZSliceHeader* dcmPZSH)
0518 {
0519 G4int mean;
0520 G4double density;
0521 G4bool overflow = false;
0522
0523 if (!dcmPZSH) {
0524 return;
0525 }
0526
0527 dcmPZSH->SetSliceLocation(fSliceLocation);
0528
0529
0530 if (fCompression == 1) {
0531 for (G4int ww = 0; ww < fRows; ++ww) {
0532 dcmPZSH->AddRow();
0533 for (G4int xx = 0; xx < fColumns; ++xx) {
0534 mean = fTab[ww][xx];
0535 density = Pixel2density(mean);
0536 dcmPZSH->AddValue(density);
0537 dcmPZSH->AddMateID(GetMaterialIndex(G4float(density)));
0538 }
0539 }
0540 }
0541 else {
0542
0543
0544 for (G4int ww = 0; ww < fRows; ww += fCompression) {
0545 dcmPZSH->AddRow();
0546 for (G4int xx = 0; xx < fColumns; xx += fCompression) {
0547 overflow = false;
0548 mean = 0;
0549 for (G4int sumx = 0; sumx < fCompression; ++sumx) {
0550 for (G4int sumy = 0; sumy < fCompression; ++sumy) {
0551 if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0552 mean += fTab[ww + sumy][xx + sumx];
0553 }
0554 if (overflow) break;
0555 }
0556 mean /= fCompression * fCompression;
0557
0558 if (!overflow) {
0559 density = Pixel2density(mean);
0560 dcmPZSH->AddValue(density);
0561 dcmPZSH->AddMateID(GetMaterialIndex(G4float(density)));
0562 }
0563 }
0564 }
0565 }
0566
0567 dcmPZSH->FlipData();
0568 }
0569
0570
0571
0572
0573 void DicomHandler::StoreData(std::ofstream& foutG4DCM)
0574 {
0575 G4int mean;
0576 G4double density;
0577 G4bool overflow = false;
0578
0579
0580 if (fCompression == 1) {
0581 for (G4int ww = 0; ww < fRows; ++ww) {
0582 for (G4int xx = 0; xx < fColumns; ++xx) {
0583 mean = fTab[ww][xx];
0584 density = Pixel2density(mean);
0585 foutG4DCM << GetMaterialIndex(G4float(density)) << " ";
0586 }
0587 foutG4DCM << G4endl;
0588 }
0589 }
0590 else {
0591
0592
0593 for (G4int ww = 0; ww < fRows; ww += fCompression) {
0594 for (G4int xx = 0; xx < fColumns; xx += fCompression) {
0595 overflow = false;
0596 mean = 0;
0597 for (G4int sumx = 0; sumx < fCompression; ++sumx) {
0598 for (G4int sumy = 0; sumy < fCompression; ++sumy) {
0599 if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0600 mean += fTab[ww + sumy][xx + sumx];
0601 }
0602 if (overflow) break;
0603 }
0604 mean /= fCompression * fCompression;
0605
0606 if (!overflow) {
0607 density = Pixel2density(mean);
0608 foutG4DCM << GetMaterialIndex(G4float(density)) << " ";
0609 }
0610 }
0611 foutG4DCM << G4endl;
0612 }
0613 }
0614
0615
0616 if (fCompression == 1) {
0617 for (G4int ww = 0; ww < fRows; ww++) {
0618 for (G4int xx = 0; xx < fColumns; xx++) {
0619 mean = fTab[ww][xx];
0620 density = Pixel2density(mean);
0621 foutG4DCM << density << " ";
0622 if (xx % 8 == 3) foutG4DCM << G4endl;
0623 }
0624 }
0625 }
0626 else {
0627
0628
0629 for (G4int ww = 0; ww < fRows; ww += fCompression) {
0630 for (G4int xx = 0; xx < fColumns; xx += fCompression) {
0631 overflow = false;
0632 mean = 0;
0633 for (G4int sumx = 0; sumx < fCompression; ++sumx) {
0634 for (G4int sumy = 0; sumy < fCompression; ++sumy) {
0635 if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0636 mean += fTab[ww + sumy][xx + sumx];
0637 }
0638 if (overflow) break;
0639 }
0640 mean /= fCompression * fCompression;
0641
0642 if (!overflow) {
0643 density = Pixel2density(mean);
0644 foutG4DCM << density << " ";
0645 if (xx / fCompression % 8 == 3) foutG4DCM << G4endl;
0646
0647 }
0648 }
0649 }
0650 }
0651 }
0652
0653
0654 void DicomHandler::ReadMaterialIndices(std::ifstream& finData)
0655 {
0656 unsigned int nMate;
0657 G4String mateName;
0658 G4float densityMax;
0659 finData >> nMate;
0660 if (finData.eof()) return;
0661
0662 G4cout << " ReadMaterialIndices " << nMate << G4endl;
0663 for (unsigned int ii = 0; ii < nMate; ++ii) {
0664 finData >> mateName >> densityMax;
0665 fMaterialIndices[densityMax] = mateName;
0666
0667
0668 }
0669 }
0670
0671
0672
0673 unsigned int DicomHandler::GetMaterialIndex(G4float density)
0674 {
0675 std::map<G4float, G4String>::const_reverse_iterator ite;
0676 std::size_t ii = fMaterialIndices.size();
0677
0678 for (ite = fMaterialIndices.crbegin(); ite != fMaterialIndices.crend(); ++ite, ii--) {
0679 if (density >= (*ite).first) {
0680 break;
0681 }
0682 }
0683
0684 if (ii == fMaterialIndices.size()) {
0685 ii = fMaterialIndices.size() - 1;
0686 }
0687
0688 return unsigned(ii);
0689 }
0690
0691
0692
0693 G4int DicomHandler::ReadData(FILE* dicom, char* filename2)
0694 {
0695 G4int returnvalue = 0;
0696 size_t rflag = 0;
0697
0698
0699
0700 fTab = new G4int*[fRows];
0701 for (G4int i = 0; i < fRows; ++i) {
0702 fTab[i] = new G4int[fColumns];
0703 }
0704
0705 if (fBitAllocated == 8) {
0706
0707 std::printf("@@@ Error! Picture != 16 bits...\n");
0708 std::printf("@@@ Error! Picture != 16 bits...\n");
0709 std::printf("@@@ Error! Picture != 16 bits...\n");
0710
0711 unsigned char ch = 0;
0712
0713 for (G4int j = 0; j < fRows; ++j) {
0714 for (G4int i = 0; i < fColumns; ++i) {
0715 rflag = std::fread(&ch, 1, 1, dicom);
0716 fTab[j][i] = ch * fRescaleSlope + fRescaleIntercept;
0717 }
0718 }
0719 returnvalue = 1;
0720 }
0721 else {
0722 char sbuff[2];
0723 short pixel;
0724 for (G4int j = 0; j < fRows; ++j) {
0725 for (G4int i = 0; i < fColumns; ++i) {
0726 rflag = std::fread(sbuff, 2, 1, dicom);
0727 GetValue(sbuff, pixel);
0728 fTab[j][i] = pixel * fRescaleSlope + fRescaleIntercept;
0729 }
0730 }
0731 }
0732
0733
0734 G4String nameProcessed = filename2 + G4String(".g4dcmb");
0735 FILE* fileOut = std::fopen(nameProcessed.c_str(), "w+b");
0736
0737 G4cout << "### Writing of " << nameProcessed << " ###\n";
0738
0739 unsigned int nMate = fMaterialIndices.size();
0740 rflag = std::fwrite(&nMate, sizeof(unsigned int), 1, fileOut);
0741
0742 for (auto ite = fMaterialIndices.cbegin(); ite != fMaterialIndices.cend(); ++ite) {
0743 G4String mateName = (*ite).second;
0744 for (std::size_t ii = (*ite).second.length(); ii < 40; ++ii) {
0745 mateName += " ";
0746 }
0747
0748 const char* mateNameC = mateName.c_str();
0749 rflag = std::fwrite(mateNameC, sizeof(char), 40, fileOut);
0750 }
0751
0752 unsigned int fRowsC = fRows / fCompression;
0753 unsigned int fColumnsC = fColumns / fCompression;
0754 unsigned int planesC = 1;
0755 G4float pixelLocationXM = -G4float(fPixelSpacingX * fColumns / 2.);
0756 G4float pixelLocationXP = G4float(fPixelSpacingX * fColumns / 2.);
0757 G4float pixelLocationYM = -G4float(fPixelSpacingY * fRows / 2.);
0758 G4float pixelLocationYP = G4float(fPixelSpacingY * fRows / 2.);
0759 G4float fSliceLocationZM = G4float(fSliceLocation - fSliceThickness / 2.);
0760 G4float fSliceLocationZP = G4float(fSliceLocation + fSliceThickness / 2.);
0761
0762 rflag = std::fwrite(&fRowsC, sizeof(unsigned int), 1, fileOut);
0763 rflag = std::fwrite(&fColumnsC, sizeof(unsigned int), 1, fileOut);
0764 rflag = std::fwrite(&planesC, sizeof(unsigned int), 1, fileOut);
0765
0766 rflag = std::fwrite(&pixelLocationXM, sizeof(G4float), 1, fileOut);
0767 rflag = std::fwrite(&pixelLocationXP, sizeof(G4float), 1, fileOut);
0768 rflag = std::fwrite(&pixelLocationYM, sizeof(G4float), 1, fileOut);
0769 rflag = std::fwrite(&pixelLocationYP, sizeof(G4float), 1, fileOut);
0770 rflag = std::fwrite(&fSliceLocationZM, sizeof(G4float), 1, fileOut);
0771 rflag = std::fwrite(&fSliceLocationZP, sizeof(G4float), 1, fileOut);
0772
0773
0774 std::printf("%8i %8i\n", fRows, fColumns);
0775 std::printf("%8f %8f\n", fPixelSpacingX, fPixelSpacingY);
0776 std::printf("%8f\n", fSliceThickness);
0777 std::printf("%8f\n", fSliceLocation);
0778 std::printf("%8i\n", fCompression);
0779
0780 G4int compSize = fCompression;
0781 G4int mean;
0782 G4float density;
0783 G4bool overflow = false;
0784
0785
0786 if (compSize == 1) {
0787 for (G4int ww = 0; ww < fRows; ++ww) {
0788 for (G4int xx = 0; xx < fColumns; ++xx) {
0789 mean = fTab[ww][xx];
0790 density = Pixel2density(mean);
0791 unsigned int mateID = GetMaterialIndex(density);
0792 rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
0793 }
0794 }
0795 }
0796 else {
0797
0798
0799 for (G4int ww = 0; ww < fRows; ww += compSize) {
0800 for (G4int xx = 0; xx < fColumns; xx += compSize) {
0801 overflow = false;
0802 mean = 0;
0803 for (G4int sumx = 0; sumx < compSize; ++sumx) {
0804 for (G4int sumy = 0; sumy < compSize; ++sumy) {
0805 if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0806 mean += fTab[ww + sumy][xx + sumx];
0807 }
0808 if (overflow) break;
0809 }
0810 mean /= compSize * compSize;
0811
0812 if (!overflow) {
0813 density = Pixel2density(mean);
0814 unsigned int mateID = GetMaterialIndex(density);
0815 rflag = std::fwrite(&mateID, sizeof(unsigned int), 1, fileOut);
0816 }
0817 }
0818 }
0819 }
0820
0821
0822 if (compSize == 1) {
0823 for (G4int ww = 0; ww < fRows; ++ww) {
0824 for (G4int xx = 0; xx < fColumns; ++xx) {
0825 mean = fTab[ww][xx];
0826 density = Pixel2density(mean);
0827 rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
0828 }
0829 }
0830 }
0831 else {
0832
0833
0834 for (G4int ww = 0; ww < fRows; ww += compSize) {
0835 for (G4int xx = 0; xx < fColumns; xx += compSize) {
0836 overflow = false;
0837 mean = 0;
0838 for (G4int sumx = 0; sumx < compSize; ++sumx) {
0839 for (G4int sumy = 0; sumy < compSize; ++sumy) {
0840 if (ww + sumy >= fRows || xx + sumx >= fColumns) overflow = true;
0841 mean += fTab[ww + sumy][xx + sumx];
0842 }
0843 if (overflow) break;
0844 }
0845 mean /= compSize * compSize;
0846
0847 if (!overflow) {
0848 density = Pixel2density(mean);
0849 rflag = std::fwrite(&density, sizeof(G4float), 1, fileOut);
0850 }
0851 }
0852 }
0853 }
0854
0855 rflag = std::fclose(fileOut);
0856
0857 delete[] nameProcessed;
0858
0859
0860
0861
0862
0863
0864
0865 if (rflag) return returnvalue;
0866 return returnvalue;
0867 }
0868
0869
0870
0871
0872
0873 #ifdef DICOM_USE_HEAD
0874 void DicomHandler::ReadCalibration()
0875 {
0876 fNbrequali = 0;
0877 fReadCalibration = false;
0878 G4cout << "No calibration curve for the DICOM HEAD needed!" << G4endl;
0879 }
0880 #else
0881
0882
0883
0884
0885 void DicomHandler::ReadCalibration()
0886 {
0887 fNbrequali = 0;
0888
0889
0890 std::ifstream calibration(fCt2DensityFile.c_str());
0891 calibration >> fNbrequali;
0892 fValueDensity = new G4double[fNbrequali];
0893 fValueCT = new G4double[fNbrequali];
0894
0895 if (!calibration) {
0896 G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException,
0897 "@@@ No value to transform pixels in density!");
0898 }
0899 else {
0900 for (G4int i = 0; i < fNbrequali; ++i) {
0901 calibration >> fValueCT[i] >> fValueDensity[i];
0902 }
0903 }
0904 calibration.close();
0905 fReadCalibration = true;
0906 }
0907 #endif
0908
0909 #ifdef DICOM_USE_HEAD
0910 G4float DicomHandler::Pixel2density(G4int pixel)
0911 {
0912 G4float density = -1;
0913
0914
0915 if (pixel == -998.) density = 0.001290;
0916
0917 else if (pixel == 24.)
0918 density = 1.00;
0919
0920 else if (pixel == 52.)
0921 density = 1.03;
0922
0923 else if (pixel == 92.)
0924 density = 1.10;
0925
0926 else if (pixel == 197.)
0927 density = 1.18;
0928
0929 else if (pixel == 923.)
0930 density = 1.85;
0931
0932 else if (pixel == 1280.)
0933 density = 2.14;
0934
0935 else if (pixel == 2310.)
0936 density = 2.89;
0937
0938 return density;
0939 }
0940
0941 #else
0942
0943
0944 G4float DicomHandler::Pixel2density(G4int pixel)
0945 {
0946 if (!fReadCalibration) {
0947 ReadCalibration();
0948 }
0949
0950 G4float density = -1.;
0951 G4double deltaCT = 0;
0952 G4double deltaDensity = 0;
0953
0954 for (G4int j = 1; j < fNbrequali; ++j) {
0955 if (pixel >= fValueCT[j - 1] && pixel < fValueCT[j]) {
0956 deltaCT = fValueCT[j] - fValueCT[j - 1];
0957 deltaDensity = fValueDensity[j] - fValueDensity[j - 1];
0958
0959
0960 density = G4float(fValueDensity[j] - ((fValueCT[j] - pixel) * deltaDensity / deltaCT));
0961 break;
0962 }
0963 }
0964
0965 if (density < 0.) {
0966 std::printf(
0967 "@@@ Error density = %f && Pixel = %i \
0968 (0x%x) && deltaDensity/deltaCT = %f\n",
0969 density, pixel, pixel, deltaDensity / deltaCT);
0970 }
0971
0972 return density;
0973 }
0974 #endif
0975
0976
0977 void DicomHandler::CheckFileFormat()
0978 {
0979 std::ifstream checkData(fDriverFile.c_str());
0980 char* oneLine = new char[128];
0981
0982 if (!(checkData.is_open())) {
0983
0984 G4String message = "\nDicomG4 needs Data.dat (or another driver file specified";
0985 message += " in command line):\n";
0986 message += "\tFirst line: number of image pixel for a voxel (G4Box)\n";
0987 message += "\tSecond line: number of images (CT slices) to read\n";
0988 message += "\tEach following line contains the name of a Dicom image";
0989 message += " except for the .dcm extension";
0990 G4Exception("DicomHandler::ReadFile", "DICOM001", FatalException, message.c_str());
0991 }
0992
0993 checkData >> fCompression;
0994 checkData >> fNFiles;
0995 G4String oneName;
0996 checkData.getline(oneLine, 100);
0997 std::ifstream testExistence;
0998 G4bool existAlready = true;
0999 for (G4int rep = 0; rep < fNFiles; ++rep) {
1000 checkData.getline(oneLine, 100);
1001 oneName = oneLine;
1002 oneName += ".g4dcm";
1003 G4cout << fNFiles << " test file " << oneName << G4endl;
1004 testExistence.open(oneName.data());
1005 if (!(testExistence.is_open())) {
1006 existAlready = false;
1007 testExistence.clear();
1008 testExistence.close();
1009 }
1010 testExistence.clear();
1011 testExistence.close();
1012 }
1013
1014 ReadMaterialIndices(checkData);
1015
1016 checkData.close();
1017 delete[] oneLine;
1018
1019 if (existAlready == false) {
1020
1021 G4cout << "\nAll the necessary images were not found in processed form "
1022 << ", starting with .dcm images\n";
1023
1024 FILE* dicom;
1025 FILE* lecturePref;
1026 char* fCompressionc = new char[LINEBUFFSIZE];
1027 char* maxc = new char[LINEBUFFSIZE];
1028
1029 char* inputFile = new char[FILENAMESIZE];
1030 G4int rflag;
1031 lecturePref = std::fopen(fDriverFile.c_str(), "r");
1032
1033 rflag = std::fscanf(lecturePref, "%s", fCompressionc);
1034 fCompression = atoi(fCompressionc);
1035 rflag = std::fscanf(lecturePref, "%s", maxc);
1036 fNFiles = atoi(maxc);
1037 G4cout << " fNFiles " << fNFiles << G4endl;
1038
1039
1040
1041 #ifdef DICOM_USE_HEAD
1042 for (G4int i = 1; i <= fNFiles; ++i) {
1043 rflag = std::fscanf(lecturePref, "%s", inputFile);
1044 G4String path = GetDicomDataPath() + "/";
1045
1046 G4String name = inputFile + G4String(".dcm");
1047
1048
1049 G4String name2 = path + name;
1050
1051 G4cout << "### Opening " << name2 << " and reading :\n";
1052 dicom = std::fopen(name2.c_str(), "rb");
1053
1054
1055
1056 if (dicom != 0) {
1057 ReadFile(dicom, inputFile);
1058 }
1059 else {
1060 G4cout << "\nError opening file : " << name2 << G4endl;
1061 }
1062 rflag = std::fclose(dicom);
1063 }
1064 #else
1065
1066 for (G4int i = 1; i <= fNFiles; ++i) {
1067 rflag = std::fscanf(lecturePref, "%s", inputFile);
1068
1069 G4String name = inputFile + G4String(".dcm");
1070
1071
1072
1073
1074 G4cout << "### Opening " << name << " and reading :\n";
1075 dicom = std::fopen(name.c_str(), "rb");
1076
1077
1078
1079 if (dicom != 0) {
1080 ReadFile(dicom, inputFile);
1081 }
1082 else {
1083 G4cout << "\nError opening file : " << name << G4endl;
1084 }
1085 rflag = std::fclose(dicom);
1086 }
1087 #endif
1088
1089 rflag = std::fclose(lecturePref);
1090
1091
1092 fMergedSlices->CheckSlices();
1093
1094 delete[] fCompressionc;
1095 delete[] maxc;
1096 delete[] inputFile;
1097 if (rflag) return;
1098 }
1099
1100 if (fValueDensity) {
1101 delete[] fValueDensity;
1102 }
1103 if (fValueCT) {
1104 delete[] fValueCT;
1105 }
1106 if (fMergedSlices) {
1107 delete fMergedSlices;
1108 }
1109 }
1110
1111
1112
1113 G4int DicomHandler::read_defined_nested(FILE* nested, G4int SQ_Length)
1114 {
1115
1116 unsigned short item_GroupNumber;
1117 unsigned short item_ElementNumber;
1118 G4int item_Length;
1119 G4int items_array_length = 0;
1120 char* buffer = new char[LINEBUFFSIZE];
1121 size_t rflag = 0;
1122
1123 while (items_array_length < SQ_Length) {
1124 rflag = std::fread(buffer, 2, 1, nested);
1125 GetValue(buffer, item_GroupNumber);
1126
1127 rflag = std::fread(buffer, 2, 1, nested);
1128 GetValue(buffer, item_ElementNumber);
1129
1130 rflag = std::fread(buffer, 4, 1, nested);
1131 GetValue(buffer, item_Length);
1132
1133 rflag = std::fread(buffer, item_Length, 1, nested);
1134
1135 items_array_length = items_array_length + 8 + item_Length;
1136 }
1137
1138 delete[] buffer;
1139
1140 if (SQ_Length > items_array_length)
1141 return 0;
1142 else
1143 return 1;
1144 if (rflag) return 1;
1145 }
1146
1147
1148
1149 void DicomHandler::read_undefined_nested(FILE* nested)
1150 {
1151
1152 unsigned short item_GroupNumber;
1153 unsigned short item_ElementNumber;
1154 unsigned int item_Length;
1155 char* buffer = new char[LINEBUFFSIZE];
1156 size_t rflag = 0;
1157
1158 do {
1159 rflag = std::fread(buffer, 2, 1, nested);
1160 GetValue(buffer, item_GroupNumber);
1161
1162 rflag = std::fread(buffer, 2, 1, nested);
1163 GetValue(buffer, item_ElementNumber);
1164
1165 rflag = std::fread(buffer, 4, 1, nested);
1166 GetValue(buffer, item_Length);
1167
1168 if (item_Length != 0xffffffff)
1169 rflag = std::fread(buffer, item_Length, 1, nested);
1170 else
1171 read_undefined_item(nested);
1172
1173 } while (item_GroupNumber != 0xFFFE || item_ElementNumber != 0xE0DD || item_Length != 0);
1174
1175 delete[] buffer;
1176 if (rflag) return;
1177 }
1178
1179
1180
1181 void DicomHandler::read_undefined_item(FILE* nested)
1182 {
1183
1184 unsigned short item_GroupNumber;
1185 unsigned short item_ElementNumber;
1186 G4int item_Length;
1187 size_t rflag = 0;
1188 char* buffer = new char[LINEBUFFSIZE];
1189
1190 do {
1191 rflag = std::fread(buffer, 2, 1, nested);
1192 GetValue(buffer, item_GroupNumber);
1193
1194 rflag = std::fread(buffer, 2, 1, nested);
1195 GetValue(buffer, item_ElementNumber);
1196
1197 rflag = std::fread(buffer, 4, 1, nested);
1198 GetValue(buffer, item_Length);
1199
1200 if (item_Length != 0) rflag = std::fread(buffer, item_Length, 1, nested);
1201
1202 } while (item_GroupNumber != 0xFFFE || item_ElementNumber != 0xE00D || item_Length != 0);
1203
1204 delete[] buffer;
1205 if (rflag) return;
1206 }
1207
1208
1209
1210 template<class Type>
1211 void DicomHandler::GetValue(char* _val, Type& _rval)
1212 {
1213 #if BYTE_ORDER == BIG_ENDIAN
1214 if (fLittleEndian) {
1215 #else
1216 if (!fLittleEndian) {
1217 #endif
1218 const G4int SIZE = sizeof(_rval);
1219 char ctemp;
1220 for (G4int i = 0; i < SIZE / 2; ++i) {
1221 ctemp = _val[i];
1222 _val[i] = _val[SIZE - 1 - i];
1223 _val[SIZE - 1 - i] = ctemp;
1224 }
1225 }
1226 _rval = *(Type*)_val;
1227 }
1228
1229