CASToR
1.0
Tomographic Reconstruction (PET/SPECT)
|
00001 00014 #include "gVariables.hh" 00015 #include "gOptions.hh" 00016 #include "sOutputManager.hh" 00017 #include "oMatrix.hh" 00018 00019 00025 void ShowHelp(int a_returnCode) 00026 { 00027 cout << endl; 00028 cout << "Usage: castor-PetScannerLutEx -alias scanner_name [settings]" << endl; 00029 cout << endl; 00030 00031 cout << "[Input settings]:" << endl; 00032 cout << " -alias scanner_name : give the alias of the scanner for which the LUT will be generated (suggested template Modality-Constructor-Model (ex: PET_GE_DLS)" << endl; 00033 cout << " the resulting file will be written in the scanner repository (default : /config/scanner directory)" << endl; 00034 cout << endl; 00035 00036 Exit(a_returnCode); 00037 } 00038 00039 00040 00045 int main(int argc, char** argv) 00046 { 00047 // No argument, then show help 00048 if (argc==1) ShowHelp(0); 00049 00050 string scanner_name = ""; 00051 string path_to_LUT = ""; 00052 string path_to_headerLUT = ""; 00053 ofstream LUT_file, header_LUT_file; 00054 00055 // ============================================================================================================ 00056 // Read command-line parameters 00057 // ============================================================================================================ 00058 for (int i=1; i<argc; i++) 00059 { 00060 string option = (string)argv[i]; 00061 00062 if (option=="-h" || option=="--help" || option=="-help") ShowHelp(0); 00063 00064 else if (option=="-alias") 00065 { 00066 if (i>=argc-1) 00067 { 00068 cerr << "***** castor-PetScannerLutEx :: Argument missing for option: " << option << endl; 00069 Exit(EXIT_FAILURE); 00070 } 00071 scanner_name = argv[i+1]; 00072 string path_base = sOutputManager::GetInstance()->GetPathToConfigDir(); 00073 00074 path_base.append("scanner"); 00075 path_to_LUT = path_base+OS_SEP; 00076 path_to_headerLUT = path_base+OS_SEP; 00077 path_to_LUT.append(scanner_name.c_str()).append(".lut"); 00078 path_to_headerLUT.append(scanner_name.c_str()).append(".hscan"); 00079 i++; 00080 } 00081 else 00082 { 00083 cerr << "***** castor-PetScannerLutEx :: Unknown option '" << option << "' !" << endl; 00084 Exit(EXIT_FAILURE); 00085 } 00086 } 00087 00088 00089 00090 // ============================================================================================================ 00091 // Checks options have been provided 00092 // ============================================================================================================ 00093 00094 // Checks 00095 // output directory 00096 if (scanner_name.empty() ) 00097 { 00098 cerr << "***** castor-PetScannerLutEx :: Please provide an alias for this scanner !" << endl; 00099 ShowHelp(0); 00100 Exit(EXIT_FAILURE); 00101 } 00102 else 00103 { 00104 cout << endl << "Generating LUT with the following alias: " << scanner_name << "... " << endl << endl; 00105 } 00106 00107 00108 00109 // ============================================================================================================ 00110 // Input parameter declarations 00111 // ============================================================================================================ 00112 int nb_rings; 00113 int nb_elts; 00114 FLTNBLUT min_trs_angle_diff; 00115 string scanner_modality; 00116 string description; 00117 FLTNBLUT angular_span; 00118 00119 int *nb_rsectors_lyr, 00120 *nb_trans_mod_lyr, 00121 *nb_axial_mod_lyr, 00122 *nb_trans_submod_lyr, 00123 *nb_axial_submod_lyr, 00124 *nb_trans_crystal_lyr, 00125 *nb_axial_crystal_lyr, 00126 *nb_crystals_lyr; 00127 00128 FLTNBLUT *radius_lyr, 00129 *gap_trans_mod_lyr, 00130 *gap_axial_mod_lyr, 00131 *gap_trans_submod_lyr, 00132 *gap_axial_submod_lyr, 00133 *gap_trans_crystal_lyr, 00134 *gap_axial_crystal_lyr, 00135 *crystal_size_depth_lyr, 00136 *crystal_size_trans_lyr, 00137 *crystal_size_axial_lyr, 00138 *mean_depth_of_interaction_lyr; 00139 00140 00141 // Layer-dependent variables 00142 int nbLayers = 1; 00143 nb_rsectors_lyr = new int[nbLayers]; 00144 nb_trans_mod_lyr = new int[nbLayers]; 00145 nb_axial_mod_lyr = new int[nbLayers]; 00146 nb_trans_submod_lyr = new int[nbLayers]; 00147 nb_axial_submod_lyr = new int[nbLayers]; 00148 nb_trans_crystal_lyr = new int[nbLayers]; 00149 nb_axial_crystal_lyr = new int[nbLayers]; 00150 nb_crystals_lyr = new int[nbLayers]; 00151 00152 radius_lyr = new FLTNBLUT[nbLayers]; 00153 00154 gap_trans_mod_lyr = new FLTNBLUT[nbLayers]; 00155 gap_axial_mod_lyr = new FLTNBLUT[nbLayers]; 00156 gap_trans_submod_lyr = new FLTNBLUT[nbLayers]; 00157 gap_axial_submod_lyr = new FLTNBLUT[nbLayers]; 00158 gap_trans_crystal_lyr = new FLTNBLUT[nbLayers]; 00159 gap_axial_crystal_lyr = new FLTNBLUT[nbLayers]; 00160 crystal_size_depth_lyr = new FLTNBLUT[nbLayers]; 00161 crystal_size_trans_lyr = new FLTNBLUT[nbLayers]; 00162 crystal_size_axial_lyr = new FLTNBLUT[nbLayers]; 00163 mean_depth_of_interaction_lyr = new FLTNBLUT[nbLayers]; 00164 00165 00166 // Initialize value of each scanner element according to the scanner system 00167 00168 description = "User-made LUT of a GATE model of the GE DRX PET scanner system, generated by the castor-PetScannerLutEx script"; 00169 scanner_modality = "PET"; 00170 00171 // System minimal transaxial angle difference between two scanner elements 00172 // to get a LOR 00173 min_trs_angle_diff = 40.; 00174 00175 // radius in mm (from isocenter to crystal surface) 00176 radius_lyr[0]= 443; 00177 00178 // nb scanner elements 00179 nb_rsectors_lyr[0] = 70; 00180 nb_trans_mod_lyr[0] = 1; 00181 nb_axial_mod_lyr[0] = 4; 00182 nb_trans_submod_lyr[0] = 1; 00183 nb_axial_submod_lyr[0] = 1; 00184 nb_trans_crystal_lyr[0] = 9; 00185 nb_axial_crystal_lyr[0] = 6; 00186 00187 00188 // Gaps between scanner elements 00189 gap_trans_mod_lyr[0] = 0; 00190 gap_axial_mod_lyr[0] = 1.75; 00191 gap_trans_submod_lyr[0] = 0; 00192 gap_axial_submod_lyr[0] = 0; 00193 gap_trans_crystal_lyr[0] = 0.065; 00194 gap_axial_crystal_lyr[0] = 0.1; 00195 00196 // crystal dimensions (mm) 00197 crystal_size_depth_lyr[0] = 30; 00198 crystal_size_trans_lyr[0] = 4.230; 00199 crystal_size_axial_lyr[0] = 6.350; 00200 00201 // mean depth of interaction in the crystal (mm) 00202 // negative value means no depth of interaction 00203 mean_depth_of_interaction_lyr[0] = -1.; 00204 00205 // angular span in degree = 360 by defaut 00206 // (rsectors will be uniformly positionned according to this value) 00207 angular_span = 360.; 00208 00209 // Default reconstruction parameters for the scanner 00210 int default_dim_trans, default_dim_axial; 00211 default_dim_trans = 256; 00212 default_dim_axial = 47; 00213 00214 // default field of view 00215 FLTNBLUT default_FOV_trans, default_FOV_axial; //mm 00216 default_FOV_trans = 700; 00217 default_FOV_axial = 153.69; 00218 00219 00220 // Z-shifts (rsector axial shift for each module) 00221 00222 // Default initialization 00223 int nb_rsctr_axial_shift = 1; 00224 FLTNBLUT *rsctr_zshift; 00225 rsctr_zshift = new FLTNBLUT[nb_rsctr_axial_shift]; 00226 00227 // System contains z-shifts) 00228 if(nb_rsctr_axial_shift > 1) 00229 { 00230 for(int zs=0 ; zs<nb_rsctr_axial_shift ; zs++) 00231 rsctr_zshift[zs] = 0.; // Add specific z-shift values for each layer 00232 } 00233 // No z-shift, default initialization 00234 else 00235 rsctr_zshift[0] = 0.; 00236 00237 00238 // Compute the total number of elements 00239 nb_elts = 0; 00240 for(int lyr=0 ; lyr<nbLayers ; lyr++) 00241 nb_elts += nb_rsectors_lyr[lyr] * nb_trans_mod_lyr[lyr] * nb_axial_mod_lyr[lyr] 00242 * nb_trans_submod_lyr[lyr] * nb_axial_submod_lyr[lyr] 00243 * nb_trans_crystal_lyr[lyr] * nb_axial_crystal_lyr[lyr]; 00244 00245 // Cumulative number of crystal (in order to keep track of crystal index if nb_layer>1) 00246 uint32_t nb_cry_cur = 0; 00247 00248 // Number of crystal in this layer 00249 uint32_t nb_cry_in_layer = 0; 00250 00251 // Loop on layers. 00252 // Write the crytal LUT elements successively for each layer 00253 for(int lyr=0 ; lyr<nbLayers ; lyr++) 00254 { 00255 // Default position for the first rsector in CASToR is directly above isocenter 00256 // The gate model of this scanner locates the first rsector on the right side of the scanner 00257 // This variable allows to provides the position of the first rsector in comparison with 00258 // CASToR convention 00259 // This is required to recover angular orientations of the crystals 00260 FLTNBLUT rsector_first_angle = 90; 00261 00262 int nb_rsectors = nb_rsectors_lyr[lyr], 00263 nb_trans_mod = nb_trans_mod_lyr[lyr], 00264 nb_axial_mod = nb_axial_mod_lyr[lyr], 00265 nb_trans_submod = nb_trans_submod_lyr[lyr], 00266 nb_axial_submod = nb_axial_submod_lyr[lyr], 00267 nb_trans_crystal = nb_trans_crystal_lyr[lyr], 00268 nb_axial_crystal = nb_axial_crystal_lyr[lyr]; 00269 00270 FLTNBLUT radius = radius_lyr[lyr], 00271 gap_trans_mod = gap_trans_mod_lyr[lyr], 00272 gap_axial_mod = gap_axial_mod_lyr[lyr], 00273 gap_trans_submod = gap_trans_submod_lyr[lyr], 00274 gap_axial_submod = gap_axial_submod_lyr[lyr], 00275 gap_trans_crystal = gap_trans_crystal_lyr[lyr], 00276 gap_axial_crystal = gap_axial_crystal_lyr[lyr], 00277 crystal_size_trans = crystal_size_trans_lyr[lyr], 00278 crystal_size_axial = crystal_size_axial_lyr[lyr], 00279 crystal_size_depth = crystal_size_depth_lyr[lyr]; 00280 00281 // Compute system element sizes 00282 FLTNBLUT size_trans_submod = nb_trans_crystal*crystal_size_trans + (nb_trans_crystal-1)*gap_trans_crystal; 00283 FLTNBLUT size_axial_submod = nb_axial_crystal*crystal_size_axial + (nb_axial_crystal-1)*gap_axial_crystal; 00284 FLTNBLUT size_trans_mod = nb_trans_submod*size_trans_submod + (nb_trans_submod-1)*gap_trans_submod; 00285 FLTNBLUT size_axial_mod = nb_axial_submod*size_axial_submod + (nb_axial_submod-1)*gap_axial_submod; 00286 00287 int nb_mod = nb_axial_mod*nb_trans_mod; 00288 int nb_submod = nb_axial_submod*nb_trans_submod; 00289 int nb_crystal = nb_trans_crystal*nb_axial_crystal; 00290 00291 nb_cry_in_layer = nb_rsectors 00292 * nb_mod 00293 * nb_submod 00294 * nb_crystal; 00295 00296 nb_crystals_lyr[lyr] = nb_cry_in_layer; 00297 00298 nb_rings = nb_rsectors 00299 * nb_trans_mod 00300 * nb_trans_submod 00301 * nb_trans_crystal; 00302 00303 int number_crystals_in_ring = nb_crystals_lyr[lyr]/nb_rings; 00304 00305 // Variables gathering the LUT elements 00306 FLTNBLUT* crystal_positionX = new FLTNBLUT[ nb_crystals_lyr[lyr] ]; 00307 FLTNBLUT* crystal_positionY = new FLTNBLUT[ nb_crystals_lyr[lyr] ]; 00308 FLTNBLUT* crystal_positionZ = new FLTNBLUT[ nb_crystals_lyr[lyr] ]; 00309 FLTNBLUT* crystal_orientationX = new FLTNBLUT[ nb_crystals_lyr[lyr] ]; 00310 FLTNBLUT* crystal_orientationY = new FLTNBLUT[ nb_crystals_lyr[lyr] ]; 00311 FLTNBLUT* crystal_orientationZ = new FLTNBLUT[ nb_crystals_lyr[lyr] ]; 00312 00313 00314 // ============================================================================================================ 00315 // Main part of the program: Generate the LUT 00316 // ============================================================================================================ 00317 00318 // Loop to nb_rsectors+1. crystal_center[0] will be used to gather position of the reference rsector (directly above isocenter) 00319 oMatrix *****crystal_center = new oMatrix ****[nb_rsectors]; 00320 00321 for(int i = 0; i < nb_rsectors+1 ; i++) 00322 { 00323 crystal_center[i] = new oMatrix ***[nb_axial_mod*nb_trans_mod]; 00324 00325 for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++) 00326 { 00327 crystal_center[i][j] = new oMatrix **[nb_axial_submod*nb_trans_submod]; 00328 00329 for (int k = 0; k<nb_axial_submod*nb_trans_submod; k++) 00330 { 00331 crystal_center[i][j][k] = new oMatrix*[nb_axial_crystal*nb_trans_crystal]; 00332 00333 for (int l = 0; l<nb_axial_crystal*nb_trans_crystal; l++) 00334 crystal_center[i][j][k][l] = new oMatrix(3,1); 00335 } 00336 } 00337 } 00338 00339 00340 // ============================================================================================================ 00341 // Generation of the rotation matrix allowing to compute the position of all the rsectors. 00342 // ============================================================================================================ 00343 oMatrix** rotation_mtx = new oMatrix*[nb_rsectors]; 00344 00345 for(int i=0; i<nb_rsectors; i++) 00346 rotation_mtx[i] = new oMatrix(3,3); 00347 00348 FLTNBLUT angular_span_rad = angular_span*M_PI/180.; 00349 for (int i = 0; i<nb_rsectors; i++) 00350 { 00351 FLTNBLUT angle = remainderf((FLTNB)i*angular_span_rad/((FLTNB)nb_rsectors), 2.*M_PI); 00352 00353 rotation_mtx[i]->SetMatriceElt(0,0,cos(angle) ); 00354 rotation_mtx[i]->SetMatriceElt(1,0,-sin(angle) ); 00355 rotation_mtx[i]->SetMatriceElt(2,0,0); 00356 rotation_mtx[i]->SetMatriceElt(0,1,sin(angle) ); 00357 rotation_mtx[i]->SetMatriceElt(1,1,cos(angle) ); 00358 rotation_mtx[i]->SetMatriceElt(2,1,0); 00359 rotation_mtx[i]->SetMatriceElt(0,2,0); 00360 rotation_mtx[i]->SetMatriceElt(1,2,0); 00361 rotation_mtx[i]->SetMatriceElt(2,2,1); 00362 } 00363 00364 00365 00366 // ============================================================================================================ 00367 // Compute scanner elements positions for the first rsector 00368 // (For the example scanner, it is located and centered on the right side of isocenter in the GATE model 00369 // ============================================================================================================ 00370 00371 for (int i=0; i < nb_mod ; i++) 00372 { 00373 // Define the transaxial and axial edge start positions for the rsector 00374 FLTNBLUT y_start_m = (nb_trans_mod*size_trans_mod + (nb_trans_mod-1)*gap_trans_mod) / 2; 00375 FLTNBLUT z_start_m = -(nb_axial_mod*size_axial_mod + (nb_axial_mod-1)*gap_axial_mod) / 2 ; 00376 00377 // Define the transaxial and axial edge start positions for the i-Module in the rsector. 00378 // Enumeration starting with the transaxial modules. 00379 y_start_m -= (i%nb_trans_mod) * (size_trans_mod + gap_trans_mod); 00380 z_start_m += int(i/nb_trans_mod) * (size_axial_mod + gap_axial_mod); 00381 00382 for (int j=0 ; j < nb_submod ; j++) 00383 { 00384 FLTNBLUT y_start_sm = y_start_m; 00385 FLTNBLUT z_start_sm = z_start_m; 00386 00387 y_start_sm -= (j%nb_trans_submod) * (size_trans_submod + gap_trans_submod); 00388 z_start_sm += int(j/nb_trans_submod) * (size_axial_submod + gap_axial_submod); 00389 00390 for (int k=0 ; k < nb_crystal ; k++) 00391 { 00392 // Define the transaxial and axial center positions for the j-SubModule (crystal) i-Module of the rsector. 00393 // Enumeration starting with the transaxial submodules. 00394 FLTNBLUT Xcrist = radius + crystal_size_depth/2; 00395 FLTNBLUT Ycrist = y_start_sm - (k%nb_trans_crystal) * (crystal_size_trans + gap_trans_crystal) - crystal_size_trans/2; 00396 FLTNBLUT Zcrist = z_start_sm + int(k/nb_trans_crystal) * (crystal_size_axial + gap_axial_crystal) + crystal_size_axial/2; 00397 00398 crystal_center[0][i][j][k]->SetMatriceElt(0,0,Xcrist); 00399 crystal_center[0][i][j][k]->SetMatriceElt(1,0,Ycrist); 00400 crystal_center[0][i][j][k]->SetMatriceElt(2,0,Zcrist); 00401 } 00402 } 00403 } 00404 00405 00406 // ============================================================================================================ 00407 // Loop over all the other rsectors. 00408 // Mandatory informations about crystals are recovered in : 00409 // crystal_position(X,Y,Z) : Cartesian positions of the center of the crystals 00410 // crystal_orientation(X,Y,Z) : Vector orientation recovering crystal angles 00411 // (usually identical for all crystals inside the same rsector) 00412 // ============================================================================================================ 00413 00414 for (int rs=0 ; rs<nb_rsectors ; rs++) 00415 { 00416 00417 // Compute angle for orientation vector for this rsector 00418 FLTNBLUT rsector_first_angle_rad = rsector_first_angle*M_PI/180.; 00419 FLTNBLUT orientation_angle = remainderf(rsector_first_angle_rad + (FLTNB)rs*angular_span_rad/((FLTNB)nb_rsectors), 2.*M_PI); 00420 00421 for (int j=0 ; j<nb_mod ; j++) 00422 for (int k=0 ; k<nb_submod ; k++) 00423 for (int l=0 ; l<nb_crystal ; l++) 00424 { 00425 // crystal indexation 00426 int cryID = int(j/nb_trans_mod)*nb_axial_submod*nb_axial_crystal*number_crystals_in_ring // = nb indexed crystals in the rings covered by the previous (axial) modules 00427 + int(k/nb_trans_submod)*nb_axial_crystal*number_crystals_in_ring // = nb indexed crystals in the rings covered by the previous (axial) submodules 00428 + int(l/nb_trans_crystal)*number_crystals_in_ring // = nb indexed crystals in the rings covered by the previous (axial) crystals 00429 + rs*nb_trans_mod*nb_trans_submod*nb_trans_crystal // = nb indexed crystals in the previous rsectors 00430 + j/nb_axial_mod*nb_trans_submod*nb_trans_crystal // = nb indexed crystals in the previous modules 00431 + k/nb_axial_submod*nb_trans_crystal // = nb indexed crystals in the previous submodules 00432 + l%nb_trans_crystal // previous crystals in the submodule 00433 + nb_cry_cur; // = number of crystals already indexed if lyr>0 00434 00435 rotation_mtx[rs]->Multiplication(crystal_center[0][j][k][l], crystal_center[rs+1][j][k][l]); 00436 crystal_positionX[cryID] = crystal_center[rs+1][j][k][l]->GetMatriceElt(0,0); 00437 crystal_positionY[cryID] = crystal_center[rs+1][j][k][l]->GetMatriceElt(1,0); 00438 crystal_positionZ[cryID] = crystal_center[rs+1][j][k][l]->GetMatriceElt(2,0); 00439 crystal_positionZ[cryID] += rsctr_zshift[rs%nb_rsctr_axial_shift]; 00440 00441 crystal_orientationX[cryID] = cos(orientation_angle); 00442 crystal_orientationY[cryID] = sin(orientation_angle); 00443 crystal_orientationZ[cryID] = 0; 00444 } 00445 } 00446 00447 // Update nb of crystal for systems with (required if nb_layers>1) 00448 nb_cry_cur += nb_crystals_lyr[lyr]; 00449 00450 // ============================================================================================================ 00451 // Write the binary LUT file (append if nb_layers > 1) 00452 // ============================================================================================================ 00453 00454 cout << ">>> Start writing binary LUT file for layer #" << lyr << "..." << endl; 00455 // Write binary file, overwrite mode 00456 if(lyr == 0) 00457 LUT_file.open(path_to_LUT.c_str(), ios::binary | ios::out); 00458 // Append otherwise (data for crystals from the next layer) 00459 else 00460 LUT_file.open(path_to_LUT.c_str(), ios::binary | ios::out | ios::app); 00461 00462 00463 // Write the corresponding crystal parameters in the LUT 00464 for(int i=0 ; i<nb_crystals_lyr[lyr] ; i++) 00465 { 00466 LUT_file.write(reinterpret_cast<char*>(&crystal_positionX[i]), sizeof(FLTNBLUT)); 00467 LUT_file.write(reinterpret_cast<char*>(&crystal_positionY[i]), sizeof(FLTNBLUT)); 00468 LUT_file.write(reinterpret_cast<char*>(&crystal_positionZ[i]), sizeof(FLTNBLUT)); 00469 LUT_file.write(reinterpret_cast<char*>(&crystal_orientationX[i]), sizeof(FLTNBLUT)); 00470 LUT_file.write(reinterpret_cast<char*>(&crystal_orientationY[i]), sizeof(FLTNBLUT)); 00471 LUT_file.write(reinterpret_cast<char*>(&crystal_orientationZ[i]), sizeof(FLTNBLUT)); 00472 } 00473 00474 LUT_file.close(); 00475 cout << ">>> Binary LUT writing OK" << endl; 00476 00477 // ============================================================================================================ 00478 // Free memory 00479 // ============================================================================================================ 00480 00481 // Delete objects 00482 00483 for (int i = 0; i < nb_rsectors ; i++) 00484 for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++) 00485 for (int k = 0; k<nb_axial_submod*nb_trans_submod; k++) 00486 for (int l = 0; l<nb_axial_crystal*nb_trans_crystal; l++) 00487 delete crystal_center[i][j][k][l]; 00488 00489 for(int i = 0; i < nb_rsectors ; i++) 00490 for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++) 00491 for (int k = 0; k<nb_axial_submod*nb_trans_submod; k++) 00492 delete[] crystal_center[i][j][k]; 00493 00494 for(int i = 0; i < nb_rsectors ; i++) 00495 for (int j = 0; j<nb_axial_mod*nb_trans_mod; j++) 00496 delete[] crystal_center[i][j]; 00497 00498 for(int i = 0; i < nb_rsectors ; i++) 00499 { 00500 delete[] crystal_center[i]; 00501 delete rotation_mtx[i]; 00502 } 00503 00504 delete[] crystal_center; 00505 delete[] rotation_mtx; 00506 delete crystal_positionX; 00507 delete crystal_positionY; 00508 delete crystal_positionZ; 00509 delete crystal_orientationX; 00510 delete crystal_orientationY; 00511 delete crystal_orientationZ; 00512 00513 } // end of loop on layers 00514 00515 00516 // ============================================================================================================ 00517 // Write header file 00518 // ============================================================================================================ 00519 00520 cout << ">>> Start writing header LUT file..." << endl; 00521 header_LUT_file.open(path_to_headerLUT.c_str(), ios::out); 00522 00523 header_LUT_file << "scanner name:" << " " << scanner_name << endl; 00524 header_LUT_file << "modality:" << " " << scanner_modality << endl; 00525 00526 header_LUT_file << "scanner radius:" << " " << radius_lyr[0]; 00527 for (int lyr=1 ; lyr<nbLayers ; lyr++) 00528 header_LUT_file << "," << radius_lyr[lyr] ; header_LUT_file << endl; 00529 00530 header_LUT_file << "number of rings in scanner:" << " " << nb_rings << endl; 00531 header_LUT_file << "number of elements:" << " " << nb_elts << endl; 00532 header_LUT_file << "number of layers:" << " " << nbLayers << endl; 00533 header_LUT_file << "number of crystals in layer(s):" << " " << nb_crystals_lyr[0]; 00534 for (int lyr=1 ; lyr<nbLayers ; lyr++) 00535 header_LUT_file << ","<< nb_crystals_lyr[lyr] ; header_LUT_file << endl; 00536 00537 header_LUT_file << "crystals size depth:" << " " << crystal_size_depth_lyr[0]; 00538 for (int lyr=1 ; lyr<nbLayers ; lyr++) 00539 header_LUT_file << ","<< crystal_size_depth_lyr[lyr] ; header_LUT_file << endl; 00540 00541 header_LUT_file << "crystals size transaxial:" << " " << crystal_size_trans_lyr[0]; 00542 for (int lyr=1 ; lyr<nbLayers ; lyr++) 00543 header_LUT_file << ","<< crystal_size_trans_lyr[lyr] ; header_LUT_file << endl; 00544 00545 header_LUT_file << "crystals size axial:" << " " << crystal_size_axial_lyr[0]; 00546 for (int lyr=1 ; lyr<nbLayers ; lyr++) 00547 header_LUT_file << ","<< crystal_size_axial_lyr[lyr] ; header_LUT_file << endl; 00548 00549 00550 //default reconstruction parameters 00551 header_LUT_file << "voxels number transaxial:" << " " << default_dim_trans << endl; 00552 header_LUT_file << "voxels number axial:" << " " << default_dim_axial << endl; 00553 00554 header_LUT_file << "field of view transaxial:" << " " << default_FOV_trans << endl; 00555 header_LUT_file << "field of view axial:" << " " << default_FOV_axial << endl; 00556 00557 header_LUT_file << "min angle difference:" << " " << min_trs_angle_diff << " #deg" << endl; 00558 00559 header_LUT_file << "mean depth of interaction:" << " " << mean_depth_of_interaction_lyr[0]; 00560 for (int lyr=1 ; lyr<nbLayers ; lyr++) 00561 header_LUT_file << ","<< mean_depth_of_interaction_lyr[lyr] ; 00562 header_LUT_file << " #optional (default value : center of crystal ). Input value must correspond to the distance from the crystal surface, or negative value if default" << endl; 00563 00564 header_LUT_file << "description:" << " " << description << endl; 00565 00566 cout << ">>> Header LUT file writing OK" << endl; 00567 00568 // Free memory 00569 delete rsctr_zshift; 00570 delete nb_rsectors_lyr; 00571 delete nb_trans_mod_lyr; 00572 delete nb_axial_mod_lyr; 00573 delete nb_trans_submod_lyr; 00574 delete nb_axial_submod_lyr; 00575 delete nb_trans_crystal_lyr; 00576 delete nb_axial_crystal_lyr; 00577 00578 delete radius_lyr; 00579 delete gap_trans_mod_lyr; 00580 delete gap_axial_mod_lyr; 00581 delete gap_trans_submod_lyr; 00582 delete gap_axial_submod_lyr; 00583 delete gap_trans_crystal_lyr; 00584 delete gap_axial_crystal_lyr; 00585 delete crystal_size_depth_lyr; 00586 delete crystal_size_trans_lyr; 00587 delete crystal_size_axial_lyr; 00588 00589 cout << "Binary file has been created in: " << path_to_LUT << endl; 00590 cout << "Header file has been created in: " << path_to_headerLUT << endl << endl; 00591 cout << "End of LUT generation" << endl << endl; 00592 00593 return EXIT_SUCCESS; 00594 } 00595