CASToR  1.1
Tomographic Reconstruction (PET/SPECT)
 All Classes Files Functions Variables Typedefs Macros Groups Pages
castor-recon.cc
Go to the documentation of this file.
1 
13 #include "gVariables.hh"
14 #include "gOptions.hh"
15 #include "oIterativeAlgorithm.hh"
16 #include "oSensitivityGenerator.hh"
18 #include "iDataFilePET.hh"
19 #include "iDataFileSPECT.hh"
20 #include "sOutputManager.hh"
21 #include "sScannerManager.hh"
23 #include "iScannerPET.hh"
24 #include "sAddonManager.hh"
25 
26 // =============================================================================================================================================
27 // =============================================================================================================================================
28 // =============================================================================================================================================
29 // H E L P F U N C T I O N S
30 // =============================================================================================================================================
31 // =============================================================================================================================================
32 // =============================================================================================================================================
33 
34 
39 void ShowHelp()
40 {
41  // Return when using MPI and mpi_rank is not 0
42  #ifdef CASTOR_MPI
43  int mpi_rank = 0;
44  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
45  if (mpi_rank!=0) return;
46  #endif
47  // Show help
48  cout << endl;
49  cout << "Usage: castor-recon.exe -df file.cdh -(f/d)out output -it iter [settings]" << endl;
50  cout << endl;
51  cout << "[Main options]:" << endl;
52 // cout << " -df file.cdh : Give an input CASTOR datafile (no default). Can use this option multiple times to specify multiple bed positions." << endl;
53  cout << " -df file.cdh : Give an input CASTOR datafile (no default)." << endl;
54  cout << " -fout name : Give the root name for all output files (no default, alternative to -dout)" << endl;
55  cout << " -dout name : Give the name of the output directory where all output files will be written (no default, alternative to -fout)" << endl;
56  cout << " -it list : Give the sequence of iterations:subsets separated by commas (no default)." << endl;
57  cout << " -dim x,y,z : Give the number of voxels in each dimension (default: those of the scanner)." << endl;
58  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;
59  cout << " the voxel sizes provided using '-vox')." << endl;
60  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;
61  cout << " if a fov value is provided using '-fov')." << endl;
62  cout << " -vb : Give the general verbosity level, from 0 (no verbose) to 5 and above (at the event level) (default: 1)." << endl;
63  cout << endl;
64  cout << "[Specific options]:" << endl;
65  cout << " -help-dim : Print out specific help about dimensions settings." << endl; // managed by main
66  cout << " -help-in : Print out specific help about input settings." << endl; // managed by main
67  cout << " -help-out : Print out specific help about output settings." << endl; // managed by main
68  cout << " -help-algo : Print out specific help about reconstruction optimizer algorithm settings." << endl; // managed by main
69  cout << " -help-proj : Print out specific help about projection operators." << endl; // managed by main
70  cout << " -help-dynamic : Print out specific help about dynamic methodologies settings." << endl; // managed by main
71  cout << " -help-imgp : Print out specific help about image processing modules." << endl; // managed by main
72  cout << " -help-comp : Print out specific help about computing settings." << endl; // managed by main
73  cout << " -help-corr : Print out specific help about all corrections that can be disabled." << endl;
74  cout << " -help-misc : Print out specific help about miscellaneous and verbose settings." << endl; // managed by main
75  cout << endl;
76  cout << "[Implemented Modules]:" << endl;
77  cout << " -help-scan : Show the list of all scanners from the configuration directory." << endl; // managed by sScannerManager
78  cout << " -help-projm : Show the list and description of all implemented projectors." << endl; // managed by oProjectorManager
79  cout << " -help-opti : Show the list and description of all implemented optimizer algorithms." << endl; // managed by oOptimizerManager
80  //cout << " -help-pnlt : Show the list and description of all implemented penalties for optimizers." << endl; // managed by oOptimizerManager
81  //cout << " -help-motion : Show the list and description of all implemented image-based deformation models." << endl; // managed by oImageDeformationManager*/
82  //cout << " -help-dynm : Show the list and description of all implemented dynamic models." << endl; // managed by oDynamicModelManager*/
83  cout << " -help-conv : Show the list and description of all implemented image convolvers." << endl; // managed by oImageConvolverManager
84  cout << " -help-proc : Show the list and description of all implemented image processing modules." << endl; // managed by oImageProcessingManager
85  cout << endl;
86  cout << endl;
87  cout << " --help,-h,-help : Print out this help page." << endl; // managed by main
88  cout << endl;
89  #ifdef CASTOR_MPI
90  cout << " Compiled with MPI" << endl;
91  #endif
92  #ifdef CASTOR_OMP
93  cout << " Compiled with OpenMP" << endl;
94  #endif
95  #ifdef CASTOR_GPU
96  cout << " Compiled for GPU" << endl;
97  #endif
98  #if defined(CASTOR_OMP) || defined(CASTOR_MPI) || defined(CASTOR_GPU)
99  cout << endl;
100  #endif
101  #ifdef BUILD_DATE
102  cout << " Build date: " << BUILD_DATE << endl;
103  cout << endl;
104  #endif
105  #ifdef CASTOR_VERSION
106  cout << " This program is part of the CASToR release version " << CASTOR_VERSION << "." << endl;
107  cout << endl;
108  #endif
109 }
110 
111 // =====================================================================
112 // ---------------------------------------------------------------------
113 // ---------------------------------------------------------------------
114 // =====================================================================
120 {
121  // Return when using MPI and mpi_rank is not 0
122  #ifdef CASTOR_MPI
123  int mpi_rank = 0;
124  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
125  if (mpi_rank!=0) return;
126  #endif
127  // Show help
128  cout << endl;
129  cout << "[Input settings]:" << endl;
130  cout << endl;
131 // cout << " -df-inv : Invert the order of provided datafiles corresponding to the different bed positions." << endl;
132 // cout << endl;
133 // cout << " -df file.Cdf : Give an input CASTOR datafile (no default). Can use this option multiple times to specify multiple bed positions." << endl;
134  cout << " -df file.Cdf : Give an input CASTOR datafile (no default)." << endl;
135  cout << endl;
136  cout << " -img file.hdr : Give an input image as the initialization of the algorithm (default: uniform value)." << endl;
137  cout << endl;
138  cout << " -sens file.hdr : Provide the sensitivity image (default: sensitivity image is computed before reconstruction)." << endl;
139  cout << " the image file should integrate all sensitivity images if more than one are required" << endl;
140  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;
141  cout << " (all cardiac-gated based sensitivity images for each one of the respiratory gates)." << endl;
142  cout << endl;
143  cout << " -norm file.cdh : For list-mode data, provide a normalization data file for sensitivity computation (default: use the scanner LUT and" << endl;
144  cout << " assume all LORs with a weight of 1.). This restricts the computation of the sensitivity to the LORs provided in the" << endl;
145  cout << " normalization file and associated normalization factors and/or attenuation factors." << endl;
146  cout << " For dynamic reconstructions with multiple frames, as many normalization files as frames can be supplied, their names" << endl;
147  cout << " separated by commas. This is useful when dead-times correction is included in the normalization factors." << endl;
148  cout << " Can also use this option multiple times when multiple bed positions are reconstructed at once." << endl;
149  cout << endl;
150  cout << " -atn file.hdr : Give an input attenuation image (unit has to be cm-1) for sensitivity image generation or SPECT attenuation correction." << endl;
151  cout << endl;
152  cout << " -help-in : Print out this help." << endl;
153  cout << endl;
154 }
155 
156 // =====================================================================
157 // ---------------------------------------------------------------------
158 // ---------------------------------------------------------------------
159 // =====================================================================
165 {
166  // Return when using MPI and mpi_rank is not 0
167  #ifdef CASTOR_MPI
168  int mpi_rank = 0;
169  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
170  if (mpi_rank!=0) return;
171  #endif
172  // Show help
173  cout << endl;
174  cout << "[Output settings]:" << endl;
175  cout << endl;
176  cout << " -fout name : Give the root name for all output files. All output files will be written as 'name_suffix.ext'." << endl;
177  cout << " So the provided name should not end with '.' or '/' character. (no default, alternative to -dout)" << endl;
178  cout << " -dout name : Give the name of the output directory where all output files will be written. All files will also" << endl;
179  cout << " be prefixed by the name of the directory. The provided name should not end with '.' or '/' character." << endl;
180  cout << " (no default, alternative to -fout)" << endl;
181  cout << endl;
182  cout << " -oit list : Give the sequence of output iterations as a list of 'a:b' pairs separated by commas. This will output one" << endl;
183  cout << " iteration over 'a' until 'b' is reached, then it goes to the next pair of setting. (default: last iteration)" << endl;
184  cout << endl;
185  cout << " -omd : (M)erge (D)ynamic images. Indicate if a dynamic serie of 3D images should be written on disk in one file" << endl;
186  cout << " instead of a serie of 3D images associated with an interfile metaheader" << endl;
187  cout << endl;
188 /* TO BE IMPLEMENTED
189  cout << " -otb : Flag to say that we want to save the time basis images too (default: only the frames are saved)." << endl;
190  cout << endl;
191 */
192  cout << " -osens : Flag to say that we want to save the sensitivity image of each subset/iteration, when in histogram mode." << endl;
193  cout << endl;
194  cout << " -osub : Flag to say that we want to save the image after each subset." << endl;
195  cout << endl;
196  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;
197  cout << endl;
198  cout << " -sens-histo : If input file is a histogram, compute the global sensitivity from it (and still proceed to normal reconstruction after)" << endl;
199  cout << endl;
200  cout << " -sens-only : For list-mode data, exit directly after computing and saving the sensitivity." << endl;
201  cout << endl;
202  cout << " -help-out : Print out this help." << endl;
203  cout << endl;
204 }
205 
206 // =====================================================================
207 // ---------------------------------------------------------------------
208 // ---------------------------------------------------------------------
209 // =====================================================================
215 {
216  // Return when using MPI and mpi_rank is not 0
217  #ifdef CASTOR_MPI
218  int mpi_rank = 0;
219  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
220  if (mpi_rank!=0) return;
221  #endif
222  // Show help
223  cout << endl;
224  cout << "[Dimensions options]:" << endl;
225  cout << endl;
226  cout << " -dim x,y,z : Give the number of voxels in each dimension (default: those of the scanner)." << endl;
227  cout << endl;
228  cout << " -fov x,y,z : Give the size of the field-of-view in each dimension, in mm (default: those of the scanner)." << endl;
229  cout << endl;
230  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;
231  cout << endl;
232  cout << " -off x,y,z : Give the offset of the field-of-view in each dimension, in mm (default: 0.,0.,0.)." << endl;
233  cout << " (note this has no effect when using a pre-computed system matrix)" << endl;
234  cout << endl;
235  cout << " -fov-out percent : Give the percentage of the eliptical transaxial FOV to be kept while saving the image (default: no making)" << endl;
236  cout << endl;
237  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;
238  cout << endl;
239  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;
240  cout << endl;
241  cout << " -help-dim : Print out this help." << endl;
242  cout << endl;
243 }
244 
245 // =====================================================================
246 // ---------------------------------------------------------------------
247 // ---------------------------------------------------------------------
248 // =====================================================================
254 {
255  // Return when using MPI and mpi_rank is not 0
256  #ifdef CASTOR_MPI
257  int mpi_rank = 0;
258  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
259  if (mpi_rank!=0) return;
260  #endif
261  // Show help
262  cout << "[Algorithm settings]:" << endl;
263  cout << endl;
264  cout << " -opti param : Give the algorithm to be used, along with a configuration file (algo:file.conf) or the list of parameters" << endl;
265  cout << " associated to the algorithm (algo,param1,param2,...). If the algorithm only is specified, the default" << endl;
266  cout << " configuration file is used if any. By default, the MLEM algorithm is used. For specific help, use option -help-opti." << endl;
267  cout << endl;
268  cout << " -opti-fom : Flag to say that we want to compute and print figures-of-merit (likelihood and RMSE) in the data-space." << endl;
269  cout << endl;
270  cout << " -opti-stat : Flag to say that we want to compute and print basic statistics about the image update." << endl;
271  cout << endl;
272 /* NOT YET IMPLEMENTED
273  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;
274  cout << " or the list of parameters associated to the penalty (penalty,param1,param2,...). If the penalty only is specified, the default" << endl;
275  cout << " configuration file is used if any. By default, no penalty is used. For specific help, use option -help-penalty." << endl;
276  cout << endl;
277 */
278  cout << " -help-opti : Print out specific help about algorithm settings." << endl; // managed by oOptimizerManager
279  cout << endl;
280 /* NOT YET IMPLEMENTED
281  cout << " -help-pnlt : Print out specific help about penalty settings." << endl; // managed by oOptimizerManager
282  cout << endl;
283 */
284 }
285 
286 // =====================================================================
287 // ---------------------------------------------------------------------
288 // ---------------------------------------------------------------------
289 // =====================================================================
295 {
296  // Return when using MPI and mpi_rank is not 0
297  #ifdef CASTOR_MPI
298  int mpi_rank = 0;
299  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
300  if (mpi_rank!=0) return;
301  #endif
302  // Show help
303  cout << "[Projector settings]:" << endl;
304  cout << endl;
305  cout << " -proj param : Give the projector to be used for both forward and backward projections, along with a configuration file (proj:file.conf)" << endl;
306  cout << " or the list of parameters associated to the projector (proj,param1,param2,...). If the projector only is specified, the" << endl;
307  cout << " default configuration file is used. By default, the Siddon projector is used. For specific help, use option -help-proj." << endl;
308  cout << endl;
309  cout << " -projF param : Give the projector to be used for forward projections. See option -proj for details." << endl;
310  cout << endl;
311  cout << " -projB param : Give the projector to be used for backward projections. See option -proj for details." << endl;
312  cout << endl;
313  cout << " -proj-common : Give parameterization of different common projector-related options." << endl;
314  cout << endl;
315 /* TO BE IMPLEMENTED
316  cout << " -ignore-POI : Flag to say that we want to ignore any potential POI information (default: use it if present in the datafile)." << endl;
317  cout << endl;
318  * */
319  cout << " -ignore-TOF : Flag to say that we want to ignore any potential TOF information (default: use it if present in the datafile)." << endl;
320  cout << endl;
321  cout << " -help-projm : Print out specific help about projector settings." << endl; // managed by oProjectorManager
322  cout << endl;
323 }
324 
325 // =====================================================================
326 // ---------------------------------------------------------------------
327 // ---------------------------------------------------------------------
328 // =====================================================================
334 {
335  // Return when using MPI and mpi_rank is not 0
336  #ifdef CASTOR_MPI
337  int mpi_rank = 0;
338  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
339  if (mpi_rank!=0) return;
340  #endif
341  // Show help
342  cout << "[Image processing settings]:" << endl;
343  cout << endl;
344  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;
345  cout << " list of parameters associated to the convolver (conv,param1,param2,...::when). If the convolver only is specified, its default" << endl;
346  cout << " configuration file is used. By default, no convolver is applied. Multiple convolvers can be combined simply by repeating this" << endl;
347  cout << " this option. The mandatory 'when' parameter specifies when the convolver is applied (psf, sieve, forward, backward, post, intra)." << endl;
348  cout << " For more specific help, use option -help-conv." << endl;
349  cout << endl;
350  cout << " -help-conv : Print out specific help about the image convolver settings." << endl; // managed by oImageConvolverManager
351  cout << endl;
352  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;
353  cout << " list of parameters associated to the module (proc,param1,param2,...;when). If the module only is specified, its default" << endl;
354  cout << " configuration file is used. By default, no image processing module is applied. Multiple modules can be combined simply by" << endl;
355  cout << " repeating this this option. The mandatory 'when' parameter specifies when the module is applied (forward, backward, post, intra)." << endl;
356  cout << " For more specific help, use option -help-proc." << endl;
357  cout << endl;
358  cout << " -help-proc : Print out specific help about the image processing module settings." << endl; // managed by oImageProcessingManager
359  cout << endl;
360 }
361 
362 // =====================================================================
363 // ---------------------------------------------------------------------
364 // ---------------------------------------------------------------------
365 // =====================================================================
371 {
372  // Return when using MPI and mpi_rank is not 0
373  #ifdef CASTOR_MPI
374  int mpi_rank = 0;
375  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
376  if (mpi_rank!=0) return;
377  #endif
378  // Show help
379  cout << endl;
380  cout << "[Dynamic settings]:" << endl;
381  cout << endl;
382  cout << " -frm list : Give the framing for the reconstruction where 'list' is a list of all frames durations in seconds separated" << endl;
383  cout << " by commas. To specify a dead frame, add ';0' concatenated to the frame duration. Milliseconds maximum precision." << endl;
384  cout << " (default: 1 frame of the whole input file duration)" << endl;
385  cout << endl;
386  cout << " -g path_to_file : Provide text file for dynamic data splitting associated to respiratory/cardiac gating or involuntary patient motion correction" << endl;
387  cout << endl;
388 /* TO BE VALIDATED
389  cout << " -time-basis nb:file : Give the number of time basis functions related to the frames given by option -frm." << endl;
390  cout << " The file should contain one line for each time-basis function, and as many numbers as frames." << endl;
391  cout << " -resp-basis nb:file : Give the number of intrinsic respiratory basis functions related to the respiratory gates" << endl;
392  cout << " The file should contain one line for each respiratory basis function, and as many numbers as respiratory gates." << endl;
393  cout << " -card-basis nb:file : Give the number of intrinsic cardiac basis functions related to the cardiac gates" << endl;
394  cout << " The file should contain one line for each cardiac basis function, and as many numbers as cardiac gates." << endl;
395  cout << endl;
396  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;
397  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;
398  cout << endl;
399  cout << " -rm param : Provide an image-based deformation model to be used for respiratory motion correction, along with a configuration file (deformation:file)" << endl;
400  cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl;
401  cout << endl;
402  cout << " -cm param : Provide an image-based deformation model to be used for cardiac motion correction, along with a configuration file (deformation:file)" << endl;
403  cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl;
404  cout << endl;
405  cout << " -rcm param : Provide an image-based deformation model to be used for both respiratory and cardiac motion corrections, along with a configuration file (deformation:file)" << endl;
406  cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl;
407  cout << endl;
408  cout << " -im param : Provide an image-based deformation model to be used for involuntary motion correction, along with a configuration file (deformation:file)" << endl;
409  cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl;
410  cout << endl;
411  cout << " -qdyn file : Provide a text file containing quantitative factors specific to dynamic frames, respiratory or cardiac gates." << endl;
412  cout << " The file should provide factors with the keywords 'FRAME_QUANTIFICATION_FACTORS' and 'GATE_QUANTIFICATION_FACTORS' " << endl;
413  cout << " The number of factors should be consistent with the number of frames/gates " << endl;
414  cout << " If the data contains several frames and gates, the gate quantification factors should be entered on a separate line for each frame " << endl;
415  cout << endl;
416  cout << " -help-dynm : Print out specific help about dynamic model." << endl; // managed by oDynamicModelManager
417  cout << endl;
418  cout << " -help-motion : Print out specific help about deformation in image space for motion correction." << endl; // managed by oImageDeformationManager
419  cout << endl;
420  */
421  cout << " -help-dynamic : Print out this help." << endl;
422  cout << endl;
423 }
424 
425 // =====================================================================
426 // ---------------------------------------------------------------------
427 // ---------------------------------------------------------------------
428 // =====================================================================
434 {
435  // Return when using MPI and mpi_rank is not 0
436  #ifdef CASTOR_MPI
437  int mpi_rank = 0;
438  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
439  if (mpi_rank!=0) return;
440  #endif
441  // Show help
442  cout << endl;
443  cout << "[Computation settings]:" << endl;
444  cout << endl;
445  #ifdef CASTOR_OMP
446  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;
447  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;
448  cout << endl;
449  #endif
450  #ifdef CASTOR_GPU
451  cout << " -gpu : Flag to say that we want to use the GPU device (default: use the CPU only)." << endl;
452  cout << endl;
453  #endif
454  cout << " -load size : Give a number between 0 and 100 to specify the number of events which will be loaded in the RAM." << endl;
455  cout << " It will be interpreted as a percent ratio (default: 100 means all data buffered. 0 means no data buffered.)" << endl;
456  cout << endl;
457  cout << " -proj-comp : Give the strategy for projection line computation. Here are the three different strategies that can be used:" << endl;
458  cout << " 1 : Image-based system matrix elements storage: The voxels weights are added in a matrix representing the whole image, so" << endl;
459  cout << " the addition of a new line to the previous ones is straightforward only by adding the weights to the corresponding voxels." << endl;
460  cout << " As it is insanely long, it can possibly be used for example with extremely complex projectors that makes use of huge number" << endl;
461  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;
462  cout << " This strategy is not compatible with SPECT reconstruction including attenuation correction." << endl;
463  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;
464  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;
465  cout << " has a fixed size which is provided by the EstimateMaxNumberOfVoxelsPerLine() function from the vProjector class. There are no" << endl;
466  cout << " ckecks at all for possible buffer overflows. This is the fastest strategy and default one." << endl;
467  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;
468  cout << " upgraded if the current number of contributing voxels exceed the list's size. The first allocated size corresponds to the diagonal" << endl;
469  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;
470  cout << " is a bit slower than the fixed-list strategy during the first iteration, but is optimal with respect to RAM usage." << endl;
471  cout << endl;
472  cout << " -rng : Give a seed for the random number generator (should be >=0)" << endl;
473  cout << endl;
474  cout << " -help-comp : Print out this help." << endl;
475  cout << endl;
476  #ifdef CASTOR_MPI
477  cout << " Compiled with MPI" << endl;
478  #endif
479  #ifdef CASTOR_OMP
480  cout << " Compiled with OpenMP" << endl;
481  #endif
482  #ifdef CASTOR_GPU
483  cout << " Compiled for GPU" << endl;
484  #endif
485  #if defined(CASTOR_OMP) || defined(CASTOR_MPI) || defined(CASTOR_GPU)
486  cout << endl;
487  #endif
488 }
489 
490 // =====================================================================
491 // ---------------------------------------------------------------------
492 // ---------------------------------------------------------------------
493 // =====================================================================
499 {
500  // Return when using MPI and mpi_rank is not 0
501  #ifdef CASTOR_MPI
502  int mpi_rank = 0;
503  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
504  if (mpi_rank!=0) return;
505  #endif
506  // Show help
507  cout << endl;
508  cout << "[Miscellaneous settings]:" << endl;
509  cout << endl;
510  cout << " -vb : Give the general verbosity level, from 0 (no verbose) to 5 and above (at the event level) (default: 1)." << endl;
511  cout << " -vb-algo : Give the verbose level specific to the algorithm (default: same as general verbose level)." << endl;
512  cout << " -vb-opti : Give the verbose level specific to the optimizer (default: same as general verbose level)." << endl;
513  cout << " -vb-proj : Give the verbose level specific to the projector (default: same as general verbose level)." << endl;
514  cout << " -vb-conv : Give the verbose level specific to the image convolver (default: same as general verbose level)." << endl;
515  cout << " -vb-proc : Give the verbose level specific to the image processing (default: same as general verbose level)." << endl;
516  cout << " -vb-scan : Give the verbose level specific to the scanner (default: same as general verbose level)." << endl;
517  cout << " -vb-data : Give the verbose level specific to the data and image management (default: same as general verbose level)." << endl;
518  cout << " -vb-defo : Give the verbose level specific to the deformation (default: same as general verbose level)." << endl;
519  cout << " -vb-dyna : Give the verbose level specific to the dynamic model (default: same as general verbose level)." << endl;
520  cout << " -vb-sens : Give the verbose level specific to the sensitivity computation (default: same as general verbose level)." << endl;
521  cout << endl;
522  cout << " -conf : Give the path to the CASToR config directory (default: located through the CASTOR_CONFIG environment variable)." << endl;
523  cout << endl;
524  cout << " -help-misc : Print out this help." << endl;
525  cout << endl;
526 }
527 
528 // =====================================================================
529 // ---------------------------------------------------------------------
530 // ---------------------------------------------------------------------
531 // =====================================================================
537 {
538  // Return when using MPI and mpi_rank is not 0
539  #ifdef CASTOR_MPI
540  int mpi_rank = 0;
541  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
542  if (mpi_rank!=0) return;
543  #endif
544  // Show help
545  cout << endl;
546  cout << "[Correction settings]:" << endl;
547  cout << endl;
548  cout << " -ignore-corr list : Give the list of corrections that should be ignored, separated by commas (default: all corrections applied if present)." << endl;
549  cout << " Here is a list of all corrections that can be ignored:" << endl;
550  cout << " - attn: to ignore the attenuation correction (emission only)" << endl;
551  cout << " - norm: to ignore the normalization correction (emission only)" << endl;
552  cout << " - rand: to ignore the random correction (PET only)" << endl;
553  cout << " - scat: to ignore the scatter correction" << endl;
554  cout << " - deca: to ignore the decay correction (emission only)" << endl;
555  cout << " - brat: to ignore the branching ratio correction (emission only)" << endl;
556  cout << " - fdur: to ignore the frame duration correction (emission only)" << endl;
557  cout << " - cali: to ignore the calibration correction (emission only)" << endl;
558  cout << endl;
559 }
560 
561 // =============================================================================================================================================
562 // =============================================================================================================================================
563 // =============================================================================================================================================
564 // M A I N P R O G R A M
565 // =============================================================================================================================================
566 // =============================================================================================================================================
567 // =============================================================================================================================================
568 
569 int main(int argc, char** argv)
570 {
571  // ============================================================================================================
572  // MPI stuff
573  // ============================================================================================================
574  int mpi_rank = 0;
575  int mpi_size = 1;
576  #ifdef CASTOR_MPI
577  MPI_Init(&argc, &argv);
578  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
579  MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
580  #endif
581 
582  // No argument, then show help
583  if (argc==1)
584  {
585  ShowHelp();
586  Exit(EXIT_SUCCESS);
587  }
588 
589  // ============================================================================================================
590  // Parameterized variables with their default values
591  // ============================================================================================================
592 
593  // --------------------------------------------------------------------------------
594  // Dimensions settings
595  // --------------------------------------------------------------------------------
596 
597  // Initialization of the voxel and field-of-view values in each spatial dimensions. default values depend of the scanner.
598  INTNB nb_voxX=-1, nb_voxY=-1, nb_voxZ=-1;
599  FLTNB fov_sizeX=-1., fov_sizeY=-1., fov_sizeZ=-1.;
600  FLTNB vox_sizeX=-1., vox_sizeY=-1., vox_sizeZ=-1.;
601  // Initialization offset values of the field-of-view in each spatial dimensions
602  FLTNB offsetX = 0., offsetY = 0., offsetZ = 0.;
603  FLTNB fov_out = 0.;
604  INTNB slice_out = 0;
605  // Output flip
606  string flip_out = "";
607 
608  // --------------------------------------------------------------------------------
609  // Dynamic settings
610  // --------------------------------------------------------------------------------
611 
612  // Frame list descriptor
613  string frame_list = "";
614  // Number of respiratory gates in the data. default : 1
615  int nb_resp_gates = 1;
616  // Number of cardiac gates in the data. default : 1
617  int nb_card_gates = 1;
618  // Path to file containing the respiratory/cardiac gate splitting of the data
619  string path_to_4D_data_splitting_file = "";
620  // 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
621  string dynamic_model_options = "";
622  // String gathering the name of the used deformation model for respiratory motion (default : none), corresponding file, and corresponding string gathering parameters
623  string resp_motion_options = "";
624  // String gathering the name of the used deformation model for cardiac motion (default : none), corresponding file, and corresponding string gathering parameters
625  string card_motion_options = "";
626  // String gathering the name of the used deformation model for both respiratory and cardiac motions (default : none), corresponding file, and corresponding string gathering parameters
627  string double_motion_options = "";
628  // String gathering the name of the used deformation model for involuntary motion (default : none), corresponding file, and corresponding string gathering parameters
629  string ipat_motion_options = "";
630  // Number of time basis functions and associated file
631  int nb_time_basis = 1;
632  string path_to_time_basis_coef = "";
633  // Number of respiratory basis functions and associated file
634  int nb_resp_basis = 1;
635  string path_to_resp_basis_coef = "";
636  // Number of cardiac basis functions and associated file
637  int nb_card_basis = 1;
638  string path_to_card_basis_coef = "";
639  // Number of cardiac basis functions and associated file
640  string path_to_dynamic_quantification_file= "";
641 
642  // --------------------------------------------------------------------------------
643  // Input settings
644  // --------------------------------------------------------------------------------
645 
646  // Number of bed position
647  int nb_beds = 0;
648  // Vector containing string which gather the path to the data filenames provided by the user. no default
649  vector<string> path_to_data_filename;
650  // Invert bed datafile names order
651  bool invert_datafile_order_flag = false;
652  // Path to an image used as initialization. no default (uniform image is used in this case)
653  string path_to_initial_img = "";
654  // Path to an image used as initialization for the sensitivity image. no default (sensitivity image is computed in this case)
655  string path_to_sensitivity_img;
656  // Path to a normalization data file for sensitivity computation with list-mode data
657  vector<string> path_to_normalization_filename;
658  // Path to an image used for the attenuation. default : uniform image
659  string path_to_attenuation_img;
660  // Number of resp and card atn images for sensitivity image generation
661  int nb_atn_resp_imgs = 1;
662  int nb_atn_card_imgs = 1;
663  // Ignored corrections (by default, if present, there are applied)
664  string ignored_corrections = "";
665 
666  // --------------------------------------------------------------------------------
667  // Output settings
668  // --------------------------------------------------------------------------------
669 
670  // Output directory name.
671  string path_dout = "";
672  // Or root name
673  string path_fout = "";
674  // Iterations to be saved
675  string output_iterations = "";
676  // Merge output dynamic images on disk into one file or not
677  bool merge_dynamic_imgs_flag = false;
678  // Write scanner LUT generated by a geom file on disk
679  bool save_LUT_flag = false;
680  // Save the sensitivity image in histogram mode for each subset/iteration
681  bool save_sens_histo = false;
682  // Save the image after each subset
683  bool save_subset_image = false;
684  // Save the time basis functions (flag). default : no saving
685  //bool save_time_basis_functions_flag = false; //TODO
686  // Exit directly after computing the sensitivity
687  bool exit_after_sensitivity = false;
688  // Compute sensitivity with a histogram file as input
689  bool sensitivity_from_histogram = false;
690 
691  // --------------------------------------------------------------------------------
692  // Projector settings
693  // --------------------------------------------------------------------------------
694 
695  // String gathering the name of the projector for forward/backward projection with specific options (default: Native Siddon for both)
696  string options_projector = "incrementalSiddon";
697  string options_projectorF = "incrementalSiddon";
698  string options_projectorB = "incrementalSiddon";
699  string options_projector_common = "";
700  // Default projector computation strategy
701  int projector_computation_strategy = FIXED_LIST_COMPUTATION_STRATEGY;
702  // POI & TOF flags for the use of such information in the reconstruction
703  bool ignore_POI = false;
704  bool ignore_TOF = false;
705 
706  // --------------------------------------------------------------------------------
707  // Algorithm settings
708  // --------------------------------------------------------------------------------
709 
710  // Numbers of iterations and associated numbers of subsets (default : 1 for both)
711  string nb_iterations_subsets = "";
712  // String gathering the name of the optimizer with specific options (default: MLEM)
713  string options_optimizer = "MLEM";
714  // Boolean to say if we want to compute FOM in the data-space
715  bool optimizer_fom = false;
716  // Boolean to say if we want to compute image update basic statistics
717  bool optimizer_stat = false;
718  // String gathering the name of the penalty with specific options (default: no penalty)
719  string options_penalty = "";
720 
721  // --------------------------------------------------------------------------------
722  // Image convolvers and processing modules
723  // --------------------------------------------------------------------------------
724 
725  // String vector gathering the name of the image convolvers with specific options (default: no image convolver)
726  vector<string> options_image_convolver;
727  // String vector gathering the name of the image processing modules with specific options (default: no image processing module)
728  vector<string> options_image_processing;
729 
730  // --------------------------------------------------------------------------------
731  // Computation settings
732  // --------------------------------------------------------------------------------
733 
734  // Using GPU (flag) ->NOTE : default : only CPU
735  bool gpu_flag = false;
736  // Size of the buffer used to read the data file (this is a percentage rounded to the integer)
737  int data_file_percentage_load = 100;
738  // Number of threads
739  string nb_threads = "1";
740 
741  // --------------------------------------------------------------------------------
742  // Miscellaneous settings
743  // --------------------------------------------------------------------------------
744 
745  // General verbose level
746  int verbose_general = 1;
747  // Specific verbose levels
748  int verbose_algo = -1;
749  int verbose_opti = -1;
750  int verbose_proj = -1;
751  int verbose_conv = -1;
752  int verbose_proc = -1;
753  int verbose_scan = -1;
754  int verbose_data = -1;
755  int verbose_defo = -1;
756  int verbose_dyna = -1;
757  int verbose_sens = -1;
758  // Path to config directory
759  string path_to_config_dir = "";
760  // Initial seed for random number generator
761  int64_t seed_RNG = -1;
762 
763  // ============================================================================================================
764  // Read command-line parameters
765  // ============================================================================================================
766 
767  // TODO : replace remaining atoi, atof, etc, by ConvertFromString()
768 
769  // Must manually increment the option index when an argument is needed after an option
770  for (int i=1; i<argc; i++)
771  {
772  // Get the option as a string
773  string option = (string)argv[i];
774 
775  // --------------------------------------------------------------------------------
776  // Miscellaneous settings
777  // --------------------------------------------------------------------------------
778 
779  // Show help
780  if (option=="-h" || option=="--help" || option=="-help")
781  {
782  ShowHelp();
783  Exit(EXIT_SUCCESS);
784  }
785  // Specific help for integrated scanners (managed by scanner manager)
786  else if (option=="-help-scan")
787  {
788  if(sScannerManager::GetInstance()->ShowScannersDescription())
789  Cerr("***** castor-recon() -> An error occured when trying to output the available scanners from the scanner repository !'" << endl;);
790  Exit(EXIT_SUCCESS);
791  }
792  // Specific help for optimizer settings (managed by optimizer children)
793  else if (option=="-help-opti")
794  {
796  Exit(EXIT_SUCCESS);
797  }
798  // Specific help for penalty settings (managed by penalty children)
799  else if (option=="-help-pnlt")
800  {
802  Exit(EXIT_SUCCESS);
803  }
804  // Specific help for projector settings (managed by projector children)
805  else if (option=="-help-projm")
806  {
807  // Call specific showHelp function from vProjector children
809  // Call the static showHelp function from vProjector
811  Exit(EXIT_SUCCESS);
812  }
813  // Specific help for image convolver settings (managed by image convolver children)
814  else if (option=="-help-conv")
815  {
816  // Call specific showHelp function from vImageConvolver children
818  // Call the static showHelp function from oImageConvolverManager
820  Exit(EXIT_SUCCESS);
821  }
822  // Specific help for image processing settings (managed by image processing children)
823  else if (option=="-help-proc")
824  {
825  // Call specific showHelp function from vImageProcessingModule children
827  // Call the static showHelp function from oImageProcessingManager
829  Exit(EXIT_SUCCESS);
830  }
831  // Specific help for dynamic model (managed by dynamic model children)
832  else if (option=="-help-dynm")
833  {
835  Exit(EXIT_SUCCESS);
836  }
837  // Specific help for image deformation settings (managed by projector children)
838  else if (option=="-help-motion")
839  {
841  Exit(EXIT_SUCCESS);
842  }
843  // Specific help for input settings (managed by main)
844  else if (option=="-help-in")
845  {
846  ShowHelpInput();
847  Exit(EXIT_SUCCESS);
848  }
849  // Specific help for output settings (managed by main)
850  else if (option=="-help-out")
851  {
852  ShowHelpOutput();
853  Exit(EXIT_SUCCESS);
854  }
855  // Specific help for dimensions settings (managed by main)
856  else if (option=="-help-dim")
857  {
859  Exit(EXIT_SUCCESS);
860  }
861  // Specific help for optimizer settings (managed by main)
862  else if (option=="-help-algo")
863  {
864  ShowHelpAlgo();
865  Exit(EXIT_SUCCESS);
866  }
867  // Specific help for projector settings (managed by main)
868  else if (option=="-help-proj")
869  {
870  ShowHelpProj();
871  Exit(EXIT_SUCCESS);
872  }
873  // Specific help for image processing settings (managed by main)
874  else if (option=="-help-imgp")
875  {
876  ShowHelpImgp();
877  Exit(EXIT_SUCCESS);
878  }
879  // Specific help for computation settings (managed by main)
880  else if (option=="-help-comp")
881  {
883  Exit(EXIT_SUCCESS);
884  }
885  // Specific help for miscellaneous settings (managed by main)
886  else if (option=="-help-misc")
887  {
889  Exit(EXIT_SUCCESS);
890  }
891  // Specific help for dynamic settings (managed by main)
892  else if (option=="-help-dynamic")
893  {
894  ShowHelpDynamic();
895  Exit(EXIT_SUCCESS);
896  }
897  // Specific help for correction settings (managed by main)
898  else if (option=="-help-corr")
899  {
901  Exit(EXIT_SUCCESS);
902  }
903  // General verbosity level
904  else if (option=="-vb")
905  {
906  if (i>=argc-1)
907  {
908  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
909  Exit(EXIT_FAILURE);
910  }
911  if (ConvertFromString(argv[i+1], &verbose_general))
912  {
913  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_general << " for option: " << option << endl);
914  Exit(EXIT_FAILURE);
915  }
916  i++;
917  }
918  // Algorithm verbosity level
919  else if (option=="-vb-algo")
920  {
921  if (i>=argc-1)
922  {
923  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
924  Exit(EXIT_FAILURE);
925  }
926  if (ConvertFromString(argv[i+1], &verbose_algo))
927  {
928  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_algo << " for option: " << option << endl);
929  Exit(EXIT_FAILURE);
930  }
931  i++;
932  }
933  // Optimizer verbosity level
934  else if (option=="-vb-opti")
935  {
936  if (i>=argc-1)
937  {
938  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
939  Exit(EXIT_FAILURE);
940  }
941  if (ConvertFromString(argv[i+1], &verbose_opti))
942  {
943  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_opti << " for option: " << option << endl);
944  Exit(EXIT_FAILURE);
945  }
946  i++;
947  }
948  // Projector verbosity level
949  else if (option=="-vb-proj")
950  {
951  if (i>=argc-1)
952  {
953  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
954  Exit(EXIT_FAILURE);
955  }
956  if (ConvertFromString(argv[i+1], &verbose_proj))
957  {
958  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_proj << " for option: " << option << endl);
959  Exit(EXIT_FAILURE);
960  }
961  i++;
962  }
963  // Image convolver verbosity level
964  else if (option=="-vb-conv")
965  {
966  if (i>=argc-1)
967  {
968  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
969  Exit(EXIT_FAILURE);
970  }
971  if (ConvertFromString(argv[i+1], &verbose_conv))
972  {
973  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_conv << " for option: " << option << endl);
974  Exit(EXIT_FAILURE);
975  }
976  i++;
977  }
978  // Image processing verbosity level
979  else if (option=="-vb-proc")
980  {
981  if (i>=argc-1)
982  {
983  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
984  Exit(EXIT_FAILURE);
985  }
986  if (ConvertFromString(argv[i+1], &verbose_proc))
987  {
988  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_proc << " for option: " << option << endl);
989  Exit(EXIT_FAILURE);
990  }
991  i++;
992  }
993  // Scanner verbosity level
994  else if (option=="-vb-scan")
995  {
996  if (i>=argc-1)
997  {
998  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
999  Exit(EXIT_FAILURE);
1000  }
1001  if (ConvertFromString(argv[i+1], &verbose_scan))
1002  {
1003  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_scan << " for option: " << option << endl);
1004  Exit(EXIT_FAILURE);
1005  }
1006  i++;
1007  }
1008  // Data and image verbosity level
1009  else if (option=="-vb-data")
1010  {
1011  if (i>=argc-1)
1012  {
1013  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1014  Exit(EXIT_FAILURE);
1015  }
1016  if (ConvertFromString(argv[i+1], &verbose_data))
1017  {
1018  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_data << " for option: " << option << endl);
1019  Exit(EXIT_FAILURE);
1020  }
1021  i++;
1022  }
1023  // Deformation verbosity level
1024  else if (option=="-vb-defo")
1025  {
1026  if (i>=argc-1)
1027  {
1028  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1029  Exit(EXIT_FAILURE);
1030  }
1031  if (ConvertFromString(argv[i+1], &verbose_defo))
1032  {
1033  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_defo << " for option: " << option << endl);
1034  Exit(EXIT_FAILURE);
1035  }
1036  i++;
1037  }
1038  // Dynamic verbosity level
1039  else if (option=="-vb-dyna")
1040  {
1041  if (i>=argc-1)
1042  {
1043  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1044  Exit(EXIT_FAILURE);
1045  }
1046  if (ConvertFromString(argv[i+1], &verbose_dyna))
1047  {
1048  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_dyna << " for option: " << option << endl);
1049  Exit(EXIT_FAILURE);
1050  }
1051  i++;
1052  }
1053  // Sensitivity verbosity level
1054  else if (option=="-vb-sens")
1055  {
1056  if (i>=argc-1)
1057  {
1058  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1059  Exit(EXIT_FAILURE);
1060  }
1061  if (ConvertFromString(argv[i+1], &verbose_sens))
1062  {
1063  Cerr("***** castor-recon() -> Exception when trying to read provided verbosity level '" << verbose_sens << " for option: " << option << endl);
1064  Exit(EXIT_FAILURE);
1065  }
1066  i++;
1067  }
1068  // RNG seed
1069  else if (option=="-rng")
1070  {
1071  if (i>=argc-1)
1072  {
1073  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1074  Exit(EXIT_FAILURE);
1075  }
1076  if(ConvertFromString(argv[i+1], &seed_RNG))
1077  {
1078  Cerr("***** castor-recon() -> Exception when trying to read provided number '" << seed_RNG << " for option: " << option << endl);
1079  Exit(EXIT_FAILURE);
1080  }
1081  i++;
1082  }
1083  // Path to config directory
1084  else if (option=="-conf")
1085  {
1086  if (i>=argc-1)
1087  {
1088  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1089  Exit(EXIT_FAILURE);
1090  }
1091  path_to_config_dir = (string)argv[i+1];
1092  i++;
1093  }
1094 
1095  // --------------------------------------------------------------------------------
1096  // Dimensions settings
1097  // --------------------------------------------------------------------------------
1098 
1099  // Dimensions: number of voxels
1100  else if (option=="-dim")
1101  {
1102  if (i>=argc-1)
1103  {
1104  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1105  Exit(EXIT_FAILURE);
1106  }
1107  INTNB input[3];
1108  if (ReadStringOption(argv[i+1], input, 3, ",", option))
1109  {
1110  Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
1111  Exit(EXIT_FAILURE);
1112  }
1113  nb_voxX = input[0];
1114  nb_voxY = input[1];
1115  nb_voxZ = input[2];
1116  i++;
1117  }
1118  // Dimensions: size of the field-of-view in mm
1119  else if (option=="-fov")
1120  {
1121  if (i>=argc-1)
1122  {
1123  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1124  Exit(EXIT_FAILURE);
1125  }
1126  FLTNB input[3];
1127  if (ReadStringOption(argv[i+1], input, 3, ",", option))
1128  {
1129  Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
1130  Exit(EXIT_FAILURE);
1131  }
1132  fov_sizeX = input[0];
1133  fov_sizeY = input[1];
1134  fov_sizeZ = input[2];
1135  i++;
1136  }
1137  // Dimensions: size of the voxels in mm
1138  else if (option=="-vox")
1139  {
1140  if (i>=argc-1)
1141  {
1142  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1143  Exit(EXIT_FAILURE);
1144  }
1145  FLTNB input[3];
1146  if (ReadStringOption(argv[i+1], input, 3, ",", option))
1147  {
1148  Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
1149  Exit(EXIT_FAILURE);
1150  }
1151  vox_sizeX = input[0];
1152  vox_sizeY = input[1];
1153  vox_sizeZ = input[2];
1154  i++;
1155  }
1156  // Dimensions: offset of the image in mm
1157  else if (option=="-off")
1158  {
1159  if (i>=argc-1)
1160  {
1161  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1162  Exit(EXIT_FAILURE);
1163  }
1164  FLTNB input[3];
1165  if (ReadStringOption(argv[i+1], input, 3, ",", option))
1166  {
1167  Cerr("***** castor-recon() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
1168  Exit(EXIT_FAILURE);
1169  }
1170  offsetX = input[0];
1171  offsetY = input[1];
1172  offsetZ = input[2];
1173  i++;
1174  }
1175  // Size of the output transaxial FOV in percentage
1176  else if (option=="-fov-out")
1177  {
1178  if (i>=argc-1)
1179  {
1180  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1181  Exit(EXIT_FAILURE);
1182  }
1183  fov_out = atof(argv[i+1]);
1184  i++;
1185  }
1186  // Number of slices to be masked at output
1187  else if (option=="-slice-out")
1188  {
1189  if (i>=argc-1)
1190  {
1191  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1192  Exit(EXIT_FAILURE);
1193  }
1194  slice_out = ((INTNB)(atoi(argv[i+1])));
1195  i++;
1196  }
1197  // Output flip
1198  else if (option=="-flip-out")
1199  {
1200  if (i>=argc-1)
1201  {
1202  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1203  Exit(EXIT_FAILURE);
1204  }
1205  flip_out = (string)(argv[i+1]);
1206  i++;
1207  }
1208 
1209  // --------------------------------------------------------------------------------
1210  // Dynamic settings
1211  // --------------------------------------------------------------------------------
1212 
1213  // Dimensions: number of frames
1214  else if (option=="-frm") // TODO: more checks to be done in the option reading
1215  {
1216  if (i>=argc-1)
1217  {
1218  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1219  Exit(EXIT_FAILURE);
1220  }
1221  frame_list = (string)argv[i+1];
1222  i++;
1223  }
1224  // Dimensions: number of respiratory gates
1225  else if (option=="-g")
1226  {
1227  if (i>=argc-1)
1228  {
1229  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1230  Exit(EXIT_FAILURE);
1231  }
1232  // Path to the dynamic file
1233  path_to_4D_data_splitting_file = ((string)argv[i+1]);
1234  // Recover number of respiratory gates from file
1235  if (ReadDataASCIIFile(path_to_4D_data_splitting_file, "nb_respiratory_gates", &nb_resp_gates, 1, KEYWORD_MANDATORY))
1236  {
1237  Cerr("***** castor-recon() -> Couldn't read the number of respiratory gates in the file " << path_to_4D_data_splitting_file << " for option " << option << endl);
1238  Exit(EXIT_FAILURE);
1239  }
1240  // Recover number of cardiac gates from file
1241  if (ReadDataASCIIFile(path_to_4D_data_splitting_file, "nb_cardiac_gates", &nb_card_gates, 1, KEYWORD_MANDATORY))
1242  {
1243  Cerr("***** castor-recon() -> Couldn't read the number of cardiac gates in the file " << path_to_4D_data_splitting_file << " for option " << option << endl);
1244  Exit(EXIT_FAILURE);
1245  }
1246  // Check for wrong initialization
1247  if (nb_resp_gates<1 || nb_card_gates <1)
1248  {
1249  Cerr("***** castor-recon() -> Incorrect initialization of the number of gates for the option: " << option << ". This number should be >= 1" << endl);
1250  Exit(EXIT_FAILURE);
1251  }
1252  i++;
1253  }
1254  // Time basis functions
1255  else if (option=="-time-basis")
1256  {
1257  if (i>=argc-1)
1258  {
1259  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1260  Exit(EXIT_FAILURE);
1261  }
1262  string input = argv[i+1];
1263  size_t column_pos = input.find_first_of(":");
1264  if (column_pos==string::npos)
1265  {
1266  Cerr("***** castor-recon() -> Incorrect argument after option " << option << ", ':' sign is missing !" << endl);
1267  Exit(EXIT_FAILURE);
1268  }
1269  string str = input.substr(0, column_pos);
1270  nb_time_basis = atoi(str.c_str());
1271  path_to_time_basis_coef = input.substr(column_pos+1);
1272  i++;
1273  }
1274  // Respiratory basis functions
1275  else if (option=="-resp-basis")
1276  {
1277  if (i>=argc-1)
1278  {
1279  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1280  Exit(EXIT_FAILURE);
1281  }
1282  string input = argv[i+1];
1283  size_t column_pos = input.find_first_of(":");
1284  if (column_pos==string::npos)
1285  {
1286  Cerr("***** castor-recon() -> Incorrect argument after option " << option << ", ':' sign is missing !" << endl);
1287  Exit(EXIT_FAILURE);
1288  }
1289  string str = input.substr(0, column_pos);
1290  nb_resp_basis = atoi(str.c_str());
1291  path_to_resp_basis_coef = input.substr(column_pos+1);
1292  i++;
1293  }
1294  // Cardiac basis functions
1295  else if (option=="-card-basis")
1296  {
1297  if (i>=argc-1)
1298  {
1299  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1300  Exit(EXIT_FAILURE);
1301  }
1302  string input = argv[i+1];
1303  size_t column_pos = input.find_first_of(":");
1304  if (column_pos==string::npos)
1305  {
1306  Cerr("***** castor-recon() -> Incorrect argument after option " << option << ", ':' sign is missing !" << endl);
1307  Exit(EXIT_FAILURE);
1308  }
1309  string str = input.substr(0, column_pos);
1310  nb_card_basis = atoi(str.c_str());
1311  path_to_card_basis_coef = input.substr(column_pos+1);
1312  i++;
1313  }
1314  // Dynamic model applied to the frames/respiratory gates/cardiac gates of the dynamic acquisition
1315  else if (option=="-dynamic-model")
1316  {
1317  if (i>=argc-1)
1318  {
1319  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1320  Exit(EXIT_FAILURE);
1321  }
1322  dynamic_model_options = (string)argv[i+1];
1323  i++;
1324  }
1325  // Data for respiratory motion correction based on deformation
1326  else if (option=="-rm")
1327  {
1328  if (i>=argc-1)
1329  {
1330  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1331  Exit(EXIT_FAILURE);
1332  }
1333  resp_motion_options = (string)argv[i+1];
1334  i++;
1335  }
1336  // Data for cardiac motion correction based on deformation
1337  else if (option=="-cm")
1338  {
1339  if (i>=argc-1)
1340  {
1341  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1342  Exit(EXIT_FAILURE);
1343  }
1344  card_motion_options = (string)argv[i+1];
1345  i++;
1346  }
1347  // Data for respiratory and cardiac motion corrections based on deformation
1348  else if (option=="-rcm")
1349  {
1350  if (i>=argc-1)
1351  {
1352  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1353  Exit(EXIT_FAILURE);
1354  }
1355  double_motion_options = (string)argv[i+1];
1356  i++;
1357  }
1358  // Data for involuntary motion correction based on deformation
1359  else if (option=="-im")
1360  {
1361  if (i>=argc-1)
1362  {
1363  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1364  Exit(EXIT_FAILURE);
1365  }
1366  ipat_motion_options = (string)argv[i+1];
1367  i++;
1368  }
1369  // Data for involuntary motion correction based on deformation
1370  else if (option=="-qdyn")
1371  {
1372  if (i>=argc-1)
1373  {
1374  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1375  Exit(EXIT_FAILURE);
1376  }
1377  path_to_dynamic_quantification_file = (string)argv[i+1];
1378  i++;
1379  }
1380 
1381  // --------------------------------------------------------------------------------
1382  // Input settings
1383  // --------------------------------------------------------------------------------
1384 
1385  // Datafiles
1386  else if (option=="-df") // This is a mandatory option
1387  {
1388  if (i>=argc-1)
1389  {
1390  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1391  Exit(EXIT_FAILURE);
1392  }
1393  string file_name = (string)argv[i+1];
1394  path_to_data_filename.push_back(file_name);
1395  nb_beds++;
1396  i++;
1397  }
1398  // Invert datafile order
1399  else if (option=="-df-inv")
1400  {
1401  invert_datafile_order_flag = true;
1402  }
1403  // Image for the initialisation of the algorithm : What should we do in case of multiple beds ? or multiple frames ? TODO
1404  else if (option=="-img")
1405  {
1406  if (i>=argc-1)
1407  {
1408  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1409  Exit(EXIT_FAILURE);
1410  }
1411  path_to_initial_img = argv[i+1];
1412  i++;
1413  }
1414  // Sensitivity image
1415  else if (option=="-sens")
1416  {
1417  if (i>=argc-1)
1418  {
1419  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1420  Exit(EXIT_FAILURE);
1421  }
1422 
1423  path_to_sensitivity_img = argv[i+1];
1424  i++;
1425  }
1426  // Normalization data files
1427  else if (option=="-norm")
1428  {
1429  if (i>=argc-1)
1430  {
1431  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1432  Exit(EXIT_FAILURE);
1433  }
1434  string file_name = (string)argv[i+1];
1435  path_to_normalization_filename.push_back(file_name);
1436  i++;
1437  }
1438 
1439  // Image for the attenuation
1440  else if (option=="-atn")
1441  {
1442  if (i>=argc-1)
1443  {
1444  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1445  Exit(EXIT_FAILURE);
1446  }
1447 
1448  path_to_attenuation_img = (string)argv[i+1];
1449 
1450  if (path_to_attenuation_img != "") // parse
1451  {
1452  // Retrieve nb of gated images from header if required
1453  Intf_fields IF;
1454  IntfKeyInitFields(&IF);
1455  if(IntfReadHeader(path_to_attenuation_img, &IF, 0) )
1456  {
1457  Cerr("***** castor-recon() -> An error occurred while trying to read the interfile header of attenuation file " << path_to_attenuation_img << " !" << endl);
1458  Exit(EXIT_FAILURE);
1459  }
1460  nb_atn_resp_imgs = IF.nb_resp_gates;
1461  nb_atn_card_imgs = IF.nb_card_gates;
1462  }
1463  i++;
1464  }
1465 
1466  // --------------------------------------------------------------------------------
1467  // Output settings
1468  // --------------------------------------------------------------------------------
1469 
1470  // Name of the output directory
1471  else if (option=="-dout") // This is a mandatory option
1472  {
1473  if (i>=argc-1)
1474  {
1475  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1476  Exit(EXIT_FAILURE);
1477  }
1478  path_dout = argv[i+1];
1479  i++;
1480  }
1481  // Base name of the output files
1482  else if (option=="-fout") // This is a mandatory option
1483  {
1484  if (i>=argc-1)
1485  {
1486  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1487  Exit(EXIT_FAILURE);
1488  }
1489  path_fout = argv[i+1];
1490  i++;
1491  }
1492  // List of iterations to be outputed
1493  else if (option=="-oit")
1494  {
1495  if (i>=argc-1)
1496  {
1497  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1498  Exit(EXIT_FAILURE);
1499  }
1500  output_iterations = (string)argv[i+1];
1501  i++;
1502  }
1503  // Flag to say that we want to save time basis functions too
1504  else if (option=="-omd")
1505  {
1506  merge_dynamic_imgs_flag = true;
1507  }
1508  // Flag to say that we want to save time basis functions too
1509  else if (option=="-olut")
1510  {
1511  save_LUT_flag = true;
1512  }
1513  // Flag to say that we want to save the sensitivity image for each subset/iteration in histogram mode
1514  else if (option=="-osens")
1515  {
1516  save_sens_histo = true;
1517  }
1518  // Flag to say that we want to save the image after each subset
1519  else if (option=="-osub")
1520  {
1521  save_subset_image = true;
1522  }
1523  // Flag to say that we want to save time basis functions too
1524  else if (option=="-otb")
1525  {
1526  Cerr("!!!!! castor-recon() -> Warning: option -otb not yet implemented !" << endl);
1527  }
1528  // Flag to say that we exit directly after computing and saving the sensitivity
1529  else if (option=="-sens-only")
1530  {
1531  exit_after_sensitivity = true;
1532  }
1533  // Flag to say that we still want to compute global sensitivity from the input histogram file
1534  else if (option=="-sens-histo")
1535  {
1536  sensitivity_from_histogram = true;
1537  }
1538 
1539  // --------------------------------------------------------------------------------
1540  // Algorithm settings
1541  // --------------------------------------------------------------------------------
1542 
1543  // List of iterations/subsets
1544  else if (option=="-it") // This is a mandatory option
1545  {
1546  if (i>=argc-1)
1547  {
1548  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1549  Exit(EXIT_FAILURE);
1550  }
1551  nb_iterations_subsets = (string)argv[i+1];
1552  i++;
1553  }
1554  // Optimizer settings
1555  else if (option=="-opti")
1556  {
1557  if (i>=argc-1)
1558  {
1559  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1560  Exit(EXIT_FAILURE);
1561  }
1562  options_optimizer = (string)argv[i+1];
1563  i++;
1564  }
1565  // Optimizer FOM
1566  else if (option=="-opti-fom")
1567  {
1568  optimizer_fom = true;
1569  }
1570  // Optimizer image update stat
1571  else if (option=="-opti-stat")
1572  {
1573  optimizer_stat = true;
1574  }
1575  // Penalty settings
1576  else if (option=="-penalty")
1577  {
1578  if (i>=argc-1)
1579  {
1580  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1581  Exit(EXIT_FAILURE);
1582  }
1583  options_penalty = (string)argv[i+1];
1584  i++;
1585  }
1586  // Image convolver settings
1587  else if (option=="-conv")
1588  {
1589  if (i>=argc-1)
1590  {
1591  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1592  Exit(EXIT_FAILURE);
1593  }
1594  string convolver = (string)argv[i+1];
1595  options_image_convolver.push_back(convolver);
1596  i++;
1597  }
1598  // Image processing settings
1599  else if (option=="-proc")
1600  {
1601  if (i>=argc-1)
1602  {
1603  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1604  Exit(EXIT_FAILURE);
1605  }
1606  string module = (string)argv[i+1];
1607  options_image_processing.push_back(module);
1608  i++;
1609  }
1610 
1611  // --------------------------------------------------------------------------------
1612  // Projection settings
1613  // --------------------------------------------------------------------------------
1614 
1615  // Projector settings
1616  else if (option=="-proj")
1617  {
1618  if (i>=argc-1)
1619  {
1620  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1621  Exit(EXIT_FAILURE);
1622  }
1623  options_projectorF = (string)argv[i+1];
1624  options_projectorB = (string)argv[i+1];
1625  i++;
1626  }
1627  // Forward projector settings
1628  else if (option=="-projF")
1629  {
1630  if (i>=argc-1)
1631  {
1632  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1633  Exit(EXIT_FAILURE);
1634  }
1635  options_projectorF = (string)argv[i+1];
1636  i++;
1637  }
1638  // Backward projector settings
1639  else if (option=="-projB")
1640  {
1641  if (i>=argc-1)
1642  {
1643  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1644  Exit(EXIT_FAILURE);
1645  }
1646  options_projectorB = (string)argv[i+1];
1647  i++;
1648  }
1649  // Common projector settings
1650  else if (option=="-proj-common")
1651  {
1652  if (i>=argc-1)
1653  {
1654  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1655  Exit(EXIT_FAILURE);
1656  }
1657  options_projector_common = (string)argv[i+1];
1658  i++;
1659  }
1660  // Ignore TOF flag
1661  else if (option=="-ignore-TOF")
1662  {
1663  ignore_TOF = true;
1664  }
1665  // Ignore POI flag
1666  else if (option=="-ignore-POI")
1667  {
1668  ignore_POI = true;
1669  }
1670  // Projection line computation strategy
1671  else if (option=="-proj-comp")
1672  {
1673  if (i>=argc-1)
1674  {
1675  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1676  Exit(EXIT_FAILURE);
1677  }
1678  projector_computation_strategy = atoi(argv[i+1]);
1679  i++;
1680  }
1681 
1682  // --------------------------------------------------------------------------------
1683  // Quantification settings
1684  // --------------------------------------------------------------------------------
1685 
1686  // Corrections settings
1687  else if (option=="-ignore-corr")
1688  {
1689  if (i>=argc-1)
1690  {
1691  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1692  Exit(EXIT_FAILURE);
1693  }
1694  ignored_corrections = (string)argv[i+1];
1695  i++;
1696  }
1697 
1698  // --------------------------------------------------------------------------------
1699  // Computation settings
1700  // --------------------------------------------------------------------------------
1701 
1702  // Flag to say that we want to use the GPU
1703  #ifdef CASTOR_GPU
1704  else if (option=="-gpu")
1705  {
1706  gpu_flag = 1;
1707  }
1708  #endif
1709  // Number of threads
1710  #ifdef CASTOR_OMP
1711  else if (option=="-th")
1712  {
1713  if (i>=argc-1)
1714  {
1715  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1716  Exit(EXIT_FAILURE);
1717  }
1718  nb_threads = (string)argv[i+1];
1719  i++;
1720  }
1721  #else
1722  else if (option=="-th")
1723  {
1724  if (i>=argc-1)
1725  {
1726  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1727  Exit(EXIT_FAILURE);
1728  }
1729  Cerr("!!!!! castor-recon() -> Option -th is available only if the code is compiled using the CASTOR_OMP environment variable set to 1 !" << endl);
1730  Cerr(" Press enter to continue with the execution BUT with only one thread." << endl);
1731  Cerr(" Or kill this and compile CASToR with OpenMP." << endl);
1732  getchar();
1733  i++;
1734  }
1735  #endif
1736  // Size of the buffer for data reading
1737  else if (option=="-load")
1738  {
1739  if (i>=argc-1)
1740  {
1741  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
1742  Exit(EXIT_FAILURE);
1743  }
1744  if (ConvertFromString(argv[i+1], &data_file_percentage_load))
1745  {
1746  Cerr("***** castor-recon() -> Error while trying to convert variable for option " << option << endl);
1747  Exit(EXIT_FAILURE);
1748  }
1749  if (data_file_percentage_load>100 || data_file_percentage_load<0)
1750  {
1751  Cerr("***** castor-recon() -> Incorrect initialization of the size data buffer" << endl);
1752  Cerr(" Number provided: " << argv[i+1] << " is not in the expected [0;100] interval" << endl);
1753  Exit(EXIT_FAILURE);
1754  }
1755  i++;
1756  }
1757 
1758  // --------------------------------------------------------------------------------
1759  // Unknown option!
1760  // --------------------------------------------------------------------------------
1761 
1762  else
1763  {
1764  Cerr("***** castor-recon() -> Unknown option '" << option << "' !" << endl);
1765  Exit(EXIT_FAILURE);
1766  }
1767  }
1768 
1769  // Synchronize MPI processes
1770  #ifdef CASTOR_MPI
1771  MPI_Barrier(MPI_COMM_WORLD);
1772  #endif
1773 
1774  // Affect specific verbose leves if not set
1775  if (verbose_algo==-1) verbose_algo = verbose_general;
1776  if (verbose_opti==-1) verbose_opti = verbose_general;
1777  if (verbose_proj==-1) verbose_proj = verbose_general;
1778  if (verbose_conv==-1) verbose_conv = verbose_general;
1779  if (verbose_proc==-1) verbose_proc = verbose_general;
1780  if (verbose_scan==-1) verbose_scan = verbose_general;
1781  if (verbose_data==-1) verbose_data = verbose_general;
1782  if (verbose_defo==-1) verbose_defo = verbose_general;
1783  if (verbose_dyna==-1) verbose_dyna = verbose_general;
1784  if (verbose_sens==-1) verbose_sens = verbose_general;
1785 
1786  // ============================================================================================================
1787  // Some checks
1788  // ============================================================================================================
1789 
1790  // Data files
1791  if (nb_beds < 1)
1792  {
1793  Cerr("***** castor-recon() -> Please provide at least one data filename !" << endl);
1794  Exit(EXIT_FAILURE);
1795  }
1796  // Output files
1797  if (path_fout.empty() && path_dout.empty())
1798  {
1799  Cerr("***** castor-recon() -> Please provide an output option for output files (-fout or -dout) !" << endl);
1800  Exit(EXIT_FAILURE);
1801  }
1802  // Check that only one option has been provided
1803  if (!path_fout.empty() && !path_dout.empty())
1804  {
1805  Cerr("***** castor-recon() -> Please provide either output option -fout or -dout but not both !" << endl);
1806  Exit(EXIT_FAILURE);
1807  }
1808 
1809  // Check if gated reconstruction is enabled but no file describing the gating of the data has been provided
1810  // TODO: maybe do it in the dynamic data manager if possible to clean this main as much as possible
1811  if ( (nb_resp_gates>1 || nb_card_gates>1) && path_to_4D_data_splitting_file.empty() )
1812  {
1813  Cerr("***** castor-recon() -> gating is enabled, but no file describing the splitting of the data has been provided (-gating option) !" << endl);
1814  Exit(EXIT_FAILURE);
1815  }
1816 
1817  // ============================================================================================================
1818  // Singletons initialization: create here all needed singletons
1819  // ============================================================================================================
1820 
1821  if (verbose_general>=5) Cout("----- Singletons initializations ... -----" << endl);
1822 
1823  // Get user endianness (interfile I/O)
1825 
1826  // ----------------------------------------------------------------------------------------
1827  // Create sOutputManager
1828  // ----------------------------------------------------------------------------------------
1829  sOutputManager* p_outputManager = sOutputManager::GetInstance();
1830  // Set verbose level
1831  p_outputManager->SetVerbose(verbose_general);
1832  // Set MPI rank
1833  p_outputManager->SetMPIRank(mpi_rank);
1834  // Set output dynamic image policy
1835  p_outputManager->SetMergeDynImagesFlag(merge_dynamic_imgs_flag);
1836 
1837  // Set path to the config directory
1838  if (p_outputManager->CheckConfigDir(path_to_config_dir))
1839  {
1840  Cerr("***** castor-recon() -> A problem occured while checking for the config directory path !" << endl);
1841  Exit(EXIT_FAILURE);
1842  }
1843  // Initialize output directory and base name
1844  if (p_outputManager->InitOutputDirectory(path_fout, path_dout))
1845  {
1846  Cerr("***** castor-recon() -> A problem occured while initializing output directory !" << endl);
1847  Exit(EXIT_FAILURE);
1848  }
1849  // Log command line
1850  if (p_outputManager->LogCommandLine(argc,argv))
1851  {
1852  Cerr("***** castor-recon() -> A problem occured while logging command line arguments !" << endl);
1853  Exit(EXIT_FAILURE);
1854  }
1855 
1856  // ----------------------------------------------------------------------------------------
1857  // Create sScannerManager
1858  // ----------------------------------------------------------------------------------------
1859  sScannerManager* p_ScannerManager = sScannerManager::GetInstance();
1860  p_ScannerManager->SetVerbose(verbose_scan);
1861  p_ScannerManager->SetSaveLUTFlag(save_LUT_flag);
1862 
1863  if (verbose_general>=5) Cout("----- Singletons initializations OK -----" << endl);
1864 
1865  // ============================================================================================================
1866  // Objects initialization: create here all elements needed for the algorithm
1867  // ============================================================================================================
1868 
1869  if (verbose_general>=5) Cout("----- Geometry Initialization ... -----" << endl);
1870 
1871  // ----------------------------------------------------------------------------------------
1872  // Search the type of scanner using the sScannerManager
1873  // ----------------------------------------------------------------------------------------
1874 
1875  // TODO: put all that stuff into only one function taking the path_to_data_filename[0] as the only parameter
1876 
1877  // Get system name from the dataFile
1878  string scanner_name = "";
1879  if (ReadDataASCIIFile(path_to_data_filename[0], "Scanner name", &scanner_name, 1, KEYWORD_MANDATORY))
1880  {
1881  Cerr("***** castor-recon() -> A problem occured while trying to find the system name in the datafile header !" << endl);
1882  Exit(EXIT_FAILURE);
1883  }
1884  if (p_ScannerManager->FindScannerSystem(scanner_name) )
1885  {
1886  Cerr("***** castor-recon() -> A problem occurred while searching for scanner system !" << endl);
1887  Exit(EXIT_FAILURE);
1888  }
1889  if (p_ScannerManager->BuildScannerObject() )
1890  {
1891  Cerr("***** castor-recon() -> A problem occurred during scanner object construction ! !" << endl);
1892  Exit(EXIT_FAILURE);
1893  }
1894  if (p_ScannerManager->InstantiateScanner() )
1895  {
1896  Cerr("***** castor-recon() -> A problem occurred while creating Scanner object !" << endl);
1897  Exit(EXIT_FAILURE);
1898  }
1899  if (p_ScannerManager->GetGeometricInfoFromDatafile(path_to_data_filename[0]))
1900  {
1901  Cerr("***** castor-recon() -> A problem occurred while retrieving scanner fields from the datafile header !" << endl);
1902  Exit(EXIT_FAILURE);
1903  }
1904  if (p_ScannerManager->BuildLUT() )
1905  {
1906  Cerr("***** castor-recon() -> A problem occurred while generating/reading the LUT !" << endl);
1907  Exit(EXIT_FAILURE);
1908  }
1909  // Check the scanner manager parameters and initialize the scanner
1910  if (p_ScannerManager->CheckParameters())
1911  {
1912  Cerr("***** castor-recon() -> A problem occured while checking scanner manager parameters !" << endl);
1913  Exit(EXIT_FAILURE);
1914  }
1915  if (p_ScannerManager->Initialize())
1916  {
1917  Cerr("***** castor-recon() -> A problem occured while initializing scanner !" << endl);
1918  Exit(EXIT_FAILURE);
1919  }
1920 
1921  if (verbose_general>=5) Cout("----- Geometry Initialization OK -----" << endl);
1922 
1923  // If no number of voxels provided, then get the default ones from the scanner
1924  if (nb_voxX<=0 || nb_voxY<=0 || nb_voxZ<=0)
1925  {
1926  if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "voxels number transaxial", &nb_voxX, 1, KEYWORD_MANDATORY))
1927  {
1928  Cerr("***** castor-recon() -> A problem occured while reading for default number of transaxial voxels !" << endl);
1929  Exit(EXIT_FAILURE);
1930  }
1931  if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "voxels number transaxial", &nb_voxY, 1, KEYWORD_MANDATORY))
1932  {
1933  Cerr("***** castor-recon() -> A problem occured while reading for default number of transaxial voxels !" << endl);
1934  Exit(EXIT_FAILURE);
1935  }
1936  if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "voxels number axial", &nb_voxZ, 1, KEYWORD_MANDATORY))
1937  {
1938  Cerr("***** castor-recon() -> A problem occured while reading for default number of axial voxels !" << endl);
1939  Exit(EXIT_FAILURE);
1940  }
1941  }
1942  // If no FOV nor VOX size provided, then get the default one
1943  if ( (fov_sizeX<=0 || fov_sizeY<=0 || fov_sizeZ<=0) && (vox_sizeX<=0 || vox_sizeY<=0 || vox_sizeZ<=0) )
1944  {
1945  if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "field of view transaxial", &fov_sizeX, 1, KEYWORD_MANDATORY))
1946  {
1947  Cerr("***** castor-recon() -> A problem occured while reading for default transaxial FOV size !" << endl);
1948  Exit(EXIT_FAILURE);
1949  }
1950  if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "field of view transaxial", &fov_sizeY, 1, KEYWORD_MANDATORY))
1951  {
1952  Cerr("***** castor-recon() -> A problem occured while reading for default transaxial FOV size !" << endl);
1953  Exit(EXIT_FAILURE);
1954  }
1955  if (ReadDataASCIIFile(p_ScannerManager->GetPathToScannerFile(), "field of view axial", &fov_sizeZ, 1, KEYWORD_MANDATORY))
1956  {
1957  Cerr("***** castor-recon() -> A problem occured while reading for default axial FOV size !" << endl);
1958  Exit(EXIT_FAILURE);
1959  }
1960  }
1961 
1962  // ----------------------------------------------------------------------------------------
1963  // Create oImageDimensionsAndQuantification
1964  // ----------------------------------------------------------------------------------------
1965 
1966  if (verbose_general>=5) Cout("----- Image dimensions initialization ... -----" << endl);
1967 
1968  oImageDimensionsAndQuantification* p_ImageDimensionsAndQuantification = new oImageDimensionsAndQuantification();
1969  if (p_ImageDimensionsAndQuantification->SetNbThreads(nb_threads))
1970  {
1971  Cerr("***** castor-recon() -> A problem occured while setting the number of threads !" << endl);
1972  Exit(EXIT_FAILURE);
1973  }
1974  p_ImageDimensionsAndQuantification->SetNbBeds(nb_beds);
1975  p_ImageDimensionsAndQuantification->SetNbVoxX(nb_voxX);
1976  p_ImageDimensionsAndQuantification->SetNbVoxY(nb_voxY);
1977  p_ImageDimensionsAndQuantification->SetNbVoxZ(nb_voxZ);
1978  p_ImageDimensionsAndQuantification->SetVoxSizeX(vox_sizeX);
1979  p_ImageDimensionsAndQuantification->SetVoxSizeY(vox_sizeY);
1980  p_ImageDimensionsAndQuantification->SetVoxSizeZ(vox_sizeZ);
1981  p_ImageDimensionsAndQuantification->SetFOVSizeX(fov_sizeX);
1982  p_ImageDimensionsAndQuantification->SetFOVSizeY(fov_sizeY);
1983  p_ImageDimensionsAndQuantification->SetFOVSizeZ(fov_sizeZ);
1984  p_ImageDimensionsAndQuantification->SetFOVOutMasking(fov_out,slice_out);
1985  p_ImageDimensionsAndQuantification->SetOffsetX(offsetX);
1986  p_ImageDimensionsAndQuantification->SetOffsetY(offsetY);
1987  p_ImageDimensionsAndQuantification->SetOffsetZ(offsetZ);
1988  p_ImageDimensionsAndQuantification->SetMPIRankAndSize(mpi_rank, mpi_size);
1989  p_ImageDimensionsAndQuantification->SetVerbose(verbose_data);
1990  p_ImageDimensionsAndQuantification->SetIgnoredCorrections(ignored_corrections);
1991  p_ImageDimensionsAndQuantification->SetFrames(frame_list);
1992  p_ImageDimensionsAndQuantification->SetNbTimeBasisFunctions(nb_time_basis);
1993  p_ImageDimensionsAndQuantification->SetTimeBasisFunctionsFile(path_to_time_basis_coef);
1994  if (p_ImageDimensionsAndQuantification->SetFlipOut(flip_out))
1995  {
1996  Cerr("***** castor-recon() -> A problem occured while setting the output flip option !" << endl);
1997  Exit(EXIT_FAILURE);
1998  }
1999  if (resp_motion_options=="" && double_motion_options=="")
2000  {
2001  p_ImageDimensionsAndQuantification->SetNbRespGates(nb_resp_gates);
2002  p_ImageDimensionsAndQuantification->SetNbRespBasisFunctions(nb_resp_basis);
2003  p_ImageDimensionsAndQuantification->SetRespBasisFunctionsFile(path_to_resp_basis_coef);
2004  }
2005  else
2006  {
2007  if (path_to_resp_basis_coef!="")
2008  {
2009  Cerr("***** castor-recon() -> Cannot use both respiratory motion correction and respiratory basis functions, it has no sense !" << endl);
2010  Exit(EXIT_FAILURE);
2011  }
2012  // Set only one gate here because we correct for motion, so we reconstruct only one image
2013  p_ImageDimensionsAndQuantification->SetNbRespGates(1);
2014  }
2015  if (card_motion_options=="" && double_motion_options=="")
2016  {
2017  p_ImageDimensionsAndQuantification->SetNbCardGates(nb_card_gates);
2018  p_ImageDimensionsAndQuantification->SetNbCardBasisFunctions(nb_card_basis);
2019  p_ImageDimensionsAndQuantification->SetCardBasisFunctionsFile(path_to_card_basis_coef);
2020  }
2021  else
2022  {
2023  if (path_to_card_basis_coef!="")
2024  {
2025  Cerr("***** castor-recon() -> Cannot use both cardiac motion correction and cardiac basis functions, it has no sense !" << endl);
2026  Exit(EXIT_FAILURE);
2027  }
2028  // Set only one gate here because we correct for motion, so we reconstruct only one image
2029  p_ImageDimensionsAndQuantification->SetNbCardGates(1);
2030  }
2031  if (p_ImageDimensionsAndQuantification->CheckParameters())
2032  {
2033  Cerr("***** castor-recon() -> A problem occured while checking image dimensions parameters !" << endl);
2034  Exit(EXIT_FAILURE);
2035  }
2036  if (p_ImageDimensionsAndQuantification->Initialize())
2037  {
2038  Cerr("***** castor-recon() -> A problem occured while initializing image dimensions !" << endl);
2039  Exit(EXIT_FAILURE);
2040  }
2041  // Initialization of DynamicDataManager class, related 4D data splitting management
2042  if (p_ImageDimensionsAndQuantification->InitDynamicData(path_to_4D_data_splitting_file,
2043  !resp_motion_options.empty(),
2044  !card_motion_options.empty(),
2045  !double_motion_options.empty(),
2046  !ipat_motion_options.empty(),
2047  nb_resp_gates,
2048  nb_card_gates) )
2049  {
2050  Cerr("***** castor-recon() -> A problem occured while initializing Dynamic data manager's class !" << endl);
2051  Exit(EXIT_FAILURE);
2052  }
2053  // Get the number of events in the data from the header (in order to check consistency between
2054  // the number of events in the datafile and in the dynamic files, if any gating is enabled)
2055  int64_t nb_events = 0;
2056  ReadDataASCIIFile(path_to_data_filename[0], "Number of events", &nb_events, 1, KEYWORD_MANDATORY);
2057  // Check dynamic parameters
2058  if (p_ImageDimensionsAndQuantification->CheckDynamicParameters(nb_events) )
2059  {
2060  Cerr("***** castor-recon() -> A problem occured while checking Dynamic data manager's parameters !" << endl);
2061  Exit(EXIT_FAILURE);
2062  }
2063  // Initialize dynamic specific quantitative factors
2064  if (p_ImageDimensionsAndQuantification->SetDynamicSpecificQuantificationFactors(path_to_dynamic_quantification_file) )
2065  {
2066  Cerr("***** castor-recon() -> A problem occured while initializing specific dynamic quantification factors!" << endl);
2067  Exit(EXIT_FAILURE);
2068  }
2069 
2070  if (verbose_general>=5) Cout("----- Image dimensions initialization OK -----" << endl);
2071 
2072  // ----------------------------------------------------------------------------------------
2073  // Random Number Generator initialization: (we first require to know the number of threads to use from p_ImageDimensionsAndQuantification)
2074  // ----------------------------------------------------------------------------------------
2075 
2076  if (verbose_general>=5) Cout("----- Random number generator initialization ... -----" << endl);
2077 
2079  p_RNG->SetVerbose(verbose_general);
2080  // Use a user-provided seed to initialize the RNG if one has been provided. Use random number otherwise.
2081  if (seed_RNG>=0) p_RNG->Initialize(seed_RNG, p_ImageDimensionsAndQuantification->GetNbThreadsMax());
2082  else p_RNG->Initialize(p_ImageDimensionsAndQuantification->GetNbThreadsMax());
2083 
2084  if (verbose_general >=5) Cout("----- Random number generator initialization OK -----" << endl);
2085 
2086  // ----------------------------------------------------------------------------------------
2087  // Create vDataFile
2088  // ----------------------------------------------------------------------------------------
2089 
2090  if (verbose_general>=5) Cout("----- Datafile initialization ... -----" << endl);
2091 
2092  vDataFile** p_DataFile = new vDataFile*[nb_beds];
2093 
2094  if (p_ScannerManager->GetScannerType() == SCANNER_PET)
2095  {
2096  // Create specific data file
2097  for (int i=0 ; i<nb_beds ; i++)
2098  {
2099  p_DataFile[i] = new iDataFilePET(); //TODO recup load data file ou pas
2100  (dynamic_cast<iDataFilePET*>(p_DataFile[i]))->SetIgnoreTOFFlag(ignore_TOF);
2101  }
2102  }
2103  else if (p_ScannerManager->GetScannerType() == SCANNER_SPECT_CONVERGENT)
2104  {
2105  // Create specific data file
2106  for (int i=0 ; i<nb_beds ; i++)
2107  {
2108  p_DataFile[i] = new iDataFileSPECT();
2109  }
2110  }
2111  // Unknown scanner
2112  else
2113  {
2114  Cerr("***** castor-recon() -> Unknown scanner type (" << p_ScannerManager->GetScannerType() << ") detected by sScannerManager ! Abort." << endl);
2115  Exit(EXIT_FAILURE);
2116  }
2117 
2118  // Load raw data in memory and do other stuff if needed.
2119  for (int bed=0 ; bed<nb_beds ; bed++)
2120  {
2121  // If it is asked to revert the order of the bed positions, then we proceed here
2122  if (invert_datafile_order_flag) p_DataFile[bed]->SetHeaderDataFileName(path_to_data_filename.at(nb_beds-1-bed));
2123  else p_DataFile[bed]->SetHeaderDataFileName(path_to_data_filename.at(bed));
2124  p_DataFile[bed]->SetBedIndex(bed);
2125  p_DataFile[bed]->SetPercentageLoad(data_file_percentage_load);
2126  p_DataFile[bed]->SetVerbose(verbose_data);
2127  p_DataFile[bed]->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2128  p_DataFile[bed]->SetIgnorePOIFlag(ignore_POI);
2129  if (p_DataFile[bed]->ReadInfoInHeader())
2130  {
2131  Cerr("***** castor-recon() -> A problem occurred during datafile header reading ! Abort." << endl);
2132  Exit(EXIT_FAILURE);
2133  }
2134  if (p_DataFile[bed]->CheckParameters())
2135  {
2136  Cerr("***** castor-recon() -> A problem occurred while checking datafile parameters ! Abort." << endl);
2137  Exit(EXIT_FAILURE);
2138  }
2139  if (p_DataFile[bed]->ComputeSizeEvent())
2140  {
2141  Cerr("***** castor-recon() -> A problem occurred in datafile initialization ! Abort." << endl);
2142  Exit(EXIT_FAILURE);
2143  }
2144  if (p_DataFile[bed]->InitializeFile())
2145  {
2146  Cerr("***** castor-recon() -> A problem occurred in datafile initialization ! Abort." << endl);
2147  Exit(EXIT_FAILURE);
2148  }
2149  if (p_DataFile[bed]->PrepareDataFile())
2150  {
2151  Cerr("***** castor-recon() -> A problem occured in datafile preparation ! Abort." << endl);
2152  Exit(EXIT_FAILURE);
2153  }
2154  }
2155  // Check consistency between all datafiles; to do that we compare the first with all the others
2156  for (int bed=1; bed<nb_beds; bed++)
2157  {
2158  if (p_DataFile[0]->CheckConsistencyWithAnotherBedDatafile(p_DataFile[bed]))
2159  {
2160  int bed_index_problem = bed + 1;
2161  if (invert_datafile_order_flag) bed_index_problem = nb_beds - bed;
2162  Cerr("***** castor-recon() -> A problem occured while checking consistency between first bed and bed " << bed_index_problem << " !" << endl);
2163  Exit(EXIT_FAILURE);
2164  }
2165  }
2166 
2167  if (verbose_general>=5) Cout("----- Datafile initialization OK -----" << endl);
2168 
2169  // ----------------------------------------------------------------------------------------
2170  // Create Projector Manager
2171  // ----------------------------------------------------------------------------------------
2172 
2173  // Verbose
2174  if (verbose_general>=5) Cout("----- Projector initialization ... -----" << endl);
2175  // Create object
2176  oProjectorManager* p_ProjectorManager = new oProjectorManager();
2177  // Set all parameters
2178  p_ProjectorManager->SetScanner(p_ScannerManager->GetScannerObject());
2179  p_ProjectorManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2180  p_ProjectorManager->SetDataFile(p_DataFile[0]);
2181  p_ProjectorManager->SetComputationStrategy(projector_computation_strategy);
2182  p_ProjectorManager->SetOptionsForward(options_projectorF);
2183  p_ProjectorManager->SetOptionsBackward(options_projectorB);
2184  p_ProjectorManager->SetOptionsCommon(options_projector_common);
2185  p_ProjectorManager->SetVerbose(verbose_proj);
2186  // Check parameters
2187  if (p_ProjectorManager->CheckParameters())
2188  {
2189  Cerr("***** castor-recon() -> A problem occured while checking projector manager's parameters !" << endl);
2190  Exit(EXIT_FAILURE);
2191  }
2192  // Initialize projector manager
2193  if (p_ProjectorManager->Initialize())
2194  {
2195  Cerr("***** castor-recon() -> A problem occured while initializing projector manager !" << endl);
2196  Exit(EXIT_FAILURE);
2197  }
2198  // Check specific requirements for SPECT with attenuation correction
2199  if (p_ProjectorManager->CheckSPECTAttenuationCompatibility(path_to_attenuation_img))
2200  {
2201  Cerr("***** castor-recon() -> A problem occured while checking projector's compatibility with SPECT and attenuation correction !" << endl);
2202  Exit(EXIT_FAILURE);
2203  }
2204  // Verbose
2205  if (verbose_general>=5) Cout("----- Projector initialization OK -----" << endl);
2206 
2207  // ----------------------------------------------------------------------------------------
2208  // Create Optimizer Manager
2209  // ----------------------------------------------------------------------------------------
2210 
2211  // Verbose
2212  if (verbose_general>=5) Cout("----- Optimizer initialization ... -----" << endl);
2213  // Create object
2214  oOptimizerManager* p_OptimizerManager = new oOptimizerManager();
2215  // Set all parameters
2216  p_OptimizerManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2217  p_OptimizerManager->SetDataMode(p_DataFile[0]->GetDataMode());
2218  p_OptimizerManager->SetDataType(p_DataFile[0]->GetDataType());
2219  p_OptimizerManager->SetOptionsOptimizer(options_optimizer);
2220  p_OptimizerManager->SetOptimizerFOMFlag(optimizer_fom);
2221  p_OptimizerManager->SetOptimizerImageStatFlag(optimizer_stat);
2222  p_OptimizerManager->SetOptionsPenalty(options_penalty);
2223  p_OptimizerManager->SetNbTOFBins(p_ProjectorManager->GetNbTOFBins());
2224  p_OptimizerManager->SetVerbose(verbose_opti);
2225  // Check parameters
2226  if (p_OptimizerManager->CheckParameters())
2227  {
2228  Cerr("***** castor-recon() -> A problem occured while checking optimizer manager's parameters !" << endl);
2229  Exit(EXIT_FAILURE);
2230  }
2231  // Initialize optimizer manager
2232  if (p_OptimizerManager->Initialize())
2233  {
2234  Cerr("***** castor-recon() -> A problem occured while initializing optimizer manager !" << endl);
2235  Exit(EXIT_FAILURE);
2236  }
2237  // Verbose
2238  if (verbose_general>=5) Cout("----- Optimizer initialization OK -----" << endl);
2239 
2240  // ----------------------------------------------------------------------------------------
2241  // Create Image Convolver Manager
2242  // ----------------------------------------------------------------------------------------
2243 
2244  // Verbose
2245  if (verbose_general>=5) Cout("----- Image Convolver initialization (if any) ... -----" << endl);
2246  // Create object
2247  oImageConvolverManager* p_ImageConvolverManager = new oImageConvolverManager();
2248  // Set all parameters
2249  p_ImageConvolverManager->SetVerbose(verbose_conv);
2250  p_ImageConvolverManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2251  p_ImageConvolverManager->SetOptions(options_image_convolver);
2252  // Check parameters
2253  if (p_ImageConvolverManager->CheckParameters())
2254  {
2255  Cerr("***** castor-recon() -> A problem occured while checking image convolver manager's parameters !" << endl);
2256  Exit(EXIT_FAILURE);
2257  }
2258  // Initialize image convolver manager
2259  if (p_ImageConvolverManager->Initialize())
2260  {
2261  Cerr("***** castor-recon() -> A problem occured while initializing image convolver manager !" << endl);
2262  Exit(EXIT_FAILURE);
2263  }
2264  // Verbose
2265  if (verbose_general>=5) Cout("----- Image Convolver initialization OK -----" << endl);
2266 
2267  // ----------------------------------------------------------------------------------------
2268  // Create Image Processing Manager
2269  // ----------------------------------------------------------------------------------------
2270 
2271  // Verbose
2272  if (verbose_general>=5) Cout("----- Image Processing initialization (if any) ... -----" << endl);
2273  // Create object
2274  oImageProcessingManager* p_ImageProcessingManager = new oImageProcessingManager();
2275  // Set all parameters
2276  p_ImageProcessingManager->SetVerbose(verbose_proc);
2277  p_ImageProcessingManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2278  p_ImageProcessingManager->SetOptions(options_image_processing);
2279  // Check parameters
2280  if (p_ImageProcessingManager->CheckParameters())
2281  {
2282  Cerr("***** castor-recon() -> A problem occured while checking image processing manager's parameters !" << endl);
2283  Exit(EXIT_FAILURE);
2284  }
2285  // Initialize image processing manager
2286  if (p_ImageProcessingManager->Initialize())
2287  {
2288  Cerr("***** castor-recon() -> A problem occured while initializing image processing manager !" << endl);
2289  Exit(EXIT_FAILURE);
2290  }
2291  // Verbose
2292  if (verbose_general>=5) Cout("----- Image Processing initialization OK -----" << endl);
2293 
2294  // ----------------------------------------------------------------------------------------
2295  // Create Dynamic Model Manager
2296  // ----------------------------------------------------------------------------------------
2297 
2298  // Verbose
2299  if (verbose_general>=5) Cout("----- Dynamic model initialization (if any) ... -----" << endl);
2300  // Create object
2301  oDynamicModelManager* p_DynamicModelManager = new oDynamicModelManager();
2302  // Set all parameters
2303  p_DynamicModelManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2304  p_DynamicModelManager->SetOptions(dynamic_model_options);
2305  p_DynamicModelManager->SetVerbose(verbose_dyna);
2306  // Check parameters
2307  if (p_DynamicModelManager->CheckParameters())
2308  {
2309  Cerr("***** castor-recon() -> A problem occured while checking dynamic model manager's parameters !" << endl);
2310  Exit(EXIT_FAILURE);
2311  }
2312  // Initialize optimizer manager
2313  if (p_DynamicModelManager->Initialize())
2314  {
2315  Cerr("***** castor-recon() -> A problem occured while initializing dynamic model manager !" << endl);
2316  Exit(EXIT_FAILURE);
2317  }
2318  // Verbose
2319  if (verbose_general>=5) Cout("----- Dynamic model initialization OK -----" << endl);
2320 
2321  // ----------------------------------------------------------------------------------------
2322  // Create Deformation Manager
2323  // ----------------------------------------------------------------------------------------
2324 
2325  // Verbose
2326  if (verbose_general>=5) Cout("----- Image deformation initialization (if any) ... -----" << endl);
2327  // Create object
2328  oDeformationManager* p_DeformationManager = new oDeformationManager();
2329  // Set all parameters
2330  p_DeformationManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2331  p_DeformationManager->SetDataMode(p_DataFile[0]->GetDataMode()); // required to know if sensitivity image deformation should be enabled
2332 
2333  if(resp_motion_options != "")
2334  {
2335  p_DeformationManager->SetOptions(resp_motion_options);
2336  p_DeformationManager->SetNbTransformations(nb_resp_gates);
2337  p_DeformationManager->SetMotionType(DEF_RESP_MOT);
2338  }
2339  else if (card_motion_options != "")
2340  {
2341  p_DeformationManager->SetOptions(card_motion_options);
2342  p_DeformationManager->SetNbTransformations(nb_card_gates);
2343  p_DeformationManager->SetMotionType(DEF_CARD_MOT);
2344  }
2345  else if (double_motion_options != "")
2346  {
2347  p_DeformationManager->SetOptions(double_motion_options);
2348  p_DeformationManager->SetNbTransformations(nb_resp_gates*nb_card_gates);
2349  p_DeformationManager->SetMotionType(DEF_DUAL_MOT);
2350  }
2351  else if (ipat_motion_options != "")
2352  {
2353  p_DeformationManager->SetOptions(ipat_motion_options);
2354  p_DeformationManager->SetNbTransformations(p_ImageDimensionsAndQuantification->GetNbIPatMotionSubsets());
2355  p_DeformationManager->SetMotionType(DEF_IPAT_MOT);
2356  }
2357  else
2358  p_DeformationManager->SetNbTransformations(0);
2359 
2360  p_DeformationManager->SetVerbose(verbose_defo);
2361  // Check parameters
2362  if (p_DeformationManager->CheckParameters())
2363  {
2364  Cerr("***** castor-recon() -> A problem occured while checking image deformation manager's parameters !" << endl);
2365  Exit(EXIT_FAILURE);
2366  }
2367  // Initialize optimizer manager
2368  if (p_DeformationManager->Initialize())
2369  {
2370  Cerr("***** castor-recon() -> A problem occured while initializing image deformation manager !" << endl);
2371  Exit(EXIT_FAILURE);
2372  }
2373  // Verbose
2374  if (verbose_general >=5) Cout("----- Image deformation initialization OK -----" << endl);
2375 
2376  // ----------------------------------------------------------------------------------------
2377  // Create the image space
2378  // ----------------------------------------------------------------------------------------
2379 
2380  oImageSpace* p_ImageSpace = new oImageSpace();
2381  p_ImageSpace->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2382  p_ImageSpace->SetVerbose(verbose_data);
2383 
2384  // ============================================================================================================
2385  // Algorithm initialization: create here sensitivity computation and launch algorithm
2386  // ============================================================================================================
2387 
2388  // --------------------------------------------------------------------------------------------
2389  // Create sensitivity if the sensitivity is not provided and if one of the following conditions
2390  // 1. Input file is a list-mode file
2391  // 2. Input file is a histogram and the -sens-histo option is provided
2392  // --------------------------------------------------------------------------------------------
2393  if ( path_to_sensitivity_img.empty() && (
2394  p_DataFile[0]->GetDataMode()==MODE_LIST ||
2395  (p_DataFile[0]->GetDataMode()==MODE_HISTOGRAM && sensitivity_from_histogram)
2396  )
2397  )
2398  {
2399  // Verbose
2400  if (verbose_general>=5) Cout("----- Image Sensitivity generation for list-mode initialization ... -----" << endl);
2401  // Create object
2402  oSensitivityGenerator* p_Sensitivity = new oSensitivityGenerator();
2403  // Set parameters
2404  p_Sensitivity->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2405  p_Sensitivity->SetImageSpace(p_ImageSpace);
2406  p_Sensitivity->SetScanner(p_ScannerManager->GetScannerObject());
2407  p_Sensitivity->SetProjectorManager(p_ProjectorManager);
2408  p_Sensitivity->SetImageConvolverManager(p_ImageConvolverManager);
2409  p_Sensitivity->SetDeformationManager(p_DeformationManager);
2410  p_Sensitivity->SetGPUflag(gpu_flag);
2411  p_Sensitivity->SetPathToAttenuationImage(path_to_attenuation_img);
2412  p_Sensitivity->SetNumberOfAtnGateImages(nb_atn_resp_imgs, nb_atn_card_imgs);
2413  p_Sensitivity->SetPathToNormalizationFileName(path_to_normalization_filename,invert_datafile_order_flag);
2414  p_Sensitivity->SetDataFile(p_DataFile);
2415  p_Sensitivity->SetComputeFromHistogramFlag(sensitivity_from_histogram);
2416  p_Sensitivity->SetVerbose(verbose_sens);
2417  // Check parameters
2418  if (p_Sensitivity->CheckParameters())
2419  {
2420  Cerr("***** castor-recon() -> A problem occured while checking parameters of the sensitivity generator !" << endl);
2421  Exit(EXIT_FAILURE);
2422  }
2423  // Initialize the sensitivity generator
2424  if (p_Sensitivity->Initialize())
2425  {
2426  Cerr("***** castor-recon() -> A problem occured while initializing the sensitivity generator !" << endl);
2427  Exit(EXIT_FAILURE);
2428  }
2429  // Launch the computation
2430  if (p_Sensitivity->Launch())
2431  {
2432  Cerr("***** castor-recon() -> A problem occured while computing the sensitivity !" << endl);
2433  Exit(EXIT_FAILURE);
2434  }
2435  // Get the path to the sensitivity image (will be given to the algorithm if input file is a list-mode)
2436  if (p_DataFile[0]->GetDataMode()==MODE_LIST) path_to_sensitivity_img = p_Sensitivity->GetPathToSensitivityImage();
2437  else path_to_sensitivity_img = "";
2438  // Delete the generator
2439  delete p_Sensitivity;
2440  // Exit now if asked for
2441  if (exit_after_sensitivity)
2442  {
2443  // Delete objects in the inverse order in which they were created
2444  delete p_ImageSpace;
2445  delete p_DeformationManager;
2446  delete p_DynamicModelManager;
2447  delete p_ImageProcessingManager;
2448  delete p_ImageConvolverManager;
2449  delete p_OptimizerManager;
2450  delete p_ProjectorManager;
2451  for (int i=0 ; i<nb_beds ; i++) delete p_DataFile[i];
2452  delete[] p_DataFile;
2453  delete p_ImageDimensionsAndQuantification;
2454  // And exit
2455  return 0;
2456  }
2457  }
2458 
2459  // ----------------------------------------------------------------------------------------
2460  // Create algorithm
2461  // ----------------------------------------------------------------------------------------
2462 
2463  // If the number of events in a datafile is below the number of threads for projections, then we must reduce this number of threads, otherwise
2464  // the datafile reading cannot work (and it has no sense anyway). This is done by the following function
2465  p_ImageDimensionsAndQuantification->CheckNumberOfProjectionThreadsConsistencyWithDatafileSize(p_DataFile);
2466  // Verbose
2467  if (verbose_general>=5) Cout("----- Iterative reconstruction algorithm initialization ... -----" << endl);
2468  // Create object
2469  oIterativeAlgorithm* p_Algorithm = new oIterativeAlgorithm();
2470  // Set parameters
2471  p_Algorithm->SetImageConvolverManager(p_ImageConvolverManager);
2472  p_Algorithm->SetImageProcessingManager(p_ImageProcessingManager);
2473  p_Algorithm->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
2474  p_Algorithm->SetImageSpace(p_ImageSpace);
2475  p_Algorithm->SetProjectorManager(p_ProjectorManager);
2476  p_Algorithm->SetDynamicModelManager(p_DynamicModelManager);
2477  p_Algorithm->SetDeformationManager(p_DeformationManager);
2478  p_Algorithm->SetOptimizerManager(p_OptimizerManager);
2479  p_Algorithm->SetDataFile(p_DataFile);
2480  p_Algorithm->SetGPUflag(gpu_flag);
2481  p_Algorithm->SetVerbose(verbose_algo);
2482  p_Algorithm->SetNbBeds(nb_beds);
2483  p_Algorithm->SetPathInitImage(path_to_initial_img);
2484  p_Algorithm->SetPathToAttenuationImage(path_to_attenuation_img);
2485  p_Algorithm->SetPathToSensitivityImage(path_to_sensitivity_img);
2486  p_Algorithm->SetSaveSensitivityHistoFlag(save_sens_histo);
2487  p_Algorithm->SetSaveSubsetImageFlag(save_subset_image);
2488  if (p_Algorithm->SetNbIterationsAndSubsets(nb_iterations_subsets))
2489  {
2490  Cerr("***** castor-recon() -> Error while setting the numbers of iterations and subsets !" << endl);
2491  Exit(EXIT_FAILURE);
2492  }
2493  if (p_Algorithm->SetOutputIterations(output_iterations))
2494  {
2495  Cerr("***** castor-recon() -> Error while setting the selected output iterations !" << endl);
2496  Exit(EXIT_FAILURE);
2497  }
2498  if (p_Algorithm->Iterate())
2499  {
2500  Cerr("***** castor-recon() -> Error while performing the reconstruction" << endl);
2501  Exit(EXIT_FAILURE);
2502  }
2503 
2504  // ============================================================================================================
2505  // End
2506  // ============================================================================================================
2507 
2508  // Delete objects in the inverse order in which they were created
2509  if (verbose_general>=5) Cout("----- Deleting CASToR objects ... -----" << endl);
2510  delete p_Algorithm;
2511  delete p_ImageSpace;
2512  delete p_DeformationManager;
2513  delete p_DynamicModelManager;
2514  delete p_ImageProcessingManager;
2515  delete p_ImageConvolverManager;
2516  delete p_OptimizerManager;
2517  delete p_ProjectorManager;
2518  for (int i=0 ; i<nb_beds ; i++) delete p_DataFile[i];
2519  delete[] p_DataFile;
2520  delete p_ImageDimensionsAndQuantification;
2521  if (verbose_general>=5) Cout("----- CASToR objects successfully deleted -----" << endl);
2522 
2523  // Ending
2524  if (verbose_general>=1) Cout(endl);
2525  #ifdef CASTOR_MPI
2526  MPI_Finalize();
2527  #endif
2528  return EXIT_SUCCESS;
2529 }
void SetIgnorePOIFlag(bool a_ignorePOIFlag)
Set a boolean that that if we ignore POI information or not.
Definition: vDataFile.hh:423
void SetRespBasisFunctionsFile(const string &a_respBasisFunctionsFile)
Set the file name containing the respiratory basis functions coefficients.
void ShowHelpDynamic()
This class is designed to be a mother virtual class for Datafile.
Definition: vDataFile.hh:67
This header file is mainly used to declare some macro definitions and all includes needed from the st...
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the member mp_ImageDimensionsAndQuantification to the provided value.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the Image Dimensions and Quantification Object.
static sRandomNumberGenerator * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
Declaration of class oImageDimensionsAndQuantification.
void SetPathToAttenuationImage(string a_pathToAttenuationImage)
This function is used to set the path to the attenuation image.
int InitDynamicData(string a_pathTo4DDataSplittingFile, int a_respMotionCorrectionFlag, int a_cardMotionCorrectionFlag, int a_doubleMotionCorrectionFlag, int a_invMotionCorrectionFlag, int a_nbRespGates, int a_nbCardGates)
Call the eponym function from the oDynamicDataManager object in order to initialize its data...
#define MODE_HISTOGRAM
Definition: vDataFile.hh:36
void SetNumberOfAtnGateImages(int a_nbAtnRespGateImages, int a_nbAtnCardGateImages)
int Iterate()
Just call either the IterateCPU or the IterateGPU function as asked for.
int SetNbIterationsAndSubsets(const string &a_nbIterationsSubsets)
Set the number of iterations and subsets.
void SetVerbose(int a_verbose)
set verbosity
void SetGPUflag(bool a_flagGPU)
Set the GPU flag.
void SetFOVSizeZ(FLTNB a_fovSizeZ)
Set the FOV's size along the Z axis, in mm.
#define MODE_LIST
Definition: vDataFile.hh:34
static void ShowCommonHelp()
This function is used to print out some help about the use of options common to all projectors...
Definition: vProjector.cc:127
void SetIgnoredCorrections(const string &a_ignoredCorrectionsList)
Set the string specifying the corrections that will be ignored.
#define FLTNB
Definition: gVariables.hh:55
void SetOptimizerImageStatFlag(bool a_optimizerImageStatFlag)
Set the optimizer image stat flag that specifies if some basic statistics about image update is compu...
void ShowHelpDynamicModel()
Show help about all implemented dynamic models.
void ShowHelpDeformation()
Show help about all implemented deformations.
void ShowHelp()
Display main command line options for castor-proj.
Definition: castor-recon.cc:39
void SetComputationStrategy(int a_computationStrategy)
Set the computation strategy for the system matrix elements storage.
void SetProjectorManager(oProjectorManager *ap_ProjectorManager)
Set the Projector Manager Object.
int Initialize()
A function used to initialize the manager and the projectors or system matrices it manages...
static void ShowCommonHelp()
This function does not take any parameter and is used to display some help about the syntax of the op...
void SetSaveSensitivityHistoFlag(bool a_saveSensitivityHistoFlag)
Set the flag that specifies if the sensitivity image in histogram mode has to be saved for each subse...
int Initialize()
A public function used to initialize the sensitivity generator.
void SetVerbose(int a_verboseLevel)
Set the member m_verboseLevel to the provided value.
void ShowHelpImgp()
Display command line options related to the Image Processing module for castor-recon.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the image dimensions in use.
int FindScannerSystem(string a_scannerName)
Look for a file matching with the scanner name in parameter inside the scanner repository.
void SetDeformationManager(oDeformationManager *ap_DeformationManager)
Set the Deformation Manager Object.
void SetFOVSizeY(FLTNB a_fovSizeY)
Set the FOV's size along the Y axis, in mm.
void SetNbVoxZ(INTNB a_nbVoxZ)
Set the number of voxels along the Z axis.
void SetNbTimeBasisFunctions(int a_nbTimeBasisFunctions)
Set the number of time basis functions.
void SetOptions(const string &a_options)
Set the respiratory motion options contained in the provided string.
void SetVerbose(int a_verboseLevel)
Set the verbose level.
int BuildScannerObject()
Instantiate the specific scanner object related to the modality, and set verbosity of scanner object...
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the image dimensions in use.
string GetPathToSensitivityImage()
This function return the path to the sensitivity image.
void SetNbRespGates(int a_nbRespGates)
Set the number of respiratory gates.
int CheckParameters()
A function used to check the parameters settings.
void SetPathToSensitivityImage(string a_pathToSensitivityImage)
Set path to the sensitivity image.
This class is designed to manage the optimization part of an iterative reconstruction.
void SetOffsetY(FLTNB a_offsetY)
Set the image offset along the Y axis, in mm.
void SetFOVOutMasking(FLTNB a_fovOutPercent, INTNB a_nbSliceOutMask)
Set the output FOV masking settings: transaxial unmasked FOV percent and number of extrem slices to r...
void ShowHelpImageProcessingModule()
Show help about all implemented image processing modules.
void SetVerbose(int a_verboseLevel)
set verbosity
Definition: vDataFile.hh:394
void SetDeformationManager(oDeformationManager *ap_DeformationManager)
This function is used to set the pointer to the oDeformationManager in use.
void SetMotionType(int a_motionType)
Set the nature of motion correction (Deformation type macro)
void SetOptionsForward(const string &a_optionsForward)
Set the forward projection options contained in the provided string.
void SetDataMode(int a_dataMode)
Set the mode of reconstruction.
int SetOutputIterations(const string &a_outputIterations)
Set the selected output iterations.
void SetVerbose(int a_verboseLevel)
Set Verbosity.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the member mp_ImageDimensionsAndQuantification to the provided value.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the image dimensions in use.
This is the main class for iterative reconstructions, that manages the iteration loops. This class manages an iterative reconstruction of any kind, using a vDataFile, and through the use of an oProjector, an oOptimizer, a oConvolver, a oImageSpace.
int Launch()
A public function used to launch the sensitivity generator (compute the sensitivity image) ...
int Initialize()
A function used to initialize the manager and all image processing modules it manages.
string GetPathToScannerFile()
void SetVerbose(int a_verboseLevel)
Set verbosity level.
void ShowHelpPenalty()
Show help about all implemented penalties.
int Initialize()
Set the dynamic model flag and instanciate/initialize model objects through the ParseOptionsAndInitia...
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
void SetOffsetZ(FLTNB a_offsetZ)
Set the image offset along the Z axis, in mm.
#define SCANNER_PET
void SetVerbose(int a_verboseLevel)
void SetImageConvolverManager(oImageConvolverManager *ap_ImageConvolverManager)
This function is used to set the pointer to the oImageConvolverManager in use.
void SetSaveLUTFlag(bool a_flag)
Set to on the flag indicating a LUT generated by a geom file should be written on disk or not...
Declaration of class iDataFilePET.
void SetOptions(vector< string > a_options)
Set the member m_options to the provided value.
Declaration of class oIterativeAlgorithm.
void SetOptionsCommon(const string &a_optionsCommon)
Set the common projection options contained in the provided string.
int Initialize()
A function used to initialize the manager and the optimizer it manages.
int CheckParameters()
Check if all parameters have been correctly initialized, and call the CheckParameters function of the...
void SetNbVoxX(INTNB a_nbVoxX)
Set the number of voxels along the X axis.
int SetNbThreads(const string &a_nbThreads)
Set the number of threads.
uint16_t nb_resp_gates
Declaration of class iDataFileSPECT.
void Exit(int code)
void SetOptionsBackward(const string &a_optionsBackward)
Set the backward projection options contained in the provided string.
uint16_t nb_card_gates
Declaration of class iScannerPET.
int IntfReadHeader(const string &a_pathToHeaderFile, Intf_fields *ap_IntfFields, int vb)
Read an Interfile header.
int InstantiateScanner()
Instantiate scanner using the related function in the scanner classes.
int LogCommandLine(int argc, char **argv)
Write log file header with the provided command line options and different informations.
void SetPathToNormalizationFileName(vector< string > ap_pathToNormalizationFileName, bool a_inverseDataFileOrderFlag)
This function is used to set the path to the normalization file names, and the flag saying if their o...
static sAddonManager * GetInstance()
void SetSaveSubsetImageFlag(bool a_saveImageAfterSubsets)
Set the flag that specifies if the image has to be saved for each subset.
void SetComputeFromHistogramFlag(bool a_computeFromHistogramFlag)
This function is used to set the m_computeFromHistogramFlag.
int ConvertFromString(const string &a_str, string *a_result)
Copy the 'a_str' string in the position pointed by 'a_result'.
Definition: gOptions.cc:749
#define DEF_DUAL_MOT
#define FIXED_LIST_COMPUTATION_STRATEGY
void SetNbVoxY(INTNB a_nbVoxY)
Set the number of voxels along the Y axis.
void SetNbRespBasisFunctions(int a_nbRespBasisFunctions)
Set the number of respiratory basis functions.
int CheckConfigDir(const string &a_path)
Set the path to the CASTOR config directory from the given path if not empty or through the existence...
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Set the image dimensions in use.
void SetVerbose(int a_verboseLevel)
Set the verbose level.
int CheckParameters()
A function used to check the parameters settings.
void SetNbCardGates(int a_nbCardGates)
Set the number of cardiac gates.
void SetDataMode(int a_dataMode)
Set the mode of the data (histogram, list-mode)
#define Cerr(MESSAGE)
#define SCANNER_SPECT_CONVERGENT
int BuildLUT()
Call the eponym function of the scanner class.
void SetDataType(int a_dataType)
Set the type of the data (pet, spect, etc)
int GetNbIPatMotionSubsets()
call the eponym function from the oDynamicDataManager object
int Initialize(int a_nbThreads)
Instanciate a number of RNG according to the number of threads used in openMP.
int Initialize()
A function used to initialize all that is needed.
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
void SetMPIRankAndSize(int a_mpiRank, int a_mpiSize)
Set the MPI rank of the MPI instance, and the MPI size (the number of instances)
#define DEF_RESP_MOT
void SetOptionsOptimizer(const string &a_optionsOptimizer)
Set the optimizer projection options contained in the provided string.
This class is designed to manage the use of dynamic model in the reconstruction.
void SetFrames(const string &a_frameList)
Set the frame list (a string that will be parsed by the InitializeFramingAndQuantification function) ...
void SetFOVSizeX(FLTNB a_fovSizeX)
Set the FOV's size along the X axis, in mm.
void SetNbBeds(int a_nbBeds)
Set number of beds (bed positions)
int ReadDataASCIIFile(const string &a_file, const string &a_keyword, T *ap_return, int a_nbElts, bool a_mandatoryFlag)
Look for "a_nbElts" elts in the "a_file" file matching the "a_keyword" string passed as parameter a...
Definition: gOptions.cc:111
int GetNbThreadsMax()
Get the maximum between the number of threads used for projections and image operations.
Singleton class that Instantiate and initialize the scanner object.
void SetImageProcessingManager(oImageProcessingManager *ap_ImageProcessingManager)
Set the Image Processing Manager Object.
void SetOptions(vector< string > a_options)
Set the member m_options to the provided value.
void SetOptionsPenalty(const string &a_optionsPenalty)
Set the penalty projection options contained in the provided string.
int CheckParameters()
A function used to check the parameters settings.
Declaration of class sScannerManager.
void SetPathInitImage(string a_pathToInitialImage)
Set path to an initial image.
void SetVoxSizeY(FLTNB a_voxSizeY)
Set the voxel's size along the Y axis, in mm.
Inherit from vDataFile. Class that manages the reading of a SPECT input file (header + data)...
This class is designed to manage the different image convolvers and to apply them.
void SetOffsetX(FLTNB a_offsetX)
Set the image offset along the X axis, in mm.
void SetHeaderDataFileName(const string &a_headerFileName)
set the data header file name
Definition: vDataFile.hh:431
vScanner * GetScannerObject()
void SetVoxSizeX(FLTNB a_voxSizeX)
Set the voxel's size along the X axis, in mm.
void IntfKeyInitFields(Intf_fields *ap_IF)
Init the file of an Interfile fields structure passed in parameter to their default values...
int CheckParameters()
A function used to check the parameters settings.
void SetMergeDynImagesFlag(bool a_flag)
Set to on the flag indicating that a dynamic serie of 3D images should be written on disk in one file...
void SetPathToAttenuationImage(string a_pathToAttenuationImage)
This function is used to set the path to the attenuation image.
void SetMPIRank(int a_mpiRank)
Initialize the machine index for MPI.
void SetVerbose(int a_verboseLevel)
Set the verbose level.
void SetTimeBasisFunctionsFile(const string &a_timeBasisFunctionsFile)
Set the file name containing the time basis functions coefficients.
void SetDataFile(vDataFile **a2p_DataFile)
This function is used to set the pointer to the vDataFile array in use.
void SetDataFile(vDataFile *ap_DataFile)
Set a data file in use to later recover some information from it.
#define DEF_CARD_MOT
void ShowHelpMiscellaneous()
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
set the pointer to the oImageDimensionsAndQuantification object
Definition: oImageSpace.hh:553
int main(int argc, char **argv)
void ShowHelpProjector()
Show help about all implemented projectors.
#define KEYWORD_MANDATORY
Definition: gOptions.hh:25
int CheckParameters()
A function used to check the parameters settings.
static void ShowCommonHelp()
This function does not take any parameter and is used to display some help about the syntax of the op...
void SetImageSpace(oImageSpace *ap_ImageSpace)
This function is used to set the pointer to the oImageSpace in use.
void ShowHelpComputation()
int CheckParameters()
This function is used to check parameters after the latter have been all set using Set functions...
Singleton class that generate a thread-safe random generator number for openMP As singleton...
int CheckParameters()
This function is used to check parameters after the latter have been all set using Set functions...
int Initialize()
Initialization : .
Declaration of class sRandomNumberGenerator.
void SetNbTOFBins(int a_nbTOFBins)
Set the number of TOF bins in use.
void SetScanner(vScanner *ap_Scanner)
This function is used to set the pointer to the vScanner in use.
void SetVerbose(int a_verbose)
Set the member m_verboseLevel to the provided value.
#define INTNB
Definition: gVariables.hh:64
void SetVerbose(int a_verboseLevel)
Set the verbose level.
This class is designed to manage the image-based deformation part of the reconstruction.
void SetVoxSizeZ(FLTNB a_voxSizeZ)
Set the voxel's size along the Z axis, in mm.
int CheckDynamicParameters(int64_t a_nbEvents)
Call the eponym function from the oDynamicDataManager object in order to check its parameters...
void SetVerbose(int a_verboseLevel)
set verbosity
Definition: oImageSpace.hh:546
Declaration of class oSensitivityGenerator.
This class is designed to manage the different image processing modules and to apply them...
This class is designed to manage the projection part of the reconstruction.
int GetNbTOFBins()
Get the number of TOF bins associated to the projector.
Interfile fields. This structure contains all the Interfile keys currently managed by CASToR Decl...
void ShowHelpOutput()
void SetBedIndex(int a_bedIndex)
set the bed index corresponding to this data file
Definition: vDataFile.hh:373
#define DEF_IPAT_MOT
int Initialize()
Set the flags for the different motion types and instanciate/initialize deformation objects through t...
Declaration of class sOutputManager.
This class holds all the matrices in the image domain that can be used in the algorithm: image...
Definition: oImageSpace.hh:41
void SetImageSpace(oImageSpace *ap_ImageSpace)
Set the Image Space Object.
void SetImageConvolverManager(oImageConvolverManager *ap_ImageConvolverManager)
Set the Image Convolver Manager Object.
int GetDataMode()
Definition: vDataFile.hh:280
int InitOutputDirectory(const string &a_pathFout, const string &a_pathDout)
Create the output directory if any, extract the base name and create the log file.
int CheckParameters()
A public function used to check the parameters settings.
void ShowHelpProj()
This class is designed to manage all dimensions and quantification related stuff. ...
void SetNbBeds(int a_nbBeds)
Set the number of bed positions.
void SetNbCardBasisFunctions(int a_nbCardBasisFunctions)
Set the number of cardiac basis functions.
This file is used for all kind of different functions designed for options parsing and ASCII file rea...
void SetProjectorManager(oProjectorManager *ap_ProjectorManager)
This function is used to set the pointer to the oProjectorManager in use.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
This function is used to set the pointer to the oImageDimensionsAndQuantification in use...
void ShowHelpDimensions()
Display command line options related to image dimensions for castor-recon.
void SetGPUflag(bool a_flagGPU)
This function is used to set the GPU flag; do we use GPU or not.
int GetGeometricInfoFromDatafile(string a_pathToDataFilename)
Call the specialized function of the scanner object in order to get geometric informations from the d...
void SetVerbose(int a_verboseLevel)
Set the member m_verboseLevel to the provided value.
void SetVerbose(int a_verboseLevel)
set verbosity
#define Cout(MESSAGE)
int CheckSPECTAttenuationCompatibility(const string &a_pathToAttenuationImage)
A function used to check specific compatibility with SPECT and attenuation correction.
#define CASTOR_VERSION
Definition: gVariables.hh:44
void SetCardBasisFunctionsFile(const string &a_cardBasisFunctionsFile)
Set the file name containing the cardiac basis functions coefficients.
void SetScanner(vScanner *ap_Scanner)
Set the scanner in use.
void ShowHelpAlgo()
Display command line options related to the Optimization algorithm module for castor-recon.
void ShowHelpOptimizer()
Show help about all implemented optimizers.
void SetOptimizerManager(oOptimizerManager *ap_OptimizerManager)
Set the Optimizer Manager Object.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
set the pointer to the oImageDimensionsAndQuantification object
Definition: vDataFile.hh:408
Inherit from vDataFile. Class that manages the reading of a PET input file (header + data)...
Definition: iDataFilePET.hh:26
void SetNbTransformations(int a_nbTransformations)
Set the total number of transformations/deformations.
void SetPercentageLoad(int a_percentageLoad)
Set the percentage of the data file that will be loaded in memory.
Definition: vDataFile.hh:380
int ReadStringOption(const string &a_input, T *ap_return, int a_nbElts, const string &sep, const string &a_option)
Parse the 'a_input' string corresponding to the 'a_option' into 'a_nbElts' elements, using the 'sep' separator. The results are returned in the templated 'ap_return' dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
Definition: gOptions.cc:50
void SetDataFile(vDataFile **a2p_DataFile)
Set the list of DataFile.
void SetOptions(const string &a_options)
Set the motion options contained in the provided string, and the related number of gates...
void SetDynamicModelManager(oDynamicModelManager *ap_DynamicModelManager)
Set the Dynamic Model Manager Object.
This class is designed to manage the computation of the sensitivity image.
void CheckNumberOfProjectionThreadsConsistencyWithDatafileSize(vDataFile **a2p_Datafile)
Declaration of class sAddonManager.
void GetUserEndianness()
Check user/host computer endianness and write it to the global variable User_Endianness.
void ShowHelpInput()
int SetFlipOut(const string &a_flipOut)
Set the output flip options, the parameter being a string potentially containing the letters x...
int Initialize()
A function used to initialize the manager and all image convolvers it manages.
int SetDynamicSpecificQuantificationFactors(const string &a_quantificationFile)
Apply specific quantification factors manually provided as an option.
void ShowHelpCorrection()
Display command line options related to correction settings for castor-recon.
void ShowHelpImageConvolver()
Show help about all implemented image convolvers.
void SetOptimizerFOMFlag(bool a_optimizerFOMFlag)
Set the optimizer FOM flag that specifies if some figures-of-merit (FOM) will be computed in the data...