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