CASToR  1.0
Tomographic Reconstruction (PET/SPECT)
castor-recon.cc
Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Typedefs Defines