![]() |
CASToR
1.0
Tomographic Reconstruction (PET/SPECT)
|
00001 00013 #include "gVariables.hh" 00014 #include "gOptions.hh" 00015 #include "oIterativeAlgorithm.hh" 00016 #include "oSensitivityGenerator.hh" 00017 #include "oImageDimensionsAndQuantification.hh" 00018 #include "iDataFilePET.hh" 00019 #include "iDataFileSPECT.hh" 00020 #include "sOutputManager.hh" 00021 #include "sScannerManager.hh" 00022 #include "sRNG.hh" 00023 #include "iScannerPET.hh" 00024 #include "sAddonManager.hh" 00025 00026 // ============================================================================================================================================= 00027 // ============================================================================================================================================= 00028 // ============================================================================================================================================= 00029 // H E L P F U N C T I O N S 00030 // ============================================================================================================================================= 00031 // ============================================================================================================================================= 00032 // ============================================================================================================================================= 00033 00034 00039 void ShowHelp() 00040 { 00041 // Return when using MPI and mpi_rank is not 0 00042 #ifdef CASTOR_MPI 00043 int mpi_rank = 0; 00044 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00045 if (mpi_rank!=0) return; 00046 #endif 00047 // Show help 00048 cout << endl; 00049 cout << "Usage: castor-recon.exe -df file.cdh -(f/d)out output -it iter [settings]" << endl; 00050 cout << endl; 00051 cout << "[Main options]:" << endl; 00052 // cout << " -df file.cdh : Give an input CASTOR datafile (no default). Can use this option multiple times to specify multiple bed positions." << endl; 00053 cout << " -df file.cdh : Give an input CASTOR datafile (no default)." << endl; 00054 cout << " -fout name : Give the root name for all output files (no default, alternative to -dout)" << endl; 00055 cout << " -dout name : Give the name of the output directory where all output files will be written (no default, alternative to -fout)" << endl; 00056 cout << " -it list : Give the sequence of iterations:subsets separated by commas (no default)." << endl; 00057 cout << " -dim x,y,z : Give the number of voxels in each dimension (default: those of the scanner)." << endl; 00058 cout << " -fov x,y,z : Give the size of the field-of-view in each dimension, in mm (default: those of the scanner, or calculated from" << endl; 00059 cout << " the voxel sizes provided using '-vox')." << endl; 00060 cout << " -vox x,y,z : Give the size of the voxels in each dimension, in mm (default: those of the scanner, or calculated from the fov" << endl; 00061 cout << " if a fov value is provided using '-fov')." << endl; 00062 cout << " -vb : Give the general verbosity level, from 0 (no verbose) to 5 and above (at the event level) (default: 1)." << endl; 00063 cout << endl; 00064 cout << "[Specific options]:" << endl; 00065 cout << " -help-dim : Print out specific help about dimensions settings." << endl; // managed by main 00066 cout << " -help-in : Print out specific help about input settings." << endl; // managed by main 00067 cout << " -help-out : Print out specific help about output settings." << endl; // managed by main 00068 cout << " -help-algo : Print out specific help about reconstruction optimizer algorithm settings." << endl; // managed by main 00069 cout << " -help-proj : Print out specific help about projection operators." << endl; // managed by main 00070 cout << " -help-dynamic : Print out specific help about dynamic methodologies settings." << endl; // managed by main 00071 cout << " -help-imgp : Print out specific help about image processing modules." << endl; // managed by main 00072 cout << " -help-comp : Print out specific help about computing settings." << endl; // managed by main 00073 cout << " -help-corr : Print out specific help about all corrections that can be disabled." << endl; 00074 cout << " -help-misc : Print out specific help about miscellaneous and verbose settings." << endl; // managed by main 00075 cout << endl; 00076 cout << "[Implemented Modules]:" << endl; 00077 cout << " -help-scan : Show the list of all scanners from the configuration directory." << endl; // managed by sScannerManager 00078 cout << " -help-projm : Show the list and description of all implemented projectors." << endl; // managed by oProjectorManager 00079 cout << " -help-opti : Show the list and description of all implemented optimizer algorithms." << endl; // managed by oOptimizerManager 00080 //cout << " -help-pnlt : Show the list and description of all implemented penalties for optimizers." << endl; // managed by oOptimizerManager 00081 //cout << " -help-deform : Show the list and description of all implemented image-based deformation models." << endl; // managed by oImageDeformationManager*/ 00082 //cout << " -help-dynm : Show the list and description of all implemented dynamic models." << endl; // managed by oDynamicModelManager*/ 00083 cout << " -help-conv : Show the list and description of all implemented image convolvers." << endl; // managed by oImageConvolverManager 00084 cout << " -help-proc : Show the list and description of all implemented image processing modules." << endl; // managed by oImageProcessingManager 00085 cout << endl; 00086 cout << endl; 00087 cout << " --help,-h,-help : Print out this help page." << endl; // managed by main 00088 cout << endl; 00089 #ifdef CASTOR_MPI 00090 cout << " Compiled with MPI" << endl; 00091 #endif 00092 #ifdef CASTOR_OMP 00093 cout << " Compiled with OpenMP" << endl; 00094 #endif 00095 #ifdef CASTOR_GPU 00096 cout << " Compiled for GPU" << endl; 00097 #endif 00098 #if defined(CASTOR_OMP) || defined(CASTOR_MPI) || defined(CASTOR_GPU) 00099 cout << endl; 00100 #endif 00101 #ifdef BUILD_DATE 00102 cout << " Build date: " << BUILD_DATE << endl; 00103 cout << endl; 00104 #endif 00105 } 00106 00107 // ===================================================================== 00108 // --------------------------------------------------------------------- 00109 // --------------------------------------------------------------------- 00110 // ===================================================================== 00115 void ShowHelpInput() 00116 { 00117 // Return when using MPI and mpi_rank is not 0 00118 #ifdef CASTOR_MPI 00119 int mpi_rank = 0; 00120 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00121 if (mpi_rank!=0) return; 00122 #endif 00123 // Show help 00124 cout << endl; 00125 cout << "[Input settings]:" << endl; 00126 cout << endl; 00127 // cout << " -df file.Cdf : Give an input CASTOR datafile (no default). Can use this option multiple times to specify multiple bed positions." << endl; 00128 cout << " -df file.Cdf : Give an input CASTOR datafile (no default)." << endl; 00129 cout << endl; 00130 cout << " -img file.hdr : Give an input image as the initialization of the algorithm (default: uniform value)." << endl; 00131 cout << endl; 00132 cout << " -sens file.hdr : Provide the sensitivity image (default: sensitivity image is computed before reconstruction)." << endl; 00133 cout << " the image file should integrate all sensitivity images if more than one are required" << endl; 00134 cout << " if dual-gating is enabled and if it required sensitivity images for each gate, the image should integrate nb_resp_gates * nb_card_gates sensitivity images" << endl; 00135 cout << " (all cardiac-gated based sensitivity images for each one of the respiratory gates)." << endl; 00136 cout << endl; 00137 cout << " -norm file.cdh : For list-mode data, provide a normalization data file for sensitivity computation (default: use the scanner LUT and" << endl; 00138 cout << " assume all LORs with a weight of 1.). This restricts the computation of the sensitivity to the LORs provided in the" << endl; 00139 cout << " normalization file and associated normalization factors and/or attenuation factors." << endl; 00140 cout << " For dynamic reconstructions with multiple frames, as many normalization files as frames can be supplied, their names" << endl; 00141 cout << " separated by commas. This is useful when dead-times correction is included in the normalization factors." << endl; 00142 cout << " Can also use this option multiple times when multiple bed positions are reconstructed at once." << endl; 00143 cout << endl; 00144 cout << " -atn file.hdr : Give an input attenuation image (unit has to be cm-1) for sensitivity image generation or SPECT attenuation correction." << endl; 00145 cout << endl; 00146 cout << " -help-in : Print out this help." << endl; 00147 cout << endl; 00148 } 00149 00150 // ===================================================================== 00151 // --------------------------------------------------------------------- 00152 // --------------------------------------------------------------------- 00153 // ===================================================================== 00158 void ShowHelpOutput() 00159 { 00160 // Return when using MPI and mpi_rank is not 0 00161 #ifdef CASTOR_MPI 00162 int mpi_rank = 0; 00163 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00164 if (mpi_rank!=0) return; 00165 #endif 00166 // Show help 00167 cout << endl; 00168 cout << "[Output settings]:" << endl; 00169 cout << endl; 00170 cout << " -fout name : Give the root name for all output files. All output files will be written as 'name_suffix.ext'." << endl; 00171 cout << " So the provided name should not end with '.' or '/' character. (no default, alternative to -dout)" << endl; 00172 cout << " -dout name : Give the name of the output directory where all output files will be written. All files will also" << endl; 00173 cout << " be prefixed by the name of the directory. The provided name should not end with '.' or '/' character." << endl; 00174 cout << " (no default, alternative to -fout)" << endl; 00175 cout << endl; 00176 cout << " -oit list : Give the sequence of output iterations as a list of 'a:b' pairs separated by commas. This will output one" << endl; 00177 cout << " iteration over 'a' until 'b' is reached, then it goes to the next pair of setting. (default: last iteration)" << endl; 00178 cout << endl; 00179 cout << " -omd : (M)erge (D)ynamic images. Indicate if a dynamic serie of 3D images should be written on disk in one file" << endl; 00180 cout << " instead of a serie of 3D images associated with an interfile metaheader" << endl; 00181 cout << endl; 00182 /* TO BE IMPLEMENTED 00183 cout << " -otb : Flag to say that we want to save the time basis images too (default: only the frames are saved)." << endl; 00184 cout << endl; 00185 */ 00186 cout << " -osens : Flag to say that we want to save the sensitivity image of each subset/iteration, when in histogram mode." << endl; 00187 cout << endl; 00188 cout << " -osub : Flag to say that we want to save the image after each subset." << endl; 00189 cout << endl; 00190 cout << " -olut : If a scanner LUT (geometry information) is computed from a .geom file, it will be save on disk in the scanner repository" << endl; 00191 cout << endl; 00192 cout << " -sens-only : For list-mode data, exit directly after computing and saving the sensitivity." << endl; 00193 cout << endl; 00194 cout << " -help-out : Print out this help." << endl; 00195 cout << endl; 00196 } 00197 00198 // ===================================================================== 00199 // --------------------------------------------------------------------- 00200 // --------------------------------------------------------------------- 00201 // ===================================================================== 00206 void ShowHelpDimensions() 00207 { 00208 // Return when using MPI and mpi_rank is not 0 00209 #ifdef CASTOR_MPI 00210 int mpi_rank = 0; 00211 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00212 if (mpi_rank!=0) return; 00213 #endif 00214 // Show help 00215 cout << endl; 00216 cout << "[Dimensions options]:" << endl; 00217 cout << endl; 00218 cout << " -dim x,y,z : Give the number of voxels in each dimension (default: those of the scanner)." << endl; 00219 cout << endl; 00220 cout << " -fov x,y,z : Give the size of the field-of-view in each dimension, in mm (default: those of the scanner)." << endl; 00221 cout << endl; 00222 cout << " -vox x,y,z : Give the size of the voxels in each dimension, in mm (default: those of the scanner, or calculated from the fov if a fov value is provided using '-fov')." << endl; 00223 cout << endl; 00224 cout << " -off x,y,z : Give the offset of the field-of-view in each dimension, in mm (default: 0.,0.,0.)." << endl; 00225 cout << " (note this has no effect when using a pre-computed system matrix)" << endl; 00226 cout << endl; 00227 cout << " -fov-out percent : Give the percentage of the eliptical transaxial FOV to be kept while saving the image (default: no making)" << endl; 00228 cout << endl; 00229 cout << " -slice-out value : Give the number of axial slices to be masked at each border of the axial field-of-view (default: 0)" << endl; 00230 cout << endl; 00231 cout << " -flip-out value : Flip the image before saving it (not done in the computation); specify the axis (e.g. 'X', 'XY', 'YZ') (default: no flip)" << endl; 00232 cout << endl; 00233 cout << " -help-dim : Print out this help." << endl; 00234 cout << endl; 00235 } 00236 00237 // ===================================================================== 00238 // --------------------------------------------------------------------- 00239 // --------------------------------------------------------------------- 00240 // ===================================================================== 00245 void ShowHelpAlgo() 00246 { 00247 // Return when using MPI and mpi_rank is not 0 00248 #ifdef CASTOR_MPI 00249 int mpi_rank = 0; 00250 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00251 if (mpi_rank!=0) return; 00252 #endif 00253 // Show help 00254 cout << "[Algorithm settings]:" << endl; 00255 cout << endl; 00256 cout << " -opti param : Give the algorithm to be used, along with a configuration file (algo:file.conf) or the list of parameters" << endl; 00257 cout << " associated to the algorithm (algo,param1,param2,...). If the algorithm only is specified, the default" << endl; 00258 cout << " configuration file is used if any. By default, the MLEM algorithm is used. For specific help, use option -help-opti." << endl; 00259 cout << endl; 00260 cout << " -opti-fom : Flag to say that we want to compute and print figures-of-merit (likelihood and RMSE) in the data-space." << endl; 00261 cout << endl; 00262 cout << " -opti-stat : Flag to say that we want to compute and print basic statistics about the image update." << endl; 00263 cout << endl; 00264 /* NOT YET IMPLEMENTED 00265 cout << " -pnlt param : Give the penalty to be used with the algorithm (if the latter allows to do so), along with a configuration file (penalty:file.conf)" << endl; 00266 cout << " or the list of parameters associated to the penalty (penalty,param1,param2,...). If the penalty only is specified, the default" << endl; 00267 cout << " configuration file is used if any. By default, no penalty is used. For specific help, use option -help-penalty." << endl; 00268 cout << endl; 00269 */ 00270 cout << " -help-opti : Print out specific help about algorithm settings." << endl; // managed by oOptimizerManager 00271 cout << endl; 00272 /* NOT YET IMPLEMENTED 00273 cout << " -help-pnlt : Print out specific help about penalty settings." << endl; // managed by oOptimizerManager 00274 cout << endl; 00275 */ 00276 } 00277 00278 // ===================================================================== 00279 // --------------------------------------------------------------------- 00280 // --------------------------------------------------------------------- 00281 // ===================================================================== 00286 void ShowHelpProj() 00287 { 00288 // Return when using MPI and mpi_rank is not 0 00289 #ifdef CASTOR_MPI 00290 int mpi_rank = 0; 00291 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00292 if (mpi_rank!=0) return; 00293 #endif 00294 // Show help 00295 cout << "[Projector settings]:" << endl; 00296 cout << endl; 00297 cout << " -proj param : Give the projector to be used for both forward and backward projections, along with a configuration file (proj:file.conf)" << endl; 00298 cout << " or the list of parameters associated to the projector (proj,param1,param2,...). If the projector only is specified, the" << endl; 00299 cout << " default configuration file is used. By default, the Siddon projector is used. For specific help, use option -help-proj." << endl; 00300 cout << endl; 00301 cout << " -projF param : Give the projector to be used for forward projections. See option -proj for details." << endl; 00302 cout << endl; 00303 cout << " -projB param : Give the projector to be used for backward projections. See option -proj for details." << endl; 00304 cout << endl; 00305 cout << " -proj-common : Give parameterization of different common projector-related options." << endl; 00306 cout << endl; 00307 /* TO BE IMPLEMENTED 00308 cout << " -ignore-POI : Flag to say that we want to ignore any potential POI information (default: use it if present in the datafile)." << endl; 00309 cout << endl; 00310 cout << " -ignore-TOF : Flag to say that we want to ignore any potential TOF information (default: use it if present in the datafile)." << endl; 00311 cout << endl; 00312 */ 00313 cout << " -help-projm : Print out specific help about projector settings." << endl; // managed by oProjectorManager 00314 cout << endl; 00315 } 00316 00317 // ===================================================================== 00318 // --------------------------------------------------------------------- 00319 // --------------------------------------------------------------------- 00320 // ===================================================================== 00325 void ShowHelpImgp() 00326 { 00327 // Return when using MPI and mpi_rank is not 0 00328 #ifdef CASTOR_MPI 00329 int mpi_rank = 0; 00330 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00331 if (mpi_rank!=0) return; 00332 #endif 00333 // Show help 00334 cout << "[Image processing settings]:" << endl; 00335 cout << endl; 00336 cout << " -conv param;when : Give an image convolver model to be used within the algorithm, along with a configuration file (conv:file.conf::when) or the" << endl; 00337 cout << " list of parameters associated to the convolver (conv,param1,param2,...::when). If the convolver only is specified, its default" << endl; 00338 cout << " configuration file is used. By default, no convolver is applied. Multiple convolvers can be combined simply by repeating this" << endl; 00339 cout << " this option. The mandatory 'when' parameter specifies when the convolver is applied (psf, sieve, forward, backward, post, intra)." << endl; 00340 cout << " For more specific help, use option -help-conv." << endl; 00341 cout << endl; 00342 cout << " -help-conv : Print out specific help about the image convolver settings." << endl; // managed by oImageConvolverManager 00343 cout << endl; 00344 cout << " -proc param;when : Give an image processing module to be used within the algorithm, along with a configuration file (proc:file.conf;when) or the" << endl; 00345 cout << " list of parameters associated to the module (proc,param1,param2,...;when). If the module only is specified, its default" << endl; 00346 cout << " configuration file is used. By default, no image processing module is applied. Multiple modules can be combined simply by" << endl; 00347 cout << " repeating this this option. The mandatory 'when' parameter specifies when the module is applied (forward, backward, post, intra)." << endl; 00348 cout << " For more specific help, use option -help-proc." << endl; 00349 cout << endl; 00350 cout << " -help-proc : Print out specific help about the image processing module settings." << endl; // managed by oImageProcessingManager 00351 cout << endl; 00352 } 00353 00354 // ===================================================================== 00355 // --------------------------------------------------------------------- 00356 // --------------------------------------------------------------------- 00357 // ===================================================================== 00362 void ShowHelpDynamic() 00363 { 00364 // Return when using MPI and mpi_rank is not 0 00365 #ifdef CASTOR_MPI 00366 int mpi_rank = 0; 00367 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00368 if (mpi_rank!=0) return; 00369 #endif 00370 // Show help 00371 cout << endl; 00372 cout << "[Dynamic settings]:" << endl; 00373 cout << endl; 00374 cout << " -frm list : Give the framing for the reconstruction where 'list' is a list of all frames durations in seconds separated" << endl; 00375 cout << " by commas. To specify a dead frame, add ';0' concatenated to the frame duration. Milliseconds maximum precision." << endl; 00376 cout << " (default: 1 frame of the whole input file duration)" << endl; 00377 cout << endl; 00378 cout << " -gating path_to_file : Provide text file for dynamic data splitting associated to respiratory/cardiac gating or involuntary patient motion correction" << endl; 00379 cout << endl; 00380 /* TO BE VALIDATED 00381 cout << " -time-basis nb:file : Give the number of time basis functions related to the frames given by option -frm." << endl; 00382 cout << " The file should contain one line for each time-basis function, and as many numbers as frames." << endl; 00383 cout << " -resp-basis nb:file : Give the number of intrinsic respiratory basis functions related to the respiratory gates" << endl; 00384 cout << " The file should contain one line for each respiratory basis function, and as many numbers as respiratory gates." << endl; 00385 cout << " -card-basis nb:file : Give the number of intrinsic cardiac basis functions related to the cardiac gates" << endl; 00386 cout << " The file should contain one line for each cardiac basis function, and as many numbers as cardiac gates." << endl; 00387 cout << endl; 00388 cout << " -dynamic-model param : Dynamic model applied to either the frames of a dynamic acquisition, respiratory-gated frames, cardiac-gated frames, or simultaneously between these datasets." << endl; 00389 cout << " Select the dynamic model to be used, along with a configuration file (model:file) or the list of parameters associated to the model (model_name,param1,param2,...)." << endl; 00390 cout << endl; 00391 cout << " -rm param : Provide an image-based deformation model to be used for respiratory motion correction, along with a configuration file (deformation:file)" << endl; 00392 cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl; 00393 cout << endl; 00394 cout << " -cm param : Provide an image-based deformation model to be used for cardiac motion correction, along with a configuration file (deformation:file)" << endl; 00395 cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl; 00396 cout << endl; 00397 cout << " -im param : Provide an image-based deformation model to be used for involuntary motion correction, along with a configuration file (deformation:file)" << endl; 00398 cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl; 00399 cout << endl; 00400 cout << " -qdyn file : Provide a text file containing quantitative factors specific to dynamic frames, respiratory or cardiac gates." << endl; 00401 cout << " The file should provide factors with the keywords 'FRAME_QUANTIFICATION_FACTORS' and 'GATE_QUANTIFICATION_FACTORS' " << endl; 00402 cout << " The number of factors should be consistent with the number of frames/gates " << endl; 00403 cout << " If the data contains several frames and gates, the gate quantification factors should be entered on a separate line for each frame " << endl; 00404 cout << endl; 00405 cout << " -help-dynm : Print out specific help about dynamic model." << endl; // managed by oDynamicModelManager 00406 cout << endl; 00407 cout << " -help-deform : Print out specific help about deformation in image space for motion correction." << endl; // managed by oImageDeformationManager 00408 cout << endl; 00409 */ 00410 cout << " -help-dynamic : Print out this help." << endl; 00411 cout << endl; 00412 } 00413 00414 // ===================================================================== 00415 // --------------------------------------------------------------------- 00416 // --------------------------------------------------------------------- 00417 // ===================================================================== 00422 void ShowHelpComputation() 00423 { 00424 // Return when using MPI and mpi_rank is not 0 00425 #ifdef CASTOR_MPI 00426 int mpi_rank = 0; 00427 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00428 if (mpi_rank!=0) return; 00429 #endif 00430 // Show help 00431 cout << endl; 00432 cout << "[Computation settings]:" << endl; 00433 cout << endl; 00434 #ifdef CASTOR_OMP 00435 cout << " -th param : Set the number of threads for parallel computation (default: 1). If 0 is given, then the maximum number of available threads is automatically determined." << endl; 00436 cout << " Can also give two parameters separated by a comma (e.g. 16,4), to distinguish between the number of threads for projection and image operations respectively." << endl; 00437 cout << endl; 00438 #endif 00439 #ifdef CASTOR_GPU 00440 cout << " -gpu : Flag to say that we want to use the GPU device (default: use the CPU only)." << endl; 00441 cout << endl; 00442 #endif 00443 cout << " -load size : Give a number between 0 and 100 to specify the number of events which will be loaded in the RAM." << endl; 00444 cout << " It will be interpreted as a percent ratio (default: 100 means all data buffered. 0 means no data buffered.)" << endl; 00445 cout << endl; 00446 cout << " -proj-comp : Give the strategy for projection line computation. Here are the three different strategies that can be used:" << endl; 00447 cout << " 1 : Image-based system matrix elements storage: The voxels weights are added in a matrix representing the whole image, so" << endl; 00448 cout << " the addition of a new line to the previous ones is straightforward only by adding the weights to the corresponding voxels." << endl; 00449 cout << " As it is insanely long, it can possibly be used for example with extremely complex projectors that makes use of huge number" << endl; 00450 cout << " of ray tracings for a single event, where the list of contributions can become longer than the number of voxels in the image." << endl; 00451 cout << " This strategy is not compatible with SPECT reconstruction including attenuation correction." << endl; 00452 cout << " 2 : Fixed-size list storage of system matrix elements: The voxels are added one by one in two separated lists, one containing voxel" << endl; 00453 cout << " indices and the other voxel weights. When a voxel is added to the oProjectionLine, it is simply pilled-up to the list. The list" << endl; 00454 cout << " has a fixed size which is provided by the EstimateMaxNumberOfVoxelsPerLine() function from the vProjector class. There are no" << endl; 00455 cout << " ckecks at all for possible buffer overflows. This is the fastest strategy and default one." << endl; 00456 cout << " 3 : Adaptative-size list storage of system matrix elements: This is the same as the fixed-size strategy except that the size can be" << endl; 00457 cout << " upgraded if the current number of contributing voxels exceed the list's size. The first allocated size corresponds to the diagonal" << endl; 00458 cout << " of the image. During the first iteration, this size will be upgraded until it will reach a size suitable for all events. Thus it" << endl; 00459 cout << " is a bit slower than the fixed-list strategy during the first iteration, but is optimal with respect to RAM usage." << endl; 00460 cout << endl; 00461 cout << " -rng : Give a seed for the random number generator (should be >=0)" << endl; 00462 cout << endl; 00463 cout << " -help-comp : Print out this help." << endl; 00464 cout << endl; 00465 #ifdef CASTOR_MPI 00466 cout << " Compiled with MPI" << endl; 00467 #endif 00468 #ifdef CASTOR_OMP 00469 cout << " Compiled with OpenMP" << endl; 00470 #endif 00471 #ifdef CASTOR_GPU 00472 cout << " Compiled for GPU" << endl; 00473 #endif 00474 #if defined(CASTOR_OMP) || defined(CASTOR_MPI) || defined(CASTOR_GPU) 00475 cout << endl; 00476 #endif 00477 } 00478 00479 // ===================================================================== 00480 // --------------------------------------------------------------------- 00481 // --------------------------------------------------------------------- 00482 // ===================================================================== 00487 void ShowHelpMiscellaneous() 00488 { 00489 // Return when using MPI and mpi_rank is not 0 00490 #ifdef CASTOR_MPI 00491 int mpi_rank = 0; 00492 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00493 if (mpi_rank!=0) return; 00494 #endif 00495 // Show help 00496 cout << endl; 00497 cout << "[Miscellaneous settings]:" << endl; 00498 cout << endl; 00499 cout << " -vb : Give the general verbosity level, from 0 (no verbose) to 5 and above (at the event level) (default: 1)." << endl; 00500 cout << " -vb-algo : Give the verbose level specific to the algorithm (default: same as general verbose level)." << endl; 00501 cout << " -vb-opti : Give the verbose level specific to the optimizer (default: same as general verbose level)." << endl; 00502 cout << " -vb-proj : Give the verbose level specific to the projector (default: same as general verbose level)." << endl; 00503 cout << " -vb-conv : Give the verbose level specific to the image convolver (default: same as general verbose level)." << endl; 00504 cout << " -vb-proc : Give the verbose level specific to the image processing (default: same as general verbose level)." << endl; 00505 cout << " -vb-scan : Give the verbose level specific to the scanner (default: same as general verbose level)." << endl; 00506 cout << " -vb-data : Give the verbose level specific to the data and image management (default: same as general verbose level)." << endl; 00507 cout << " -vb-defo : Give the verbose level specific to the deformation (default: same as general verbose level)." << endl; 00508 cout << " -vb-dyna : Give the verbose level specific to the dynamic model (default: same as general verbose level)." << endl; 00509 cout << " -vb-sens : Give the verbose level specific to the sensitivity computation (default: same as general verbose level)." << endl; 00510 cout << endl; 00511 cout << " -conf : Give the path to the CASToR config directory (default: located through the CASTOR_CONFIG environment variable)." << endl; 00512 cout << endl; 00513 cout << " -help-misc : Print out this help." << endl; 00514 cout << endl; 00515 } 00516 00517 // ===================================================================== 00518 // --------------------------------------------------------------------- 00519 // --------------------------------------------------------------------- 00520 // ===================================================================== 00525 void ShowHelpCorrection() 00526 { 00527 // Return when using MPI and mpi_rank is not 0 00528 #ifdef CASTOR_MPI 00529 int mpi_rank = 0; 00530 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00531 if (mpi_rank!=0) return; 00532 #endif 00533 // Show help 00534 cout << endl; 00535 cout << "[Correction settings]:" << endl; 00536 cout << endl; 00537 cout << " -ignore-corr list : Give the list of corrections that should be ignored, separated by commas (default: all corrections applied if present)." << endl; 00538 cout << " Here is a list of all corrections that can be ignored:" << endl; 00539 cout << " - attn: to ignore the attenuation correction (emission only)" << endl; 00540 cout << " - norm: to ignore the normalization correction (emission only)" << endl; 00541 cout << " - rand: to ignore the random correction (PET only)" << endl; 00542 cout << " - scat: to ignore the scatter correction" << endl; 00543 cout << " - deca: to ignore the decay correction (emission only)" << endl; 00544 cout << " - brat: to ignore the branching ratio correction (emission only)" << endl; 00545 cout << " - fdur: to ignore the frame duration correction (emission only)" << endl; 00546 cout << " - cali: to ignore the calibration correction (emission only)" << endl; 00547 cout << endl; 00548 } 00549 00550 // ============================================================================================================================================= 00551 // ============================================================================================================================================= 00552 // ============================================================================================================================================= 00553 // M A I N P R O G R A M 00554 // ============================================================================================================================================= 00555 // ============================================================================================================================================= 00556 // ============================================================================================================================================= 00557 00558 int main(int argc, char** argv) 00559 { 00560 // ============================================================================================================ 00561 // MPI stuff 00562 // ============================================================================================================ 00563 int mpi_rank = 0; 00564 int mpi_size = 1; 00565 #ifdef CASTOR_MPI 00566 MPI_Init(&argc, &argv); 00567 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); 00568 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); 00569 #endif 00570 00571 // No argument, then show help 00572 if (argc==1) 00573 { 00574 ShowHelp(); 00575 Exit(EXIT_SUCCESS); 00576 } 00577 00578 // ============================================================================================================ 00579 // Parameterized variables with their default values 00580 // ============================================================================================================ 00581 00582 // -------------------------------------------------------------------------------- 00583 // Dimensions settings 00584 // -------------------------------------------------------------------------------- 00585 00586 // Initialization of the voxel and field-of-view values in each spatial dimensions. default values depend of the scanner. 00587 INTNB nb_voxX=-1, nb_voxY=-1, nb_voxZ=-1; 00588 FLTNB fov_sizeX=-1., fov_sizeY=-1., fov_sizeZ=-1.; 00589 FLTNB vox_sizeX=-1., vox_sizeY=-1., vox_sizeZ=-1.; 00590 // Initialization offset values of the field-of-view in each spatial dimensions 00591 FLTNB offsetX = 0., offsetY = 0., offsetZ = 0.; 00592 FLTNB fov_out = 0.; 00593 INTNB slice_out = 0; 00594 // Output flip 00595 string flip_out = ""; 00596 00597 // -------------------------------------------------------------------------------- 00598 // Dynamic settings 00599 // -------------------------------------------------------------------------------- 00600 00601 // Frame list descriptor 00602 string frame_list = ""; 00603 // Number of respiratory gates in the data. default : 1 00604 int nb_resp_gates = 1; 00605 // Number of cardiac gates in the data. default : 1 00606 int nb_card_gates = 1; 00607 // Path to file containing the respiratory/cardiac gate splitting of the data 00608 string path_to_4D_data_splitting_file = ""; 00609 // String gathering the name of the used dynamic model applied to the frames/resp gates/card gates of the dynamic acquisition (default : none), corresponding file, and corresponding string gathering parameters 00610 string dynamic_model_options = ""; 00611 // String gathering the name of the used deformation model for respiratory motion (default : none), corresponding file, and corresponding string gathering parameters 00612 string resp_motion_options = ""; 00613 // String gathering the name of the used deformation model for cardiac motion (default : none), corresponding file, and corresponding string gathering parameters 00614 string card_motion_options = ""; 00615 // String gathering the name of the used deformation model for involuntary motion (default : none), corresponding file, and corresponding string gathering parameters 00616 string inv_motion_options = ""; 00617 // Number of time basis functions and associated file 00618 int nb_time_basis = 1; 00619 string path_to_time_basis_coef = ""; 00620 // Number of respiratory basis functions and associated file 00621 int nb_resp_basis = 1; 00622 string path_to_resp_basis_coef = ""; 00623 // Number of cardiac basis functions and associated file 00624 int nb_card_basis = 1; 00625 string path_to_card_basis_coef = ""; 00626 // Number of cardiac basis functions and associated file 00627 string path_to_dynamic_quantification_file= ""; 00628 00629 // -------------------------------------------------------------------------------- 00630 // Input settings 00631 // -------------------------------------------------------------------------------- 00632 00633 // Number of bed position 00634 int nb_beds = 0; 00635 // Vector containing string which gather the path to the data filenames provided by the user. no default 00636 vector<string> path_to_data_filename; 00637 // Path to an image used as initialization. no default (uniform image is used in this case) 00638 string path_to_initial_img = ""; 00639 // Path to an image used as initialization for the sensitivity image. no default (sensitivity image is computed in this case) 00640 string path_to_sensitivity_img; 00641 // Path to a normalization data file for sensitivity computation with list-mode data 00642 vector<string> path_to_normalization_filename; 00643 // Path to an image used for the attenuation. default : uniform image 00644 string path_to_attenuation_img; 00645 // Number of resp and card atn images for sensitivity image generation 00646 int nb_atn_resp_imgs = 1; 00647 int nb_atn_card_imgs = 1; 00648 // Ignored corrections (by default, if present, there are applied) 00649 string ignored_corrections = ""; 00650 00651 // -------------------------------------------------------------------------------- 00652 // Output settings 00653 // -------------------------------------------------------------------------------- 00654 00655 // Output directory name. 00656 string path_dout = ""; 00657 // Or root name 00658 string path_fout = ""; 00659 // Iterations to be saved 00660 string output_iterations = ""; 00661 // Merge output dynamic images on disk into one file or not 00662 bool merge_dynamic_imgs_flag = false; 00663 // Write scanner LUT generated by a geom file on disk 00664 bool save_LUT_flag = false; 00665 // Save the sensitivity image in histogram mode for each subset/iteration 00666 bool save_sens_histo = false; 00667 // Save the image after each subset 00668 bool save_subset_image = false; 00669 // Save the time basis functions (flag). default : no saving 00670 //bool save_time_basis_functions_flag = false; //TODO 00671 // Exit directly after computing the sensitivity 00672 bool exit_after_sensitivity = false; 00673 00674 // -------------------------------------------------------------------------------- 00675 // Projector settings 00676 // -------------------------------------------------------------------------------- 00677 00678 // String gathering the name of the projector for forward/backward projection with specific options (default: Native Siddon for both) 00679 string options_projector = "incrementalSiddon"; 00680 string options_projectorF = "incrementalSiddon"; 00681 string options_projectorB = "incrementalSiddon"; 00682 string options_projector_common = ""; 00683 // Default projector computation strategy 00684 int projector_computation_strategy = FIXED_LIST_COMPUTATION_STRATEGY; 00685 // DOI & TOF flags for the use of such informations in the reconstruction 00686 bool ignore_POI = false; 00687 bool ignore_TOF = false; 00688 00689 // -------------------------------------------------------------------------------- 00690 // Algorithm settings 00691 // -------------------------------------------------------------------------------- 00692 00693 // Numbers of iterations and associated numbers of subsets (default : 1 for both) 00694 string nb_iterations_subsets = ""; 00695 // String gathering the name of the optimizer with specific options (default: MLEM) 00696 string options_optimizer = "MLEM"; 00697 // Boolean to say if we want to compute FOM in the data-space 00698 bool optimizer_fom = false; 00699 // Boolean to say if we want to compute image update basic statistics 00700 bool optimizer_stat = false; 00701 // String gathering the name of the penalty with specific options (default: no penalty) 00702 string options_penalty = ""; 00703 00704 // -------------------------------------------------------------------------------- 00705 // Image convolvers and processing modules 00706 // -------------------------------------------------------------------------------- 00707 00708 // String vector gathering the name of the image convolvers with specific options (default: no image convolver) 00709 vector<string> options_image_convolver; 00710 // String vector gathering the name of the image processing modules with specific options (default: no image processing module) 00711 vector<string> options_image_processing; 00712 00713 // -------------------------------------------------------------------------------- 00714 // Computation settings 00715 // -------------------------------------------------------------------------------- 00716 00717 // Using GPU (flag) ->NOTE : default : only CPU 00718 bool gpu_flag = false; 00719 // Size of the buffer used to read the data file (this is a percentage rounded to the integer) 00720 int data_file_percentage_load = 100; 00721 // Number of threads 00722 string nb_threads = "1"; 00723 00724 // -------------------------------------------------------------------------------- 00725 // Miscellaneous settings 00726 // -------------------------------------------------------------------------------- 00727 00728 // General verbose level 00729 int verbose_general = 1; 00730 // Specific verbose levels 00731 int verbose_algo = -1; 00732 int verbose_opti = -1; 00733 int verbose_proj = -1; 00734 int verbose_conv = -1; 00735 int verbose_proc = -1; 00736 int verbose_scan = -1; 00737 int verbose_data = -1; 00738 int verbose_defo = -1; 00739 int verbose_dyna = -1; 00740 int verbose_sens = -1; 00741 // Path to config directory 00742 string path_to_config_dir = ""; 00743 // Initial seed for random number generator 00744 int64_t seed_RNG = -1; 00745 00746 // ============================================================================================================ 00747 // Read command-line parameters 00748 // ============================================================================================================ 00749 00750 // TODO : replace remaining atoi, atof, etc, by ConvertFromString() 00751 00752 // Must manually increment the option index when an argument is needed after an option 00753 for (int i=1; i<argc; i++) 00754 { 00755 // Get the option as a string 00756 string option = (string)argv[i]; 00757 00758 // -------------------------------------------------------------------------------- 00759 // Miscellaneous settings 00760 // -------------------------------------------------------------------------------- 00761 00762 // Show help 00763 if (option=="-h" || option=="--help" || option=="-help") 00764 { 00765 ShowHelp(); 00766 Exit(EXIT_SUCCESS); 00767 } 00768 // Specific help for integrated scanners (managed by scanner manager) 00769 else if (option=="-help-scan") 00770 { 00771 if(sScannerManager::GetInstance()->ShowScannersDescription()) 00772 Cerr("***** castor-recon() -> An error occured when trying to output the available scanners from the scanner repository !'" << endl;); 00773 Exit(EXIT_SUCCESS); 00774 } 00775 // Specific help for optimizer settings (managed by optimizer children) 00776 else if (option=="-help-opti") 00777 { 00778 sAddonManager::GetInstance()->ShowHelpOptimizer(); 00779 Exit(EXIT_SUCCESS); 00780 } 00781 // Specific help for penalty settings (managed by penalty children) 00782 else if (option=="-help-pnlt") 00783 { 00784 sAddonManager::GetInstance()->ShowHelpPenalty(); 00785 Exit(EXIT_SUCCESS); 00786 } 00787 // Specific help for projector settings (managed by projector children) 00788 else if (option=="-help-projm") 00789 { 00790 // Call specific showHelp function from vProjector children 00791 sAddonManager::GetInstance()->ShowHelpProjector(); 00792 // Call the static showHelp function from vProjector 00793 vProjector::ShowCommonHelp(); 00794 Exit(EXIT_SUCCESS); 00795 } 00796 // Specific help for image convolver settings (managed by image convolver children) 00797 else if (option=="-help-conv") 00798 { 00799 // Call specific showHelp function from vImageConvolver children 00800 sAddonManager::GetInstance()->ShowHelpImageConvolver(); 00801 // Call the static showHelp function from oImageConvolverManager 00802 oImageConvolverManager::ShowCommonHelp(); 00803 Exit(EXIT_SUCCESS); 00804 } 00805 // Specific help for image processing settings (managed by image processing children) 00806 else if (option=="-help-proc") 00807 { 00808 // Call specific showHelp function from vImageProcessingModule children 00809 sAddonManager::GetInstance()->ShowHelpImageProcessingModule(); 00810 // Call the static showHelp function from oImageProcessingManager 00811 oImageProcessingManager::ShowCommonHelp(); 00812 Exit(EXIT_SUCCESS); 00813 } 00814 // Specific help for dynamic model (managed by dynamic model children) 00815 else if (option=="-help-dynm") 00816 { 00817 sAddonManager::GetInstance()->ShowHelpDynamicModel(); 00818 Exit(EXIT_SUCCESS); 00819 } 00820 // Specific help for image deformation settings (managed by projector children) 00821 else if (option=="-help-deform") 00822 { 00823 sAddonManager::GetInstance()->ShowHelpDeformation(); 00824 Exit(EXIT_SUCCESS); 00825 } 00826 // Specific help for input settings (managed by main) 00827 else if (option=="-help-in") 00828 { 00829 ShowHelpInput(); 00830 Exit(EXIT_SUCCESS); 00831 } 00832 // Specific help for output settings (managed by main) 00833 else if (option=="-help-out") 00834 { 00835 ShowHelpOutput(); 00836 Exit(EXIT_SUCCESS); 00837 } 00838 // Specific help for dimensions settings (managed by main) 00839 else if (option=="-help-dim") 00840 { 00841 ShowHelpDimensions(); 00842 Exit(EXIT_SUCCESS); 00843 } 00844 // Specific help for optimizer settings (managed by main) 00845 else if (option=="-help-algo") 00846 { 00847 ShowHelpAlgo(); 00848 Exit(EXIT_SUCCESS); 00849 } 00850 // Specific help for projector settings (managed by main) 00851 else if (option=="-help-proj") 00852 { 00853 ShowHelpProj(); 00854 Exit(EXIT_SUCCESS); 00855 } 00856 // Specific help for image processing settings (managed by main) 00857 else if (option=="-help-imgp") 00858 { 00859 ShowHelpImgp(); 00860 Exit(EXIT_SUCCESS); 00861 } 00862 // Specific help for computation settings (managed by main) 00863 else if (option=="-help-comp") 00864 { 00865 ShowHelpComputation(); 00866 Exit(EXIT_SUCCESS); 00867 } 00868 // Specific help for miscellaneous settings (managed by main) 00869 else if (option=="-help-misc") 00870 { 00871 ShowHelpMiscellaneous(); 00872 Exit(EXIT_SUCCESS); 00873 } 00874 // Specific help for dynamic settings (managed by main) 00875 else if (option=="-help-dynamic") 00876 { 00877 ShowHelpDynamic(); 00878 Exit(EXIT_SUCCESS); 00879 } 00880 // Specific help for correction settings (managed by main) 00881 else if (option=="-help-corr") 00882 { 00883 ShowHelpCorrection(); 00884 Exit(EXIT_SUCCESS); 00885 } 00886 // General verbosity level 00887 else if (option=="-vb") 00888 { 00889 if (i>=argc-1) 00890 { 00891 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00892 Exit(EXIT_FAILURE); 00893 } 00894 if (ConvertFromString(argv[i+1], &verbose_general)) 00895 { 00896 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_general << " for option: " << option << endl); 00897 Exit(EXIT_FAILURE); 00898 } 00899 i++; 00900 } 00901 // Algorithm verbosity level 00902 else if (option=="-vb-algo") 00903 { 00904 if (i>=argc-1) 00905 { 00906 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00907 Exit(EXIT_FAILURE); 00908 } 00909 if (ConvertFromString(argv[i+1], &verbose_algo)) 00910 { 00911 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_algo << " for option: " << option << endl); 00912 Exit(EXIT_FAILURE); 00913 } 00914 i++; 00915 } 00916 // Optimizer verbosity level 00917 else if (option=="-vb-opti") 00918 { 00919 if (i>=argc-1) 00920 { 00921 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00922 Exit(EXIT_FAILURE); 00923 } 00924 if (ConvertFromString(argv[i+1], &verbose_opti)) 00925 { 00926 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_opti << " for option: " << option << endl); 00927 Exit(EXIT_FAILURE); 00928 } 00929 i++; 00930 } 00931 // Projector verbosity level 00932 else if (option=="-vb-proj") 00933 { 00934 if (i>=argc-1) 00935 { 00936 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00937 Exit(EXIT_FAILURE); 00938 } 00939 if (ConvertFromString(argv[i+1], &verbose_proj)) 00940 { 00941 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_proj << " for option: " << option << endl); 00942 Exit(EXIT_FAILURE); 00943 } 00944 i++; 00945 } 00946 // Image convolver verbosity level 00947 else if (option=="-vb-conv") 00948 { 00949 if (i>=argc-1) 00950 { 00951 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00952 Exit(EXIT_FAILURE); 00953 } 00954 if (ConvertFromString(argv[i+1], &verbose_conv)) 00955 { 00956 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_conv << " for option: " << option << endl); 00957 Exit(EXIT_FAILURE); 00958 } 00959 i++; 00960 } 00961 // Image processing verbosity level 00962 else if (option=="-vb-proc") 00963 { 00964 if (i>=argc-1) 00965 { 00966 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00967 Exit(EXIT_FAILURE); 00968 } 00969 if (ConvertFromString(argv[i+1], &verbose_proc)) 00970 { 00971 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_proc << " for option: " << option << endl); 00972 Exit(EXIT_FAILURE); 00973 } 00974 i++; 00975 } 00976 // Scanner verbosity level 00977 else if (option=="-vb-scan") 00978 { 00979 if (i>=argc-1) 00980 { 00981 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00982 Exit(EXIT_FAILURE); 00983 } 00984 if (ConvertFromString(argv[i+1], &verbose_scan)) 00985 { 00986 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_scan << " for option: " << option << endl); 00987 Exit(EXIT_FAILURE); 00988 } 00989 i++; 00990 } 00991 // Data and image verbosity level 00992 else if (option=="-vb-data") 00993 { 00994 if (i>=argc-1) 00995 { 00996 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 00997 Exit(EXIT_FAILURE); 00998 } 00999 if (ConvertFromString(argv[i+1], &verbose_data)) 01000 { 01001 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_data << " for option: " << option << endl); 01002 Exit(EXIT_FAILURE); 01003 } 01004 i++; 01005 } 01006 // Deformation verbosity level 01007 else if (option=="-vb-defo") 01008 { 01009 if (i>=argc-1) 01010 { 01011 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01012 Exit(EXIT_FAILURE); 01013 } 01014 if (ConvertFromString(argv[i+1], &verbose_defo)) 01015 { 01016 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_defo << " for option: " << option << endl); 01017 Exit(EXIT_FAILURE); 01018 } 01019 i++; 01020 } 01021 // Dynamic verbosity level 01022 else if (option=="-vb-dyna") 01023 { 01024 if (i>=argc-1) 01025 { 01026 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01027 Exit(EXIT_FAILURE); 01028 } 01029 if (ConvertFromString(argv[i+1], &verbose_dyna)) 01030 { 01031 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_dyna << " for option: " << option << endl); 01032 Exit(EXIT_FAILURE); 01033 } 01034 i++; 01035 } 01036 // Sensitivity verbosity level 01037 else if (option=="-vb-sens") 01038 { 01039 if (i>=argc-1) 01040 { 01041 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01042 Exit(EXIT_FAILURE); 01043 } 01044 if (ConvertFromString(argv[i+1], &verbose_sens)) 01045 { 01046 Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_sens << " for option: " << option << endl); 01047 Exit(EXIT_FAILURE); 01048 } 01049 i++; 01050 } 01051 // RNG seed 01052 else if (option=="-rng") 01053 { 01054 if (i>=argc-1) 01055 { 01056 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01057 Exit(EXIT_FAILURE); 01058 } 01059 if(ConvertFromString(argv[i+1], &seed_RNG)) 01060 { 01061 Cerr("***** castor-recon() -> Exception when trying to read provided number '" << seed_RNG << " for option: " << option << endl); 01062 Exit(EXIT_FAILURE); 01063 } 01064 i++; 01065 } 01066 // Path to config directory 01067 else if (option=="-conf") 01068 { 01069 if (i>=argc-1) 01070 { 01071 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01072 Exit(EXIT_FAILURE); 01073 } 01074 path_to_config_dir = (string)argv[i+1]; 01075 i++; 01076 } 01077 01078 // -------------------------------------------------------------------------------- 01079 // Dimensions settings 01080 // -------------------------------------------------------------------------------- 01081 01082 // Dimensions: number of voxels 01083 else if (option=="-dim") 01084 { 01085 if (i>=argc-1) 01086 { 01087 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01088 Exit(EXIT_FAILURE); 01089 } 01090 INTNB input[3]; 01091 if (ReadStringOption(argv[i+1], input, 3, ",", option)) 01092 { 01093 Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl); 01094 Exit(EXIT_FAILURE); 01095 } 01096 nb_voxX = input[0]; 01097 nb_voxY = input[1]; 01098 nb_voxZ = input[2]; 01099 i++; 01100 } 01101 // Dimensions: size of the field-of-view in mm 01102 else if (option=="-fov") 01103 { 01104 if (i>=argc-1) 01105 { 01106 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01107 Exit(EXIT_FAILURE); 01108 } 01109 FLTNB input[3]; 01110 if (ReadStringOption(argv[i+1], input, 3, ",", option)) 01111 { 01112 Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl); 01113 Exit(EXIT_FAILURE); 01114 } 01115 fov_sizeX = input[0]; 01116 fov_sizeY = input[1]; 01117 fov_sizeZ = input[2]; 01118 i++; 01119 } 01120 // Dimensions: size of the voxels in mm 01121 else if (option=="-vox") 01122 { 01123 if (i>=argc-1) 01124 { 01125 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01126 Exit(EXIT_FAILURE); 01127 } 01128 FLTNB input[3]; 01129 if (ReadStringOption(argv[i+1], input, 3, ",", option)) 01130 { 01131 Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl); 01132 Exit(EXIT_FAILURE); 01133 } 01134 vox_sizeX = input[0]; 01135 vox_sizeY = input[1]; 01136 vox_sizeZ = input[2]; 01137 i++; 01138 } 01139 // Dimensions: offset of the image in mm 01140 else if (option=="-off") 01141 { 01142 if (i>=argc-1) 01143 { 01144 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01145 Exit(EXIT_FAILURE); 01146 } 01147 FLTNB input[3]; 01148 if (ReadStringOption(argv[i+1], input, 3, ",", option)) 01149 { 01150 Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl); 01151 Exit(EXIT_FAILURE); 01152 } 01153 offsetX = input[0]; 01154 offsetY = input[1]; 01155 offsetZ = input[2]; 01156 i++; 01157 } 01158 // Size of the output transaxial FOV in percentage 01159 else if (option=="-fov-out") 01160 { 01161 if (i>=argc-1) 01162 { 01163 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01164 Exit(EXIT_FAILURE); 01165 } 01166 fov_out = atof(argv[i+1]); 01167 i++; 01168 } 01169 // Number of slices to be masked at output 01170 else if (option=="-slice-out") 01171 { 01172 if (i>=argc-1) 01173 { 01174 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01175 Exit(EXIT_FAILURE); 01176 } 01177 slice_out = ((INTNB)(atoi(argv[i+1]))); 01178 i++; 01179 } 01180 // Output flip 01181 else if (option=="-flip-out") 01182 { 01183 if (i>=argc-1) 01184 { 01185 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01186 Exit(EXIT_FAILURE); 01187 } 01188 flip_out = (string)(argv[i+1]); 01189 i++; 01190 } 01191 01192 // -------------------------------------------------------------------------------- 01193 // Dynamic settings 01194 // -------------------------------------------------------------------------------- 01195 01196 // Dimensions: number of frames 01197 else if (option=="-frm") // TODO: more checks to be done in the option reading 01198 { 01199 if (i>=argc-1) 01200 { 01201 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01202 Exit(EXIT_FAILURE); 01203 } 01204 frame_list = (string)argv[i+1]; 01205 i++; 01206 } 01207 // Dimensions: number of respiratory gates 01208 else if (option=="-gating") 01209 { 01210 if (i>=argc-1) 01211 { 01212 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01213 Exit(EXIT_FAILURE); 01214 } 01215 // Path to the dynamic file 01216 path_to_4D_data_splitting_file = ((string)argv[i+1]); 01217 // Recover number of respiratory gates from file 01218 if (ReadDataASCIIFile(path_to_4D_data_splitting_file, "nb_respiratory_gates", &nb_resp_gates, 1, KEYWORD_MANDATORY)) 01219 { 01220 Cerr("***** castor-recon() -> Couldn't read the number of respiratory gates in the file " << path_to_4D_data_splitting_file << " for option " << option << endl); 01221 Exit(EXIT_FAILURE); 01222 } 01223 // Recover number of cardiac gates from file 01224 if (ReadDataASCIIFile(path_to_4D_data_splitting_file, "nb_cardiac_gates", &nb_card_gates, 1, KEYWORD_MANDATORY)) 01225 { 01226 Cerr("***** castor-recon() -> Couldn't read the number of cardiac gates in the file " << path_to_4D_data_splitting_file << " for option " << option << endl); 01227 Exit(EXIT_FAILURE); 01228 } 01229 // Check for wrong initialization 01230 if (nb_resp_gates<1 || nb_card_gates <1) 01231 { 01232 Cerr("***** castor-recon() -> Incorrect initialization of the number of gates for the option: " << option << ". This number should be >= 1" << endl); 01233 Exit(EXIT_FAILURE); 01234 } 01235 i++; 01236 } 01237 // Time basis functions 01238 else if (option=="-time-basis") 01239 { 01240 if (i>=argc-1) 01241 { 01242 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01243 Exit(EXIT_FAILURE); 01244 } 01245 string input = argv[i+1]; 01246 size_t column_pos = input.find_first_of(":"); 01247 if (column_pos==string::npos) 01248 { 01249 Cerr("***** castor-recon() -> Incorrect argument after option " << option << ", ':' sign is missing !" << endl); 01250 Exit(EXIT_FAILURE); 01251 } 01252 string str = input.substr(0, column_pos); 01253 nb_time_basis = atoi(str.c_str()); 01254 path_to_time_basis_coef = input.substr(column_pos+1); 01255 i++; 01256 } 01257 // Respiratory basis functions 01258 else if (option=="-resp-basis") 01259 { 01260 if (i>=argc-1) 01261 { 01262 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01263 Exit(EXIT_FAILURE); 01264 } 01265 string input = argv[i+1]; 01266 size_t column_pos = input.find_first_of(":"); 01267 if (column_pos==string::npos) 01268 { 01269 Cerr("***** castor-recon() -> Incorrect argument after option " << option << ", ':' sign is missing !" << endl); 01270 Exit(EXIT_FAILURE); 01271 } 01272 string str = input.substr(0, column_pos); 01273 nb_resp_basis = atoi(str.c_str()); 01274 path_to_resp_basis_coef = input.substr(column_pos+1); 01275 i++; 01276 } 01277 // Cardiac basis functions 01278 else if (option=="-card-basis") 01279 { 01280 if (i>=argc-1) 01281 { 01282 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01283 Exit(EXIT_FAILURE); 01284 } 01285 string input = argv[i+1]; 01286 size_t column_pos = input.find_first_of(":"); 01287 if (column_pos==string::npos) 01288 { 01289 Cerr("***** castor-recon() -> Incorrect argument after option " << option << ", ':' sign is missing !" << endl); 01290 Exit(EXIT_FAILURE); 01291 } 01292 string str = input.substr(0, column_pos); 01293 nb_card_basis = atoi(str.c_str()); 01294 path_to_card_basis_coef = input.substr(column_pos+1); 01295 i++; 01296 } 01297 // Dynamic model applied to the frames/respiratory gates/cardiac gates of the dynamic acquisition 01298 else if (option=="-dynamic-model") 01299 { 01300 if (i>=argc-1) 01301 { 01302 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01303 Exit(EXIT_FAILURE); 01304 } 01305 dynamic_model_options = (string)argv[i+1]; 01306 i++; 01307 } 01308 // Data for respiratory motion correction based on deformation 01309 else if (option=="-rm") 01310 { 01311 if (i>=argc-1) 01312 { 01313 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01314 Exit(EXIT_FAILURE); 01315 } 01316 resp_motion_options = (string)argv[i+1]; 01317 i++; 01318 } 01319 // Data for cardiac motion correction based on deformation 01320 else if (option=="-cm") 01321 { 01322 if (i>=argc-1) 01323 { 01324 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01325 Exit(EXIT_FAILURE); 01326 } 01327 card_motion_options = (string)argv[i+1]; 01328 i++; 01329 } 01330 // Data for involuntary motion correction based on deformation 01331 else if (option=="-im") 01332 { 01333 if (i>=argc-1) 01334 { 01335 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01336 Exit(EXIT_FAILURE); 01337 } 01338 inv_motion_options = (string)argv[i+1]; 01339 i++; 01340 } 01341 // Data for involuntary motion correction based on deformation 01342 else if (option=="-qdyn") 01343 { 01344 if (i>=argc-1) 01345 { 01346 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01347 Exit(EXIT_FAILURE); 01348 } 01349 path_to_dynamic_quantification_file = (string)argv[i+1]; 01350 i++; 01351 } 01352 01353 // -------------------------------------------------------------------------------- 01354 // Input settings 01355 // -------------------------------------------------------------------------------- 01356 01357 // Datafiles 01358 else if (option=="-df") // This is a mandatory option 01359 { 01360 if (i>=argc-1) 01361 { 01362 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01363 Exit(EXIT_FAILURE); 01364 } 01365 string file_name = (string)argv[i+1]; 01366 path_to_data_filename.push_back(file_name); 01367 nb_beds++; 01368 i++; 01369 } 01370 // Image for the initialisation of the algorithm : What should we do in case of multiple beds ? or multiple frames ? TODO 01371 else if (option=="-img") 01372 { 01373 if (i>=argc-1) 01374 { 01375 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01376 Exit(EXIT_FAILURE); 01377 } 01378 path_to_initial_img = argv[i+1]; 01379 i++; 01380 } 01381 // Sensitivity image 01382 else if (option=="-sens") 01383 { 01384 if (i>=argc-1) 01385 { 01386 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01387 Exit(EXIT_FAILURE); 01388 } 01389 01390 path_to_sensitivity_img = argv[i+1]; 01391 i++; 01392 } 01393 // Normalization data files 01394 else if (option=="-norm") 01395 { 01396 if (i>=argc-1) 01397 { 01398 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01399 Exit(EXIT_FAILURE); 01400 } 01401 string file_name = (string)argv[i+1]; 01402 path_to_normalization_filename.push_back(file_name); 01403 i++; 01404 } 01405 01406 // Image for the attenuation 01407 else if (option=="-atn") 01408 { 01409 if (i>=argc-1) 01410 { 01411 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01412 Exit(EXIT_FAILURE); 01413 } 01414 01415 path_to_attenuation_img = argv[i+1]; 01416 01417 if(path_to_attenuation_img != "") // parse 01418 { 01419 // Retrieve nb of gated images from header if required 01420 Intf_fields IF; 01421 IntfKeyInitFields(&IF); 01422 if(IntfReadHeader(path_to_attenuation_img, &IF, 0) ) 01423 { 01424 Cerr("***** castor-recon() -> An error occurred while trying to read the interfile header of attenuation file " << path_to_attenuation_img << " !" << endl); 01425 Exit(EXIT_FAILURE); 01426 } 01427 nb_atn_resp_imgs = IF.nb_resp_gates; 01428 nb_atn_card_imgs = IF.nb_card_gates; 01429 } 01430 i++; 01431 } 01432 01433 // -------------------------------------------------------------------------------- 01434 // Output settings 01435 // -------------------------------------------------------------------------------- 01436 01437 // Name of the output directory 01438 else if (option=="-dout") // This is a mandatory option 01439 { 01440 if (i>=argc-1) 01441 { 01442 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01443 Exit(EXIT_FAILURE); 01444 } 01445 path_dout = argv[i+1]; 01446 i++; 01447 } 01448 // Base name of the output files 01449 else if (option=="-fout") // This is a mandatory option 01450 { 01451 if (i>=argc-1) 01452 { 01453 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01454 Exit(EXIT_FAILURE); 01455 } 01456 path_fout = argv[i+1]; 01457 i++; 01458 } 01459 // List of iterations to be outputed 01460 else if (option=="-oit") 01461 { 01462 if (i>=argc-1) 01463 { 01464 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01465 Exit(EXIT_FAILURE); 01466 } 01467 output_iterations = (string)argv[i+1]; 01468 i++; 01469 } 01470 // Flag to say that we want to save time basis functions too 01471 else if (option=="-omd") 01472 { 01473 merge_dynamic_imgs_flag = true; 01474 } 01475 // Flag to say that we want to save time basis functions too 01476 else if (option=="-olut") 01477 { 01478 save_LUT_flag = true; 01479 } 01480 // Flag to say that we want to save the sensitivity image for each subset/iteration in histogram mode 01481 else if (option=="-osens") 01482 { 01483 save_sens_histo = true; 01484 } 01485 // Flag to say that we want to save the image after each subset 01486 else if (option=="-osub") 01487 { 01488 save_subset_image = true; 01489 } 01490 // Flag to say that we want to save time basis functions too 01491 else if (option=="-otb") 01492 { 01493 Cerr("!!!!! castor-recon() -> Warning: option -otb not yet implemented !" << endl); 01494 } 01495 // Flag to say that we exit directly after computing and saving the sensitivity 01496 else if (option=="-sens-only") 01497 { 01498 exit_after_sensitivity = true; 01499 } 01500 01501 // -------------------------------------------------------------------------------- 01502 // Algorithm settings 01503 // -------------------------------------------------------------------------------- 01504 01505 // List of iterations/subsets 01506 else if (option=="-it") // This is a mandatory option 01507 { 01508 if (i>=argc-1) 01509 { 01510 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01511 Exit(EXIT_FAILURE); 01512 } 01513 nb_iterations_subsets = (string)argv[i+1]; 01514 i++; 01515 } 01516 // Optimizer settings 01517 else if (option=="-opti") 01518 { 01519 if (i>=argc-1) 01520 { 01521 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01522 Exit(EXIT_FAILURE); 01523 } 01524 options_optimizer = (string)argv[i+1]; 01525 i++; 01526 } 01527 // Optimizer FOM 01528 else if (option=="-opti-fom") 01529 { 01530 optimizer_fom = true; 01531 } 01532 // Optimizer image update stat 01533 else if (option=="-opti-stat") 01534 { 01535 optimizer_stat = true; 01536 } 01537 // Penalty settings 01538 else if (option=="-penalty") 01539 { 01540 if (i>=argc-1) 01541 { 01542 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01543 Exit(EXIT_FAILURE); 01544 } 01545 options_penalty = (string)argv[i+1]; 01546 i++; 01547 } 01548 // Image convolver settings 01549 else if (option=="-conv") 01550 { 01551 if (i>=argc-1) 01552 { 01553 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01554 Exit(EXIT_FAILURE); 01555 } 01556 string convolver = (string)argv[i+1]; 01557 options_image_convolver.push_back(convolver); 01558 i++; 01559 } 01560 // Image processing settings 01561 else if (option=="-proc") 01562 { 01563 if (i>=argc-1) 01564 { 01565 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01566 Exit(EXIT_FAILURE); 01567 } 01568 string module = (string)argv[i+1]; 01569 options_image_processing.push_back(module); 01570 i++; 01571 } 01572 01573 // -------------------------------------------------------------------------------- 01574 // Projection settings 01575 // -------------------------------------------------------------------------------- 01576 01577 // Projector settings 01578 else if (option=="-proj") 01579 { 01580 if (i>=argc-1) 01581 { 01582 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01583 Exit(EXIT_FAILURE); 01584 } 01585 options_projectorF = (string)argv[i+1]; 01586 options_projectorB = (string)argv[i+1]; 01587 i++; 01588 } 01589 // Forward projector settings 01590 else if (option=="-projF") 01591 { 01592 if (i>=argc-1) 01593 { 01594 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01595 Exit(EXIT_FAILURE); 01596 } 01597 options_projectorF = (string)argv[i+1]; 01598 i++; 01599 } 01600 // Backward projector settings 01601 else if (option=="-projB") 01602 { 01603 if (i>=argc-1) 01604 { 01605 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01606 Exit(EXIT_FAILURE); 01607 } 01608 options_projectorB = (string)argv[i+1]; 01609 i++; 01610 } 01611 // Common projector settings 01612 else if (option=="-proj-common") 01613 { 01614 if (i>=argc-1) 01615 { 01616 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01617 Exit(EXIT_FAILURE); 01618 } 01619 options_projector_common = (string)argv[i+1]; 01620 i++; 01621 } 01622 // Ignore TOF flag 01623 else if (option=="-ignore-TOF") 01624 { 01625 ignore_TOF = true; 01626 } 01627 // Ignore POI flag 01628 else if (option=="-ignore-POI") 01629 { 01630 ignore_POI = true; 01631 } 01632 // Projection line computation strategy 01633 else if (option=="-proj-comp") 01634 { 01635 if (i>=argc-1) 01636 { 01637 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01638 Exit(EXIT_FAILURE); 01639 } 01640 projector_computation_strategy = atoi(argv[i+1]); 01641 i++; 01642 } 01643 01644 // -------------------------------------------------------------------------------- 01645 // Quantification settings 01646 // -------------------------------------------------------------------------------- 01647 01648 // Corrections settings 01649 else if (option=="-ignore-corr") 01650 { 01651 if (i>=argc-1) 01652 { 01653 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01654 Exit(EXIT_FAILURE); 01655 } 01656 ignored_corrections = (string)argv[i+1]; 01657 i++; 01658 } 01659 01660 // -------------------------------------------------------------------------------- 01661 // Computation settings 01662 // -------------------------------------------------------------------------------- 01663 01664 // Flag to say that we want to use the GPU 01665 #ifdef CASTOR_GPU 01666 else if (option=="-gpu") 01667 { 01668 gpu_flag = 1; 01669 } 01670 #endif 01671 // Number of threads 01672 #ifdef CASTOR_OMP 01673 else if (option=="-th") 01674 { 01675 if (i>=argc-1) 01676 { 01677 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01678 Exit(EXIT_FAILURE); 01679 } 01680 nb_threads = (string)argv[i+1]; 01681 i++; 01682 } 01683 #else 01684 else if (option=="-th") 01685 { 01686 if (i>=argc-1) 01687 { 01688 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01689 Exit(EXIT_FAILURE); 01690 } 01691 Cerr("!!!!! castor-recon() -> Option -th is available only if the code is compiled using the CASTOR_OMP environment variable set to 1 !" << endl); 01692 Cerr(" Press enter to continue with the execution BUT with only one thread." << endl); 01693 Cerr(" Or kill this and compile CASToR with OpenMP." << endl); 01694 getchar(); 01695 i++; 01696 } 01697 #endif 01698 // Size of the buffer for data reading 01699 else if (option=="-load") 01700 { 01701 if (i>=argc-1) 01702 { 01703 Cerr("***** castor-recon() -> Argument missing for option: " << option << endl); 01704 Exit(EXIT_FAILURE); 01705 } 01706 if (ConvertFromString(argv[i+1], &data_file_percentage_load)) 01707 { 01708 Cerr("***** castor-recon() -> Error while trying to convert variable for option " << option << endl); 01709 Exit(EXIT_FAILURE); 01710 } 01711 if (data_file_percentage_load>100 || data_file_percentage_load<0) 01712 { 01713 Cerr("***** castor-recon() -> Incorrect initialization of the size data buffer" << endl); 01714 Cerr(" Number provided: " << argv[i+1] << " is not in the expected [0;100] interval" << endl); 01715 Exit(EXIT_FAILURE); 01716 } 01717 i++; 01718 } 01719 01720 // -------------------------------------------------------------------------------- 01721 // Unknown option! 01722 // -------------------------------------------------------------------------------- 01723 01724 else 01725 { 01726 Cerr("***** castor-recon() -> Unknown option '" << option << "' !" << endl); 01727 Exit(EXIT_FAILURE); 01728 } 01729 } 01730 01731 // Synchronize MPI processes 01732 #ifdef CASTOR_MPI 01733 MPI_Barrier(MPI_COMM_WORLD); 01734 #endif 01735 01736 // Affect specific verbose leves if not set 01737 if (verbose_algo==-1) verbose_algo = verbose_general; 01738 if (verbose_opti==-1) verbose_opti = verbose_general; 01739 if (verbose_proj==-1) verbose_proj = verbose_general; 01740 if (verbose_conv==-1) verbose_conv = verbose_general; 01741 if (verbose_proc==-1) verbose_proc = verbose_general; 01742 if (verbose_scan==-1) verbose_scan = verbose_general; 01743 if (verbose_data==-1) verbose_data = verbose_general; 01744 if (verbose_defo==-1) verbose_defo = verbose_general; 01745 if (verbose_dyna==-1) verbose_dyna = verbose_general; 01746 if (verbose_sens==-1) verbose_sens = verbose_general; 01747 01748 // ============================================================================================================ 01749 // Some checks 01750 // ============================================================================================================ 01751 01752 // Data files 01753 if (nb_beds < 1) 01754 { 01755 Cerr("***** castor-recon() -> Please provide at least one data filename !" << endl); 01756 Exit(EXIT_FAILURE); 01757 } 01758 // Output files 01759 if (path_fout.empty() && path_dout.empty()) 01760 { 01761 Cerr("***** castor-recon() -> Please provide an output option for output files (-fout or -dout) !" << endl); 01762 Exit(EXIT_FAILURE); 01763 } 01764 // Check that only one option has been provided 01765 if (!path_fout.empty() && !path_dout.empty()) 01766 { 01767 Cerr("***** castor-recon() -> Please provide either output option -fout or -dout but not both !" << endl); 01768 Exit(EXIT_FAILURE); 01769 } 01770 01771 // Check if gated reconstruction is enabled but no file describing the gating of the data has been provided 01772 // TODO: maybe do it in the dynamic data manager if possible to clean this main as much as possible 01773 if ( (nb_resp_gates>1 || nb_card_gates>1) && path_to_4D_data_splitting_file.empty() ) 01774 { 01775 Cerr("***** castor-recon() -> gating is enabled, but no file describing the splitting of the data has been provided (-gating option) !" << endl); 01776 Exit(EXIT_FAILURE); 01777 } 01778 01779 // ============================================================================================================ 01780 // Singletons initialization: create here all needed singletons 01781 // ============================================================================================================ 01782 01783 if (verbose_general>=5) Cout("----- Singletons initializations ... -----" << endl); 01784 01785 // Get user endianness (interfile I/O) 01786 GetUserEndianness(); 01787 01788 // ---------------------------------------------------------------------------------------- 01789 // Create sOutputManager 01790 // ---------------------------------------------------------------------------------------- 01791 sOutputManager* p_outputManager = sOutputManager::GetInstance(); 01792 // Set verbose level 01793 p_outputManager->SetVerbose(verbose_general); 01794 // Set MPI rank 01795 p_outputManager->SetMPIRank(mpi_rank); 01796 // Set output dynamic image policy 01797 p_outputManager->SetMergeDynImagesFlag(merge_dynamic_imgs_flag); 01798 01799 // Set path to the config directory 01800 if (p_outputManager->CheckConfigDir(path_to_config_dir)) 01801 { 01802 Cerr("***** castor-recon() -> A problem occured while checking for the config directory path !" << endl); 01803 Exit(EXIT_FAILURE); 01804 } 01805 // Initialize output directory and base name 01806 if (p_outputManager->InitOutputDirectory(path_fout, path_dout)) 01807 { 01808 Cerr("***** castor-recon() -> A problem occured while initializing output directory !" << endl); 01809 Exit(EXIT_FAILURE); 01810 } 01811 // Log command line 01812 if (p_outputManager->LogCommandLine(argc,argv)) 01813 { 01814 Cerr("***** castor-recon() -> A problem occured while logging command line arguments !" << endl); 01815 Exit(EXIT_FAILURE); 01816 } 01817 01818 // ---------------------------------------------------------------------------------------- 01819 // Create sScannerManager 01820 // ---------------------------------------------------------------------------------------- 01821 sScannerManager* p_ScannerManager = sScannerManager::GetInstance(); 01822 p_ScannerManager->SetVerbose(verbose_scan); 01823 p_ScannerManager->SetSaveLUTFlag(save_LUT_flag); 01824 01825 if (verbose_general>=5) Cout("----- Singletons initializations OK -----" << endl); 01826 01827 // ============================================================================================================ 01828 // Objects initialization: create here all elements needed for the algorithm 01829 // ============================================================================================================ 01830 01831 if (verbose_general>=5) Cout("----- Geometry Initialization ... -----" << endl); 01832 01833 // ---------------------------------------------------------------------------------------- 01834 // Search the type of scanner using the sScannerManager 01835 // ---------------------------------------------------------------------------------------- 01836 01837 // TODO: put all that stuff into only one function taking the path_to_data_filename[0] as the only parameter 01838 01839 // Get system name from the dataFile 01840 string scanner_name = ""; 01841 if (ReadDataASCIIFile(path_to_data_filename[0], "Scanner name", &scanner_name, 1, KEYWORD_MANDATORY)) 01842 { 01843 Cerr("***** castor-recon() -> A problem occured while trying to find the system name in the datafile header !" << endl); 01844 Exit(EXIT_FAILURE); 01845 } 01846 if (p_ScannerManager->FindScannerSystem(scanner_name) ) 01847 { 01848 Cerr("***** castor-recon() -> A problem occurred while searching for scanner system !" << endl); 01849 Exit(EXIT_FAILURE); 01850 } 01851 if (p_ScannerManager->BuildScannerObject() ) 01852 { 01853 Cerr("***** castor-recon() -> A problem occurred during scanner object construction ! !" << endl); 01854 Exit(EXIT_FAILURE); 01855 } 01856 if (p_ScannerManager->InstantiateScanner() ) 01857 { 01858 Cerr("***** castor-recon() -> A problem occurred while creating Scanner object !" << endl); 01859 Exit(EXIT_FAILURE); 01860 } 01861 if (p_ScannerManager->GetGeometricInfoFromDatafile(path_to_data_filename[0]) ) 01862 { 01863 Cerr("***** castor-recon() -> A problem occurred while retrieving scanner fields from the datafile header !" << endl); 01864 Exit(EXIT_FAILURE); 01865 } 01866 if (p_ScannerManager->BuildLUT() ) 01867 { 01868 Cerr("***** castor-recon() -> A problem occurred while generating/reading the LUT !" << endl); 01869 Exit(EXIT_FAILURE); 01870 } 01871 // Check the scanner manager parameters and initialize the scanner 01872 if (p_ScannerManager->CheckParameters()) 01873 { 01874 Cerr("***** castor-recon() -> A problem occured while checking scanner manager parameters !" << endl); 01875 Exit(EXIT_FAILURE); 01876 } 01877 if (p_ScannerManager->Initialize()) 01878 { 01879 Cerr("***** castor-recon() -> A problem occured while initializing scanner !" << endl); 01880 Exit(EXIT_FAILURE); 01881 } 01882 01883 if (verbose_general>=5) Cout("----- Geometry Initialization OK -----" << endl); 01884 01885 // If no number of voxels provided, then get the default ones from the scanner 01886 if (nb_voxX<=0 || nb_voxY<=0 || nb_voxZ<=0) 01887 { 01888 if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "voxels number transaxial", &nb_voxX, 1, KEYWORD_MANDATORY)) 01889 { 01890 Cerr("***** castor-recon() -> A problem occured while reading for default number of transaxial voxels !" << endl); 01891 Exit(EXIT_FAILURE); 01892 } 01893 if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "voxels number transaxial", &nb_voxY, 1, KEYWORD_MANDATORY)) 01894 { 01895 Cerr("***** castor-recon() -> A problem occured while reading for default number of transaxial voxels !" << endl); 01896 Exit(EXIT_FAILURE); 01897 } 01898 if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "voxels number axial", &nb_voxZ, 1, KEYWORD_MANDATORY)) 01899 { 01900 Cerr("***** castor-recon() -> A problem occured while reading for default number of axial voxels !" << endl); 01901 Exit(EXIT_FAILURE); 01902 } 01903 } 01904 // If no FOV nor VOX size provided, then get the default one 01905 if ( (fov_sizeX<=0 || fov_sizeY<=0 || fov_sizeZ<=0) && (vox_sizeX<=0 || vox_sizeY<=0 || vox_sizeZ<=0) ) 01906 { 01907 if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "field of view transaxial", &fov_sizeX, 1, KEYWORD_MANDATORY)) 01908 { 01909 Cerr("***** castor-recon() -> A problem occured while reading for default transaxial FOV size !" << endl); 01910 Exit(EXIT_FAILURE); 01911 } 01912 if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "field of view transaxial", &fov_sizeY, 1, KEYWORD_MANDATORY)) 01913 { 01914 Cerr("***** castor-recon() -> A problem occured while reading for default transaxial FOV size !" << endl); 01915 Exit(EXIT_FAILURE); 01916 } 01917 if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "field of view axial", &fov_sizeZ, 1, KEYWORD_MANDATORY)) 01918 { 01919 Cerr("***** castor-recon() -> A problem occured while reading for default axial FOV size !" << endl); 01920 Exit(EXIT_FAILURE); 01921 } 01922 } 01923 01924 // ---------------------------------------------------------------------------------------- 01925 // Create oImageDimensionsAndQuantification 01926 // ---------------------------------------------------------------------------------------- 01927 01928 if (verbose_general>=5) Cout("----- Image dimensions initialization ... -----" << endl); 01929 01930 oImageDimensionsAndQuantification* p_ImageDimensionsAndQuantification = new oImageDimensionsAndQuantification(); 01931 if (p_ImageDimensionsAndQuantification->SetNbThreads(nb_threads)) 01932 { 01933 Cerr("***** castor-recon() -> A problem occured while setting the number of threads !" << endl); 01934 Exit(EXIT_FAILURE); 01935 } 01936 p_ImageDimensionsAndQuantification->SetNbBeds(nb_beds); 01937 p_ImageDimensionsAndQuantification->SetNbVoxX(nb_voxX); 01938 p_ImageDimensionsAndQuantification->SetNbVoxY(nb_voxY); 01939 p_ImageDimensionsAndQuantification->SetNbVoxZ(nb_voxZ); 01940 p_ImageDimensionsAndQuantification->SetVoxSizeX(vox_sizeX); 01941 p_ImageDimensionsAndQuantification->SetVoxSizeY(vox_sizeY); 01942 p_ImageDimensionsAndQuantification->SetVoxSizeZ(vox_sizeZ); 01943 p_ImageDimensionsAndQuantification->SetFOVSizeX(fov_sizeX); 01944 p_ImageDimensionsAndQuantification->SetFOVSizeY(fov_sizeY); 01945 p_ImageDimensionsAndQuantification->SetFOVSizeZ(fov_sizeZ); 01946 p_ImageDimensionsAndQuantification->SetFOVOutMasking(fov_out,slice_out); 01947 p_ImageDimensionsAndQuantification->SetOffsetX(offsetX); 01948 p_ImageDimensionsAndQuantification->SetOffsetY(offsetY); 01949 p_ImageDimensionsAndQuantification->SetOffsetZ(offsetZ); 01950 p_ImageDimensionsAndQuantification->SetMPIRankAndSize(mpi_rank, mpi_size); 01951 p_ImageDimensionsAndQuantification->SetVerbose(verbose_data); 01952 p_ImageDimensionsAndQuantification->SetIgnoredCorrections(ignored_corrections); 01953 p_ImageDimensionsAndQuantification->SetFrames(frame_list); 01954 p_ImageDimensionsAndQuantification->SetNbTimeBasisFunctions(nb_time_basis); 01955 p_ImageDimensionsAndQuantification->SetTimeBasisFunctionsFile(path_to_time_basis_coef); 01956 if (p_ImageDimensionsAndQuantification->SetFlipOut(flip_out)) 01957 { 01958 Cerr("***** castor-recon() -> A problem occured while setting the output flip option !" << endl); 01959 Exit(EXIT_FAILURE); 01960 } 01961 if (resp_motion_options=="") 01962 { 01963 p_ImageDimensionsAndQuantification->SetNbRespGates(nb_resp_gates); 01964 p_ImageDimensionsAndQuantification->SetNbRespBasisFunctions(nb_resp_basis); 01965 p_ImageDimensionsAndQuantification->SetRespBasisFunctionsFile(path_to_resp_basis_coef); 01966 } 01967 else 01968 { 01969 if (path_to_resp_basis_coef!="") 01970 { 01971 Cerr("***** castor-recon() -> Cannot use both respiratory motion correction and respiratory basis functions, it has no sense !" << endl); 01972 Exit(EXIT_FAILURE); 01973 } 01974 // Set only one gate here because we correct for motion, so we reconstruct only one image 01975 p_ImageDimensionsAndQuantification->SetNbRespGates(1); 01976 } 01977 if (card_motion_options=="") 01978 { 01979 p_ImageDimensionsAndQuantification->SetNbCardGates(nb_card_gates); 01980 p_ImageDimensionsAndQuantification->SetNbCardBasisFunctions(nb_card_basis); 01981 p_ImageDimensionsAndQuantification->SetCardBasisFunctionsFile(path_to_card_basis_coef); 01982 } 01983 else 01984 { 01985 if (path_to_card_basis_coef!="") 01986 { 01987 Cerr("***** castor-recon() -> Cannot use both cardiac motion correction and cardiac basis functions, it has no sense !" << endl); 01988 Exit(EXIT_FAILURE); 01989 } 01990 // Set only one gate here because we correct for motion, so we reconstruct only one image 01991 p_ImageDimensionsAndQuantification->SetNbCardGates(1); 01992 } 01993 if (p_ImageDimensionsAndQuantification->CheckParameters()) 01994 { 01995 Cerr("***** castor-recon() -> A problem occured while checking image dimensions parameters !" << endl); 01996 Exit(EXIT_FAILURE); 01997 } 01998 if (p_ImageDimensionsAndQuantification->Initialize()) 01999 { 02000 Cerr("***** castor-recon() -> A problem occured while initializing image dimensions !" << endl); 02001 Exit(EXIT_FAILURE); 02002 } 02003 // Initialization of DynamicDataManager class, related 4D data splitting management 02004 if (p_ImageDimensionsAndQuantification->InitDynamicData(path_to_4D_data_splitting_file, 02005 !resp_motion_options.empty(), 02006 !card_motion_options.empty(), 02007 !inv_motion_options.empty(), 02008 nb_resp_gates, 02009 nb_card_gates) ) 02010 { 02011 Cerr("***** castor-recon() -> A problem occured while initializing Dynamic data manager's class !" << endl); 02012 Exit(EXIT_FAILURE); 02013 } 02014 // Get the number of events in the data from the header (in order to check consistency between 02015 // the number of events in the datafile and in the dynamic files, if any gating is enabled) 02016 int64_t nb_events = 0; 02017 ReadDataASCIIFile(path_to_data_filename[0], "Number of events", &nb_events, 1, KEYWORD_MANDATORY); 02018 // Check dynamic parameters 02019 if (p_ImageDimensionsAndQuantification->CheckDynamicParameters(nb_events) ) 02020 { 02021 Cerr("***** castor-recon() -> A problem occured while checking Dynamic data manager's parameters !" << endl); 02022 Exit(EXIT_FAILURE); 02023 } 02024 // Initialize dynamic specific quantitative factors 02025 if (p_ImageDimensionsAndQuantification->SetDynamicSpecificQuantificationFactors(path_to_dynamic_quantification_file) ) 02026 { 02027 Cerr("***** castor-recon() -> A problem occured while initializing specific dynamic quantification factors!" << endl); 02028 Exit(EXIT_FAILURE); 02029 } 02030 02031 if (verbose_general>=5) Cout("----- Image dimensions initialization OK -----" << endl); 02032 02033 // ---------------------------------------------------------------------------------------- 02034 // Random Number Generator initialization: (we first require to know the number of threads to use from p_ImageDimensionsAndQuantification) 02035 // ---------------------------------------------------------------------------------------- 02036 02037 if (verbose_general>=5) Cout("----- Random number generator initialization ... -----" << endl); 02038 02039 sRNG* p_RNG = sRNG::GetInstance(); 02040 p_RNG->SetVerbose(verbose_general); 02041 // Use a user-provided seed to initialize the RNG if one has been provided. Use random number otherwise. 02042 if (seed_RNG>=0) p_RNG->Initialize(seed_RNG, p_ImageDimensionsAndQuantification->GetNbThreadsMax()); 02043 else p_RNG->Initialize(p_ImageDimensionsAndQuantification->GetNbThreadsMax()); 02044 02045 if (verbose_general >=5) Cout("----- Random number generator initialization OK -----" << endl); 02046 02047 // ---------------------------------------------------------------------------------------- 02048 // Create vDataFile and vScanner 02049 // ---------------------------------------------------------------------------------------- 02050 02051 if(verbose_general>=5) Cout("----- Datafile initialization ... -----" << endl); 02052 02053 vDataFile** p_DataFile = new vDataFile*[nb_beds]; 02054 02055 if (p_ScannerManager->GetScannerType() == SCANNER_PET) 02056 { 02057 // Create specific data file 02058 for (int i=0 ; i<nb_beds ; i++) 02059 { 02060 p_DataFile[i] = new iDataFilePET(); //TODO recup load data file ou pas 02061 (dynamic_cast<iDataFilePET*>(p_DataFile[i]))->SetIgnoreTOFFlag(ignore_TOF); 02062 } 02063 } 02064 else if (p_ScannerManager->GetScannerType() == SCANNER_SPECT_CONVERGENT) 02065 { 02066 // Create specific data file 02067 for (int i=0 ; i<nb_beds ; i++) 02068 { 02069 p_DataFile[i] = new iDataFileSPECT(); 02070 } 02071 } 02072 // Unknown scanner 02073 else 02074 { 02075 Cerr("***** castor-recon() -> Unknown scanner type (" << p_ScannerManager->GetScannerType() << ") detected by sScannerManager ! Abort." << endl); 02076 Exit(EXIT_FAILURE); 02077 } 02078 02079 // Load raw data in memory and do other stuff if needed. 02080 for (int bed=0 ; bed<nb_beds ; bed++) 02081 { 02082 p_DataFile[bed]->SetHeaderDataFileName(path_to_data_filename.at(bed)); 02083 p_DataFile[bed]->SetBedIndex(bed); 02084 p_DataFile[bed]->SetPercentageLoad(data_file_percentage_load); 02085 p_DataFile[bed]->SetVerbose(verbose_data); 02086 p_DataFile[bed]->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02087 p_DataFile[bed]->SetIgnorePOIFlag(ignore_POI); 02088 if (p_DataFile[bed]->ReadInfoInHeader()) 02089 { 02090 Cerr("***** castor-recon() -> A problem occurred during datafile header reading ! Abort." << endl); 02091 Exit(EXIT_FAILURE); 02092 } 02093 if (p_DataFile[bed]->CheckParameters()) 02094 { 02095 Cerr("***** castor-recon() -> A problem occurred while checking datafile parameters ! Abort." << endl); 02096 Exit(EXIT_FAILURE); 02097 } 02098 if (p_DataFile[bed]->ComputeSizeEvent()) 02099 { 02100 Cerr("***** castor-recon() -> A problem occurred in datafile initialization ! Abort." << endl); 02101 Exit(EXIT_FAILURE); 02102 } 02103 if (p_DataFile[bed]->InitializeFile()) 02104 { 02105 Cerr("***** castor-recon() -> A problem occurred in datafile initialization ! Abort." << endl); 02106 Exit(EXIT_FAILURE); 02107 } 02108 // Allocate events for reading 02109 if (p_DataFile[bed]->PrepareDataFile()) 02110 { 02111 Cerr("***** castor-recon() -> A problem occured in datafile preparation ! Abort." << endl); 02112 Exit(EXIT_FAILURE); 02113 } 02114 // TODO: for all data files (except first), check consistency with the first data file (call a function to do that) 02115 } 02116 02117 if (verbose_general>=5) Cout("----- Datafile initialization OK -----" << endl); 02118 02119 // ---------------------------------------------------------------------------------------- 02120 // Create Projector Manager 02121 // ---------------------------------------------------------------------------------------- 02122 02123 // Verbose 02124 if (verbose_general>=5) Cout("----- Projector initialization ... -----" << endl); 02125 // Create object 02126 oProjectorManager* p_ProjectorManager = new oProjectorManager(); 02127 // Set all parameters 02128 p_ProjectorManager->SetScanner(p_ScannerManager->GetScannerObject()); 02129 p_ProjectorManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02130 p_ProjectorManager->SetDataFile(p_DataFile[0]); 02131 p_ProjectorManager->SetComputationStrategy(projector_computation_strategy); 02132 p_ProjectorManager->SetOptionsForward(options_projectorF); 02133 p_ProjectorManager->SetOptionsBackward(options_projectorB); 02134 p_ProjectorManager->SetOptionsCommon(options_projector_common); 02135 p_ProjectorManager->SetVerbose(verbose_proj); 02136 // Check parameters 02137 if (p_ProjectorManager->CheckParameters()) 02138 { 02139 Cerr("***** castor-recon() -> A problem occured while checking projector manager's parameters !" << endl); 02140 Exit(EXIT_FAILURE); 02141 } 02142 // Initialize projector manager 02143 if (p_ProjectorManager->Initialize()) 02144 { 02145 Cerr("***** castor-recon() -> A problem occured while initializing projector manager !" << endl); 02146 Exit(EXIT_FAILURE); 02147 } 02148 // Verbose 02149 if (verbose_general>=5) Cout("----- Projector initialization OK -----" << endl); 02150 02151 // ---------------------------------------------------------------------------------------- 02152 // Create Optimizer Manager 02153 // ---------------------------------------------------------------------------------------- 02154 02155 // Verbose 02156 if (verbose_general>=5) Cout("----- Optimizer initialization ... -----" << endl); 02157 // Create object 02158 oOptimizerManager* p_OptimizerManager = new oOptimizerManager(); 02159 // Set all parameters 02160 p_OptimizerManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02161 p_OptimizerManager->SetDataMode(p_DataFile[0]->GetDataMode()); 02162 p_OptimizerManager->SetDataType(p_DataFile[0]->GetDataType()); 02163 p_OptimizerManager->SetOptionsOptimizer(options_optimizer); 02164 p_OptimizerManager->SetOptimizerFOMFlag(optimizer_fom); 02165 p_OptimizerManager->SetOptimizerImageStatFlag(optimizer_stat); 02166 p_OptimizerManager->SetOptionsPenalty(options_penalty); 02167 p_OptimizerManager->SetNbTOFBins(p_ProjectorManager->GetNbTOFBins()); 02168 p_OptimizerManager->SetVerbose(verbose_opti); 02169 // Check parameters 02170 if (p_OptimizerManager->CheckParameters()) 02171 { 02172 Cerr("***** castor-recon() -> A problem occured while checking optimizer manager's parameters !" << endl); 02173 Exit(EXIT_FAILURE); 02174 } 02175 // Initialize optimizer manager 02176 if (p_OptimizerManager->Initialize()) 02177 { 02178 Cerr("***** castor-recon() -> A problem occured while initializing optimizer manager !" << endl); 02179 Exit(EXIT_FAILURE); 02180 } 02181 // Verbose 02182 if (verbose_general>=5) Cout("----- Optimizer initialization OK -----" << endl); 02183 02184 // ---------------------------------------------------------------------------------------- 02185 // Create Image Convolver Manager 02186 // ---------------------------------------------------------------------------------------- 02187 02188 // Verbose 02189 if (verbose_general>=5) Cout("----- Image Convolver initialization (if any) ... -----" << endl); 02190 // Create object 02191 oImageConvolverManager* p_ImageConvolverManager = new oImageConvolverManager(); 02192 // Set all parameters 02193 p_ImageConvolverManager->SetVerbose(verbose_conv); 02194 p_ImageConvolverManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02195 p_ImageConvolverManager->SetOptions(options_image_convolver); 02196 // Check parameters 02197 if (p_ImageConvolverManager->CheckParameters()) 02198 { 02199 Cerr("***** castor-recon() -> A problem occured while checking image convolver manager's parameters !" << endl); 02200 Exit(EXIT_FAILURE); 02201 } 02202 // Initialize image convolver manager 02203 if (p_ImageConvolverManager->Initialize()) 02204 { 02205 Cerr("***** castor-recon() -> A problem occured while initializing image convolver manager !" << endl); 02206 Exit(EXIT_FAILURE); 02207 } 02208 // Verbose 02209 if (verbose_general>=5) Cout("----- Image Convolver initialization OK -----" << endl); 02210 02211 // ---------------------------------------------------------------------------------------- 02212 // Create Image Processing Manager 02213 // ---------------------------------------------------------------------------------------- 02214 02215 // Verbose 02216 if (verbose_general>=5) Cout("----- Image Processing initialization (if any) ... -----" << endl); 02217 // Create object 02218 oImageProcessingManager* p_ImageProcessingManager = new oImageProcessingManager(); 02219 // Set all parameters 02220 p_ImageProcessingManager->SetVerbose(verbose_proc); 02221 p_ImageProcessingManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02222 p_ImageProcessingManager->SetOptions(options_image_processing); 02223 // Check parameters 02224 if (p_ImageProcessingManager->CheckParameters()) 02225 { 02226 Cerr("***** castor-recon() -> A problem occured while checking image processing manager's parameters !" << endl); 02227 Exit(EXIT_FAILURE); 02228 } 02229 // Initialize image processing manager 02230 if (p_ImageProcessingManager->Initialize()) 02231 { 02232 Cerr("***** castor-recon() -> A problem occured while initializing image processing manager !" << endl); 02233 Exit(EXIT_FAILURE); 02234 } 02235 // Verbose 02236 if (verbose_general>=5) Cout("----- Image Processing initialization OK -----" << endl); 02237 02238 // ---------------------------------------------------------------------------------------- 02239 // Create Dynamic Model Manager 02240 // ---------------------------------------------------------------------------------------- 02241 02242 // Verbose 02243 if (verbose_general>=5) Cout("----- Dynamic model initialization (if any) ... -----" << endl); 02244 // Create object 02245 oDynamicModelManager* p_DynamicModelManager = new oDynamicModelManager(); 02246 // Set all parameters 02247 p_DynamicModelManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02248 p_DynamicModelManager->SetOptions(dynamic_model_options); 02249 p_DynamicModelManager->SetVerbose(verbose_dyna); 02250 // Check parameters 02251 if (p_DynamicModelManager->CheckParameters()) 02252 { 02253 Cerr("***** castor-recon() -> A problem occured while checking dynamic model manager's parameters !" << endl); 02254 Exit(EXIT_FAILURE); 02255 } 02256 // Initialize optimizer manager 02257 if (p_DynamicModelManager->Initialize()) 02258 { 02259 Cerr("***** castor-recon() -> A problem occured while initializing dynamic model manager !" << endl); 02260 Exit(EXIT_FAILURE); 02261 } 02262 // Verbose 02263 if (verbose_general>=5) Cout("----- Dynamic model initialization OK -----" << endl); 02264 02265 // ---------------------------------------------------------------------------------------- 02266 // Create Deformation Manager 02267 // ---------------------------------------------------------------------------------------- 02268 02269 // Verbose 02270 if (verbose_general>=5) Cout("----- Image deformation initialization (if any) ... -----" << endl); 02271 // Create object 02272 oDeformationManager* p_DeformationManager = new oDeformationManager(); 02273 // Set all parameters 02274 p_DeformationManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02275 p_DeformationManager->SetDataMode(p_DataFile[0]->GetDataMode()); // required to know if sensitivity image deformation should be enabled 02276 p_DeformationManager->SetOptionsResp(resp_motion_options, nb_resp_gates); 02277 p_DeformationManager->SetOptionsCard(card_motion_options, nb_card_gates); 02278 p_DeformationManager->SetOptionsInv(inv_motion_options); 02279 p_DeformationManager->SetVerbose(verbose_defo); 02280 // Check parameters 02281 if (p_DeformationManager->CheckParameters()) 02282 { 02283 Cerr("***** castor-recon() -> A problem occured while checking image deformation manager's parameters !" << endl); 02284 Exit(EXIT_FAILURE); 02285 } 02286 // Initialize optimizer manager 02287 if (p_DeformationManager->Initialize()) 02288 { 02289 Cerr("***** castor-recon() -> A problem occured while initializing image deformation manager !" << endl); 02290 Exit(EXIT_FAILURE); 02291 } 02292 // Verbose 02293 if (verbose_general >=5) Cout("----- Image deformation initialization OK -----" << endl); 02294 02295 // ---------------------------------------------------------------------------------------- 02296 // Create the image space 02297 // ---------------------------------------------------------------------------------------- 02298 02299 oImageSpace* p_ImageSpace = new oImageSpace(); 02300 p_ImageSpace->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02301 p_ImageSpace->SetVerbose(verbose_data); 02302 02303 // ============================================================================================================ 02304 // Algorithm initialization: create here sensitivity computation and launch algorithm 02305 // ============================================================================================================ 02306 02307 // ---------------------------------------------------------------------------------------- 02308 // Create sensitivity only for listmode if the sensitivity is not provided 02309 // ---------------------------------------------------------------------------------------- 02310 if (path_to_sensitivity_img.empty() && p_DataFile[0]->GetDataMode()==MODE_LIST) 02311 { 02312 // Verbose 02313 if (verbose_general>=5) Cout("----- Image Sensitivity generation for list-mode initialization ... -----" << endl); 02314 // Create object 02315 oSensitivityGenerator* p_Sensitivity = new oSensitivityGenerator(); 02316 // Set parameters 02317 p_Sensitivity->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02318 p_Sensitivity->SetImageSpace(p_ImageSpace); 02319 p_Sensitivity->SetScanner(p_ScannerManager->GetScannerObject()); 02320 p_Sensitivity->SetProjectorManager(p_ProjectorManager); 02321 p_Sensitivity->SetImageConvolverManager(p_ImageConvolverManager); 02322 p_Sensitivity->SetDeformationManager(p_DeformationManager); 02323 p_Sensitivity->SetGPUflag(gpu_flag); 02324 p_Sensitivity->SetPathToAttenuationImage(path_to_attenuation_img); 02325 p_Sensitivity->SetNumberOfAtnGateImages(nb_atn_resp_imgs, nb_atn_card_imgs); 02326 p_Sensitivity->SetPathToNormalizationFileName(path_to_normalization_filename); 02327 p_Sensitivity->SetDataFile(p_DataFile); 02328 p_Sensitivity->SetVerbose(verbose_sens); 02329 // Check parameters 02330 if (p_Sensitivity->CheckParameters()) 02331 { 02332 Cerr("***** castor-recon() -> A problem occured while checking parameters of the sensitivity generator !" << endl); 02333 Exit(EXIT_FAILURE); 02334 } 02335 // Initialize the sensitivity generator 02336 if (p_Sensitivity->Initialize()) 02337 { 02338 Cerr("***** castor-recon() -> A problem occured while initializing the sensitivity generator !" << endl); 02339 Exit(EXIT_FAILURE); 02340 } 02341 // Launch the computation 02342 if (p_Sensitivity->Launch()) 02343 { 02344 Cerr("***** castor-recon() -> A problem occured while computing the sensitivity !" << endl); 02345 Exit(EXIT_FAILURE); 02346 } 02347 // Get the path to the sensitivity image (will be given to the algorithm) 02348 path_to_sensitivity_img = p_Sensitivity->GetPathToSensitivityImage(); 02349 // Delete the generator 02350 delete p_Sensitivity; 02351 // Exit now if asked for 02352 if (exit_after_sensitivity) 02353 { 02354 // Delete objects in the inverse order in which they were created 02355 delete p_ImageSpace; 02356 delete p_DeformationManager; 02357 delete p_DynamicModelManager; 02358 delete p_ImageProcessingManager; 02359 delete p_ImageConvolverManager; 02360 delete p_OptimizerManager; 02361 delete p_ProjectorManager; 02362 for (int i=0 ; i<nb_beds ; i++) delete p_DataFile[i]; 02363 delete[] p_DataFile; 02364 delete p_ImageDimensionsAndQuantification; 02365 // And exit 02366 return 0; 02367 } 02368 } 02369 02370 // ---------------------------------------------------------------------------------------- 02371 // Create algorithm 02372 // ---------------------------------------------------------------------------------------- 02373 02374 // Verbose 02375 if (verbose_general>=5) Cout("----- Iterative reconstruction algorithm initialization ... -----" << endl); 02376 // Create object 02377 oIterativeAlgorithm* p_Algorithm = new oIterativeAlgorithm(); 02378 // Set parameters 02379 p_Algorithm->SetImageConvolverManager(p_ImageConvolverManager); 02380 p_Algorithm->SetImageProcessingManager(p_ImageProcessingManager); 02381 p_Algorithm->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification); 02382 p_Algorithm->SetImageSpace(p_ImageSpace); 02383 p_Algorithm->SetProjectorManager(p_ProjectorManager); 02384 p_Algorithm->SetDynamicModelManager(p_DynamicModelManager); 02385 p_Algorithm->SetDeformationManager(p_DeformationManager); 02386 p_Algorithm->SetOptimizerManager(p_OptimizerManager); 02387 p_Algorithm->SetDataFile(p_DataFile); 02388 p_Algorithm->SetGPUflag(gpu_flag); 02389 p_Algorithm->SetVerbose(verbose_algo); 02390 p_Algorithm->SetNbBeds(nb_beds); 02391 p_Algorithm->SetPathInitImage(path_to_initial_img); 02392 p_Algorithm->SetPathToAttenuationImage(path_to_attenuation_img); 02393 p_Algorithm->SetPathToSensitivityImage(path_to_sensitivity_img); 02394 p_Algorithm->SetSaveSensitivityHistoFlag(save_sens_histo); 02395 p_Algorithm->SetSaveSubsetImageFlag(save_subset_image); 02396 if (p_Algorithm->SetNbIterationsAndSubsets(nb_iterations_subsets)) 02397 { 02398 Cerr("***** castor-recon() -> Error while setting the numbers of iterations and subsets !" << endl); 02399 Exit(EXIT_FAILURE); 02400 } 02401 if (p_Algorithm->SetOutputIterations(output_iterations)) 02402 { 02403 Cerr("***** castor-recon() -> Error while setting the selected output iterations !" << endl); 02404 Exit(EXIT_FAILURE); 02405 } 02406 if (p_Algorithm->Iterate()) 02407 { 02408 Cerr("***** castor-recon() -> Error while performing the reconstruction" << endl); 02409 Exit(EXIT_FAILURE); 02410 } 02411 02412 // ============================================================================================================ 02413 // End 02414 // ============================================================================================================ 02415 02416 // Delete objects in the inverse order in which they were created 02417 if (verbose_general>=5) Cout("----- Deleting CASToR objects ... -----" << endl); 02418 delete p_Algorithm; 02419 delete p_ImageSpace; 02420 delete p_DeformationManager; 02421 delete p_DynamicModelManager; 02422 delete p_ImageProcessingManager; 02423 delete p_ImageConvolverManager; 02424 delete p_OptimizerManager; 02425 delete p_ProjectorManager; 02426 for (int i=0 ; i<nb_beds ; i++) delete p_DataFile[i]; 02427 delete[] p_DataFile; 02428 delete p_ImageDimensionsAndQuantification; 02429 if (verbose_general>=5) Cout("----- CASToR objects successfully deleted -----" << endl); 02430 02431 // Ending 02432 if (verbose_general>=1) Cout(endl); 02433 #ifdef CASTOR_MPI 02434 MPI_Finalize(); 02435 #endif 02436 return EXIT_SUCCESS; 02437 }