CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
castor-proj.cc
Go to the documentation of this file.
1 
9 #include "gVariables.hh"
10 #include "gOptions.hh"
11 #include "oAnalyticProjection.hh"
12 #include "oImageConvolverManager.hh"
13 #include "oImageDimensionsAndQuantification.hh"
14 #include "iDataFilePET.hh"
15 #include "iDataFileSPECT.hh"
16 #include "sOutputManager.hh"
17 #include "sScannerManager.hh"
18 #include "sRandomNumberGenerator.hh"
19 #include "iScannerPET.hh"
20 
21 
22 // =====================================================================
23 // ---------------------------------------------------------------------
24 // ---------------------------------------------------------------------
25 // =====================================================================
30 void ShowHelp(int a_returnCode, int a_mpiRank)
31 {
32  // Return when using MPI and mpi_rank is not 0
33  #ifdef CASTOR_MPI
34  int mpi_rank = 0;
35  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
36  if (mpi_rank!=0) return;
37  #endif
38 
39  // Show help
40  cout << endl;
41  cout << "Usage: castor-proj.exe -img path_to_file.hdr -sc name -(f/d)out output [settings]" << endl;
42  cout << endl;
43  cout << "[Main options]:" << endl;
44  cout << " -img path_to_img.hdr : Give the interfile header of the image to project (no default)." << endl;
45  cout << " -sc scanner_alias : Give the scanner model. It must correspond to the name of one of the file in the scanner repository (w/o file extension)" << endl;
46  cout << " -fout name : Give the root name for all output files (no default, alternative to -dout)" << endl;
47  cout << " -dout name : Give the name of the output directory where all output files will be written (no default, alternative to -fout)" << endl;
48  cout << " -fileType type : Give the type of events that will be generated : ('TYPE_PET' ou '0' = PET, 'TYPE_SPECT' ou '1' = SPECT) (default : TYPE_PET)" << endl;
49  cout << " -vb : Give the verbosity level, from 0 (no verbose) to above 5 (at the event level) (default: 1)." << endl;
50  cout << endl;
51  cout << "[Specific options]:" << endl;
52  cout << " -help-in : Print out specific help about input settings." << endl; // managed by main
53  cout << " -help-out : Print out specific help about output settings." << endl; // managed by main
54  cout << " -help-proj : Print out specific help about projector settings." << endl; // managed by main
55  cout << " -help-comp : Print out specific help about computing settings." << endl; // managed by main
56  cout << " -help-misc : Print out specific help about miscellaneous and verbose settings." << endl; // managed by main
57  cout << " -help-dynamic : Print out specific help about dynamic options." << endl; // managed by main
58  cout << " -help-pet : Print out specific help about PET settings for analytic projection." << endl; // managed by main
59  cout << " -help-spect : Print out specific help about SPECT settings for analytic projection." << endl; // managed by main
60  cout << endl;
61  cout << "[Implemented Modules]:" << endl;
62  cout << " -help-scan : Show the list of all scanners from the configuration directory." << endl; // managed by sScannerManager
63  cout << " -help-projm : Show the list and description of all implemented projectors." << endl; // managed by oProjectorManager
64  cout << endl;
65  cout << " --help,-h,-help : Print out this help page." << endl; // managed by main
66  cout << endl;
67  #ifdef CASTOR_MPI
68  cout << " Compiled with MPI" << endl;
69  #endif
70  #ifdef CASTOR_OMP
71  cout << " Compiled with OpenMP" << endl;
72  #endif
73  #ifdef CASTOR_GPU
74  cout << " Compiled for GPU" << endl;
75  #endif
76  #if defined(CASTOR_OMP) || defined(CASTOR_MPI) || defined(CASTOR_GPU)
77  cout << endl;
78  #endif
79  #ifdef BUILD_DATE
80  cout << " Build date: " << BUILD_DATE << endl;
81  cout << endl;
82  #endif
83  #ifdef CASTOR_VERSION
84  cout << " This program is part of the CASToR release version " << CASTOR_VERSION << "." << endl;
85  cout << endl;
86  #endif
87  Exit(a_returnCode);
88 }
89 
90 
91 
92 
93 // =====================================================================
94 // ---------------------------------------------------------------------
95 // ---------------------------------------------------------------------
96 // =====================================================================
102 {
103  // Return when using MPI and mpi_rank is not 0
104  #ifdef CASTOR_MPI
105  int mpi_rank = 0;
106  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
107  if (mpi_rank!=0) return;
108  #endif
109  // Show help
110  cout << endl;
111  cout << "[Input settings]:" << endl;
112  cout << endl;
113  cout << " -off x,y,z : Give the offset of the field-of-view in each dimension, in mm (default: 0.,0.,0.)." << endl;
114  cout << endl;
115  cout << " -atn path_to_img.hdr : Give the interfile header of an input attenuation image (unit has to be cm-1) (default: uniform value)." << endl;
116  cout << endl;
117  cout << " -help-in : Print out this help." << endl;
118  cout << endl;
119 }
120 
121 
122 
123 // =====================================================================
124 // ---------------------------------------------------------------------
125 // ---------------------------------------------------------------------
126 // =====================================================================
132 {
133  // Return when using MPI and mpi_rank is not 0
134  #ifdef CASTOR_MPI
135  int mpi_rank = 0;
136  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
137  if (mpi_rank!=0) return;
138  #endif
139  // Show help
140  cout << endl;
141  cout << "[Output settings]:" << endl;
142  cout << endl;
143  cout << " -fout name : Give the root name for all output files. All output files will be written as 'name_suffix.ext'." << endl;
144  cout << " So the provided name should not end with '.' or '/' character. (no default, alternative to -dout)" << endl;
145  cout << " -dout name : Give the name of the output directory where all output files will be written. All files will also" << endl;
146  cout << " be prefixed by the name of the directory. The provided name should not end with '.' or '/' character." << endl;
147  cout << " (no default, alternative to -fout)" << endl;
148  cout << endl;
149  cout << " -olut : If a scanner LUT (geometry information) is computed from a .geom file, it will be written on disk in the scanner repository" << endl;
150  cout << endl;
151  cout << " -onbp prec : By default, numbers are displayed using scientific format. This option allows to customize the format and precision" << endl;
152  cout << " : The format is format,precision. f is the format (s=scientific, f=fixed), p is the precision" << endl;
153  cout << " eg: -onbp f,5 --> fixed with 5 digits precision, -onbp --> scientifici with max precision." << endl;
154  cout << endl;
155  cout << " -help-out : Print out this help." << endl;
156  cout << endl;
157 }
158 
159 
160 
161 // =====================================================================
162 // ---------------------------------------------------------------------
163 // ---------------------------------------------------------------------
164 // =====================================================================
170 {
171  // Return when using MPI and mpi_rank is not 0
172  #ifdef CASTOR_MPI
173  int mpi_rank = 0;
174  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
175  if (mpi_rank!=0) return;
176  #endif
177  // Show help
178  cout << "[Projector settings]:" << endl;
179  cout << endl;
180  cout << " -proj param : Give the projector to be used for both forward and backward projections, along with a configuration file (proj:file.conf)" << endl;
181  cout << " or the list of parameters associated to the projector (proj,param1,param2,...). If the projector only is specified, the" << endl;
182  cout << " default configuration file is used. By default, the Siddon projector is used." << endl;
183  cout << endl;
184  cout << " -proj-comp : Give the strategy for projection line computation. Here are the three different strategies that can be used:" << endl;
185  cout << " 1 : Image-based system matrix elements storage: The voxels weights are added in a matrix representing the whole image, so" << endl;
186  cout << " the addition of a new line to the previous ones is straightforward only by adding the weights to the corresponding voxels." << endl;
187  cout << " As it is insanely long, it can possibly be used for example with extremely complex projectors that makes use of huge number" << endl;
188  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;
189  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;
190  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;
191  cout << " has a fixed size which is provided by the EstimateMaxNumberOfVoxelsPerLine() function from the vProjector class. There are no" << endl;
192  cout << " ckecks at all for possible buffer overflows. This is the fastest strategy and default one." << endl;
193  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;
194  cout << " upgraded if the current number of contributing voxels exceed the list's size. The first allocated size corresponds to the diagonal" << endl;
195  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;
196  cout << " is a bit slower than the fixed-list strategy during the first iteration, but is optimal with respect to RAM usage." << endl;
197  cout << endl;
198  cout << " -help-projm : Print out specific help about projector settings." << endl; // managed by oProjectorManager
199  cout << endl;
200  cout << " -help-proj : Print out this help." << endl; // managed by oProjectorManager
201  cout << endl;
202 }
203 
204 
205 
206 // =====================================================================
207 // ---------------------------------------------------------------------
208 // ---------------------------------------------------------------------
209 // =====================================================================
215 {
216  // Return when using MPI and mpi_rank is not 0
217  #ifdef CASTOR_MPI
218  int mpi_rank = 0;
219  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
220  if (mpi_rank!=0) return;
221  #endif
222  // Show help
223  cout << endl;
224  cout << "[Computation settings]:" << endl;
225  cout << endl;
226  #ifdef CASTOR_OMP
227  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;
228  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;
229  cout << endl;
230  #endif
231  #ifdef CASTOR_GPU
232  cout << " -gpu : Flag to say that we want to use the GPU device (default: use the CPU only)." << endl;
233  cout << endl;
234  #endif
235  cout << " -conv param : Give an image convolver model to be used within the algorithm, along with a configuration file (conv:file.conf) or the" << endl;
236  cout << " list of parameters associated to the convolver (conv,param1,param2,...). If the convolver only is specified, its default" << endl;
237  cout << " configuration file is used. By default, no convolver is applied" << endl;
238  cout << endl;
239  cout << " -help-conv : Show the list and description of all implemented image convolvers." << endl; // managed by oImageConvolverManager
240  cout << endl;
241  cout << " -noise poisson : Give the noise model to be used. Only Poisson noise is implemented for the moment (default : no noise model)" << endl;
242  cout << endl;
243  cout << " -rng : Give a seed for the random number generator (should be >=0)" << endl;
244  cout << endl;
245  cout << " -no0 : Discard zero events (not saved)." << endl;
246  cout << endl;
247  cout << " -help-comp : Print out this help." << endl;
248  cout << endl;
249  #ifdef CASTOR_MPI
250  cout << " Compiled with MPI" << endl;
251  #endif
252  #ifdef CASTOR_OMP
253  cout << " Compiled with OpenMP" << endl;
254  #endif
255  #ifdef CASTOR_GPU
256  cout << " Compiled for GPU" << endl;
257  #endif
258  #if defined(CASTOR_OMP) || defined(CASTOR_MPI) || defined(CASTOR_GPU)
259  cout << endl;
260  #endif
261 }
262 
263 
264 
265 // =====================================================================
266 // ---------------------------------------------------------------------
267 // ---------------------------------------------------------------------
268 // =====================================================================
274 {
275  // Return when using MPI and mpi_rank is not 0
276  #ifdef CASTOR_MPI
277  int mpi_rank = 0;
278  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
279  if (mpi_rank!=0) return;
280  #endif
281  // Show help
282  cout << endl;
283  cout << "[Dynamic settings]:" << endl;
284  cout << endl;
285  cout << " -frm list : Give the framing for the reconstruction where 'list' is a list of all frames durations in seconds separated" << endl;
286  cout << " by commas. To specify a dead frame, add 'df' concatenated to the frame duration. Milliseconds maximum precision." << endl;
287  cout << " (default: read from the 'image duration (sec)' key in the interfile image header" << endl;
288  cout << endl;
289  cout << " (about gated images) : An image contening several respiratory/cardiac 'gates' can be provided to generate one datafile containing histograms of these gated images." << endl;
290  cout << " The number of gates being directly read from the 'number of respiratory gates' and 'number of cardiac gates' keys in the interfile header" << endl;
291  cout << endl;
292  cout << " -help-dynamic : Print out this help." << endl;
293  cout << endl;
294 }
295 
296 
297 
298 // =====================================================================
299 // ---------------------------------------------------------------------
300 // ---------------------------------------------------------------------
301 // =====================================================================
307 {
308  // Return when using MPI and mpi_rank is not 0
309  #ifdef CASTOR_MPI
310  int mpi_rank = 0;
311  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
312  if (mpi_rank!=0) return;
313  #endif
314  // Show help
315  cout << "[SPECT settings]:" << endl;
316  cout << endl;
317  cout << " -SPECT_bins par : Give two integer parameters corresponding to the transaxial number of bins, separated by a comma (nbBinsX, nbBinsY). " << endl;
318  cout << " Default = transaxial number of pixels in the SPECT scanner file " << endl;
319  cout << endl;
320  cout << " -SPECT_ang par : Give the total number of projections, followed by the first angle and the angle step in float" << endl;
321  cout << " Format : nb_projs:first_angle,step_angle" << endl;
322  cout << endl;
323  cout << " -SPECT_c_ang par : SPECT custom angles : give the total number of projections, followed by the projections angles in float" << endl;
324  cout << " Format : nb_projs:angle1,angle2,... " << endl;
325  cout << endl;
326  cout << " -SPECT_radius par : Give a distance between center of rotation to detectors which will be used for all heads" << endl;
327  cout << endl;
328  cout << " -SPECT_rot par : Give the heads rotation direction. Accept two parameters: CW (clockwise, default), CCW (counter-clockwise)" << endl;
329  cout << endl;
330  cout << " -help-spect : Print out this specific help." << endl; // managed by oProjectorManager
331  cout << endl;
332 }
333 
334 
335 
336 // =====================================================================
337 // ---------------------------------------------------------------------
338 // ---------------------------------------------------------------------
339 // =====================================================================
345 {
346  // Return when using MPI and mpi_rank is not 0
347  #ifdef CASTOR_MPI
348  int mpi_rank = 0;
349  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
350  if (mpi_rank!=0) return;
351  #endif
352  // Show help
353  cout << "[PET settings]:" << endl;
354  cout << endl;
355  cout << " -PET_maxAxialDiffmm param : Set the maximum axial difference in mm between two crystals in a LOR (default = no restriction)" << endl;
356  cout << endl;
357 }
358 
359 
360 
361 // =====================================================================
362 // ---------------------------------------------------------------------
363 // ---------------------------------------------------------------------
364 // =====================================================================
370 {
371  // Return when using MPI and mpi_rank is not 0
372  #ifdef CASTOR_MPI
373  int mpi_rank = 0;
374  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
375  if (mpi_rank!=0) return;
376  #endif
377  // Show help
378  cout << endl;
379  cout << "[Miscellaneous settings]:" << endl;
380  cout << endl;
381  cout << " -vb : Give the general verbosity level, from 0 (no verbose) to 5 and above (at the event level) (default: 1)." << endl;
382  cout << " -vb-algo : Give the verbose level specific to the analytic projection algorithm (default: same as general verbose level)." << endl;
383  cout << " -vb-proj : Give the verbose level specific to the projector (default: same as general verbose level)." << endl;
384  cout << " -vb-conv : Give the verbose level specific to the image convolver (default: same as general verbose level)." << endl;
385  cout << " -vb-scan : Give the verbose level specific to the scanner (default: same as general verbose level)." << endl;
386  cout << " -vb-data : Give the verbose level specific to the data and image management (default: same as general verbose level)." << endl;
387  cout << endl;
388  cout << " -conf : Give the path to the CASToR config directory (default: located through the CASTOR_CONFIG environment variable)." << endl;
389  cout << endl;
390  cout << " -help-misc : Print out this help." << endl;
391  cout << endl;
392 }
393 
394 
395 
396 
397 
398 // =====================================================================
399 // ---------------------------------------------------------------------
400 // ---------------------------------------------------------------------
401 // =====================================================================
402 /*
403  Main program
404 */
405 int main(int argc, char** argv)
406 {
407  // ============================================================================================================
408  // MPI management
409  // ============================================================================================================
410  int mpi_rank = 0;
411  //int mpi_size = 1;
412  #ifdef CASTOR_MPI
413  int mpi_size = 1;
414  MPI_Init(&argc, &argv );
415  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
416  MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
417  #endif
418 
419  // No argument, then show help
420  if (argc==1) ShowHelp(0,mpi_rank);
421  if (mpi_rank==0) cout << endl; // TODO : Most stuff is handled with processor 1 at first
422 
423  // ============================================================================================================
424  // Parameterized variables with their default values
425  // ============================================================================================================
426 
427  // Initialization of the voxel and field-of-view values in each spatial dimensions.
428  // Read from the interfile header of the image
429  int nb_VoxX=-1, nb_VoxY=-1, nb_VoxZ=-1;
430  FLTNB fov_SizeX=-1, fov_SizeY=-1, fov_SizeZ=-1;
431  FLTNB vox_SizeX=-1, vox_SizeY=-1, vox_SizeZ=-1;
432  // Initialization offset values of the field-of-view in each spatial dimensions
433  FLTNB offsetX = 0, offsetY = 0, offsetZ = 0;
434 
435  // Path to an image used as initialization. no default
436  string path_to_initial_img = "";
437  // Path to an image used for the attenuation. default : uniform image
438  string path_to_attenuation_img = "";
439  // Scanner name provided by the user
440  string scanner_name = "";
441 
442  // DataFile mode
443  int datafile_mode = MODE_HISTOGRAM;
444  int datafile_type = TYPE_PET;
445 
446  // Frame list descriptor
447  string frame_list = "";
448  FLTNB acquisition_duration_sec = 0.;
449 
450  // Number of resp gates
451  int nb_resp_gates = 1;
452  // Number of card gates
453  int nb_card_gates = 1;
454 
455  // Number of beds position in the data. default : 1
456  int nb_beds = 1;
457 
458  // Maximum axial difference between the crystals in a LOR (negative value means no restriction)
459  FLTNB max_axial_diff_mm = -1.;
460 
461  // Output directory name.
462  string path_dout = "";
463  // Or root name
464  string path_fout = "";
465 
466  // Write scanner LUT generated by a geom file on disk
467  bool save_LUT_flag = false;
468 
469  // String gathering the name of the used noise model (default : none)
470  string noise_model = "";
471 
472  // String gathering the name of the used projector for forward/backward projection (default : Siddon)
473  string options_projector = "incrementalSiddon";
474 
475  // Default projector computation strategy
476  int projector_computation_strategy = FIXED_LIST_COMPUTATION_STRATEGY;
477 
478  // String vector gathering the name of the image convolvers with specific options (default: no image convolver)
479  vector<string> options_image_convolver;
480 
481  // Using GPU (flag) ->NOTE : default : only CPU
482  bool discard_nil_events_flag = false;
483 
484  // Using GPU (flag) ->NOTE : default : only CPU
485  bool gpu_flag = false;
486  // Size of the buffer used to read the data file (0 by default for projection as it is not used, but should be initialized to use the DataFile objects)
487  int data_file_percentage_load = 0;
488 
489  // Precision for output number display
490  string onb_prec = "s,0";
491 
492  // Verbose level
493  int verbose_general = 1,
494  verbose_algo = -1,
495  verbose_proj = -1,
496  verbose_conv = -1,
497  verbose_scan = -1,
498  verbose_data = -1;
499 
500  // Path to config directory
501  string path_to_config_dir = "";
502 
503  // Initial seed for random number generator
504  int64_t seed_RNG = -1;
505  // Number of threads
506  string nb_threads = "1";
507 
508  // SPECT specific parameters
509 
510  // SPECT number of transaxial bins
511  uint16_t SPECT_nb_bins[2] = {0, 0};
512  // SPECT Number of projection angles
513  uint32_t SPECT_nb_projection_angles = 0;
514  // SPECT projections angles
515  FLTNB* SPECT_projection_angles = NULL;
516  // SPECT first angle and step angle for automatic initialization
517  FLTNB SPECT_first_angle= -1., SPECT_step_angle=-1.;
518  // SPECT distance from center of rotation to detectors
519  FLTNB SPECT_radius = -1.;
520  // SPECT head rotation orientation
521  string SPECT_rot = "CW";
522 
523  // ============================================================================================================
524  // Read command-line parameters
525  // ============================================================================================================
526 
527  for (int i=1; i<argc; i++)
528  {
529  string option = (string)argv[i];
530 
531  if (option=="-h" || option=="--help" || option=="-help") ShowHelp(0,mpi_rank);
532 
533  // Specific help for integrated scanners (managed by scanner manager)
534  else if (option=="-help-scan")
535  {
536  if(sScannerManager::GetInstance()->ShowScannersDescription())
537  Cerr("***** castor-proj() -> An error occurred when trying to output the available scanners from the scanner repository !'" << endl;);
538  Exit(EXIT_SUCCESS);
539  }
540 
541 
542  // Specific help for projector settings (managed by projector children)
543  else if (option=="-help-projm")
544  {
545  // Call specific showHelp function from vProjector children
547  // Call the static showHelp function from vProjector
549  Exit(EXIT_SUCCESS);
550  }
551 
552  // Specific help for image convolver settings (managed by image convolver children)
553  else if (option=="-help-conv")
554  {
555  // Call specific showHelp function from vImageConvolver children
557  // Call the static showHelp function from oImageConvolverManager
558  // Call the static showHelp function from oImageConvolverManager
560  Exit(EXIT_SUCCESS);
561  }
562 
563  // Specific help for input settings (managed by main)
564  else if (option=="-help-in")
565  {
566  ShowHelpInput();
567  Exit(EXIT_SUCCESS);
568  }
569  // Specific help for output settings (managed by main)
570  else if (option=="-help-out")
571  {
572  ShowHelpOutput();
573  Exit(EXIT_SUCCESS);
574  }
575  // Specific help for projector settings (managed by main)
576  else if (option=="-help-proj")
577  {
578  ShowHelpProj();
579  Exit(EXIT_SUCCESS);
580  }
581  // Specific help for computation settings (managed by main)
582  else if (option=="-help-comp")
583  {
585  Exit(EXIT_SUCCESS);
586  }
587  // Specific help for dynamic settings (managed by main)
588  else if (option=="-help-dynamic")
589  {
590  ShowHelpDynamic();
591  Exit(EXIT_SUCCESS);
592  }
593  // Specific help for PET projection settings (managed by main)
594  else if (option=="-help-pet")
595  {
596  ShowHelpPET();
597  Exit(EXIT_SUCCESS);
598  }
599  // Specific help for SPECT projection settings (managed by main)
600  else if (option=="-help-spect")
601  {
602  ShowHelpSPECT();
603  Exit(EXIT_SUCCESS);
604  }
605  // Specific help for miscellaneous settings (managed by main)
606  else if (option=="-help-misc")
607  {
609  Exit(EXIT_SUCCESS);
610  }
611 
612  else if (option=="-off")
613  {
614  if (i>=argc-1)
615  {
616  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
617  Exit(EXIT_FAILURE);
618  }
619  else
620  {
621  FLTNB input[3];
622  if (ReadStringOption(argv[i+1], input, 3, ",", option))
623  {
624  Cerr("***** castor-proj() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
625  Exit(EXIT_FAILURE);
626  }
627  offsetX = input[0];
628  offsetY = input[1];
629  offsetZ = input[2];
630  }
631  i++;
632  }
633 
634  else if (option=="-frm")
635  {
636  if (i>=argc-1)
637  {
638  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
639  Exit(EXIT_FAILURE);
640  }
641  frame_list = (string)argv[i+1];
642  i++;
643  }
644 
645  // Scanner name
646  else if (option=="-sc")
647  {
648  if (i>=argc-1)
649  {
650  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
651  Exit(EXIT_FAILURE);
652  }
653  scanner_name = argv[i+1];
654  i++;
655  }
656 
657  // Image for the initialisation of the algorithm : What should we do in case of multiple frames ?
658  else if (option=="-img")
659  {
660  if (i>=argc-1)
661  {
662  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
663  Exit(EXIT_FAILURE);
664  }
665  path_to_initial_img = argv[i+1];
666  i++;
667  }
668 
669 
670  else if (option=="-fileType")
671  {
672  if (i>=argc-1)
673  {
674  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
675  Exit(EXIT_FAILURE);
676  }
677 
678  string input_str = argv[i+1];
679 
680  if(!input_str.compare("TYPE_PET") )
681  datafile_type = TYPE_PET;
682  else if(!input_str.compare("TYPE_SPECT") )
683  datafile_type = TYPE_SPECT;
684  else if(!input_str.compare("TYPE_CT") )
685  datafile_type = TYPE_CT;
686  else // check for number
687  {
688  if(ConvertFromString(input_str , &datafile_type))
689  {
690  Cerr("***** castor-proj() -> Exception when trying to read provided entry '" << input_str << " for option: " << option << endl);
691  Exit(EXIT_FAILURE);
692  }
693  }
694 
695  i++;
696  }
697 
698  // Image for the attenuation
699  else if (option=="-atn")
700  {
701  if (i>=argc-1)
702  {
703  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
704  Exit(EXIT_FAILURE);
705  }
706  path_to_attenuation_img = argv[i+1];
707  i++;
708  }
709 
710  // Number of beds
711  else if (option=="-bed")
712  {
713  if (i>=argc-1)
714  {
715  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
716  Exit(EXIT_FAILURE);
717  }
718  nb_beds = atoi(argv[i+1]);
719  i++;
720  }
721 
722  // maximum axial difference between two crystals in a lor
723  else if (option=="-PET_maxAxialDiffmm")
724  {
725  if (i>=argc-1)
726  {
727  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
728  Exit(EXIT_FAILURE);
729  }
730  max_axial_diff_mm = atoi(argv[i+1]);
731  i++;
732  }
733 
734  // Name of the output directory
735  else if (option=="-dout") // This is a mandatory option
736  {
737  if (i>=argc-1)
738  {
739  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
740  Exit(EXIT_FAILURE);
741  }
742  path_dout = argv[i+1];
743  i++;
744  }
745  // Base name of the output files
746  else if (option=="-fout") // This is a mandatory option
747  {
748  if (i>=argc-1)
749  {
750  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
751  Exit(EXIT_FAILURE);
752  }
753  path_fout = argv[i+1];
754  i++;
755  }
756  // Flag to say that we want to save time basis functions too
757  else if (option=="-olut")
758  {
759  save_LUT_flag = true;
760  }
761  // Output number precision
762  else if (option=="-onbp")
763  {
764  if (i>=argc-1)
765  {
766  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
767  Exit(EXIT_FAILURE);
768  }
769  onb_prec = argv[i+1];
770  i++;
771  }
772  else if (option=="-noise")
773  {
774  if (i>=argc-1)
775  {
776  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
777  Exit(EXIT_FAILURE);
778  }
779  noise_model = argv[i+1];
780  i++;
781  }
782 
783  else if (option=="-proj")
784  {
785  if (i>=argc-1)
786  {
787  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
788  Exit(EXIT_FAILURE);
789  }
790  options_projector = (string)argv[i+1];
791  i++;
792  }
793 
794  // Projection line computation strategy
795  else if (option=="-proj-comp")
796  {
797  if (i>=argc-1)
798  {
799  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
800  Exit(EXIT_FAILURE);
801  }
802  projector_computation_strategy = atoi(argv[i+1]);
803  i++;
804  }
805 
806  // Image convolver settings
807  else if (option=="-conv")
808  {
809  if (i>=argc-1)
810  {
811  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
812  Exit(EXIT_FAILURE);
813  }
814  string convolver = (string)argv[i+1];
815  convolver.append("::forward"); // convolution only allowed before projection
816  options_image_convolver.push_back(convolver);
817  i++;
818  }
819 
820  // Image convolver settings
821  else if (option=="-no0")
822  {
823  discard_nil_events_flag = true;
824  }
825 
826  // --- Verbosities ---
827 
828  // General verbosity level
829  else if (option=="-vb")
830  {
831  if (i>=argc-1)
832  {
833  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
834  Exit(EXIT_FAILURE);
835  }
836  if (ConvertFromString(argv[i+1], &verbose_general))
837  {
838  Cerr("***** castor-proj() -> Exception when trying to read provided verbosity level '" << verbose_general << " for option: " << option << endl);
839  Exit(EXIT_FAILURE);
840  }
841  i++;
842  }
843 
844  // Algorithm verbosity level
845  else if (option=="-vb-algo")
846  {
847  if (i>=argc-1)
848  {
849  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
850  Exit(EXIT_FAILURE);
851  }
852  if (ConvertFromString(argv[i+1], &verbose_algo))
853  {
854  Cerr("***** castor-proj() -> Exception when trying to read provided verbosity level '" << verbose_algo << " for option: " << option << endl);
855  Exit(EXIT_FAILURE);
856  }
857  i++;
858  }
859 
860  // Projector verbosity level
861  else if (option=="-vb-proj")
862  {
863  if (i>=argc-1)
864  {
865  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
866  Exit(EXIT_FAILURE);
867  }
868  if (ConvertFromString(argv[i+1], &verbose_proj))
869  {
870  Cerr("***** castor-proj() -> Exception when trying to read provided verbosity level '" << verbose_proj << " for option: " << option << endl);
871  Exit(EXIT_FAILURE);
872  }
873  i++;
874  }
875 
876  // Image convolver verbosity level
877  else if (option=="-vb-conv")
878  {
879  if (i>=argc-1)
880  {
881  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
882  Exit(EXIT_FAILURE);
883  }
884  if (ConvertFromString(argv[i+1], &verbose_conv))
885  {
886  Cerr("***** castor-proj() -> Exception when trying to read provided verbosity level '" << verbose_conv << " for option: " << option << endl);
887  Exit(EXIT_FAILURE);
888  }
889  i++;
890  }
891 
892  // Scanner verbosity level
893  else if (option=="-vb-scan")
894  {
895  if (i>=argc-1)
896  {
897  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
898  Exit(EXIT_FAILURE);
899  }
900  if (ConvertFromString(argv[i+1], &verbose_scan))
901  {
902  Cerr("***** castor-proj() -> Exception when trying to read provided verbosity level '" << verbose_scan << " for option: " << option << endl);
903  Exit(EXIT_FAILURE);
904  }
905  i++;
906  }
907 
908  // Data and image verbosity level
909  else if (option=="-vb-data")
910  {
911  if (i>=argc-1)
912  {
913  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
914  Exit(EXIT_FAILURE);
915  }
916  if (ConvertFromString(argv[i+1], &verbose_data))
917  {
918  Cerr("***** castor-proj() -> Exception when trying to read provided verbosity level '" << verbose_data << " for option: " << option << endl);
919  Exit(EXIT_FAILURE);
920  }
921  i++;
922  }
923 
924 
925  // RNG seed
926  else if (option=="-rng")
927  {
928  if (i>=argc-1)
929  {
930  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
931  Exit(EXIT_FAILURE);
932  }
933  if(ConvertFromString(argv[i+1], &seed_RNG))
934  {
935  Cerr("***** castor-proj() -> Exception when trying to read provided number '" << seed_RNG << " for option: " << option << endl);
936  Exit(EXIT_FAILURE);
937  }
938  i++;
939  }
940 
941  // Path to config directory
942  else if (option=="-conf")
943  {
944  if (i>=argc-1)
945  {
946  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
947  Exit(EXIT_FAILURE);
948  }
949  path_to_config_dir = (string)argv[i+1];
950  i++;
951  }
952 
953  #ifdef CASTOR_GPU
954  else if (option=="-gpu")
955  {
956  gpu_flag = 1;
957  }
958  #endif
959  #ifdef CASTOR_OMP
960  else if (option=="-th")
961  {
962  if (i>=argc-1)
963  {
964  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
965  Exit(EXIT_FAILURE);
966  }
967  nb_threads = (string)argv[i+1];
968  i++;
969  }
970  #endif
971 
972  else if (option=="-load")
973  {
974  if (i>=argc-1)
975  {
976  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
977  Exit(EXIT_FAILURE);
978  }
979  data_file_percentage_load = atoi(argv[i+1]);
980  if (data_file_percentage_load>100 || data_file_percentage_load<0)
981  {
982  Cerr("***** castor-proj() -> Incorrect initialization of the size data buffer" << endl);
983  Cerr(" Number provided: " << argv[i+1] << " is not in the expected [0;100] interval" << endl);
984  Exit(EXIT_FAILURE);
985  }
986  i++;
987  }
988  else if (option=="-SPECT_bins")
989  {
990  if (i>=argc-1)
991  {
992  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
993  Exit(EXIT_FAILURE);
994  }
995 
996  if(ReadStringOption(argv[i+1], SPECT_nb_bins, 2, ",", option))
997  {
998  Cerr("***** castor-proj() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
999  Cerr("***** castor-proj() -> Expected two uint16 parameters separated by a comma" << endl);
1000  Exit(EXIT_FAILURE);
1001  }
1002 
1003  i++;
1004  }
1005 
1006  // Custom initialization of SPECT projection angles using a number of projections, and an equivalent number of pre-set projection angles
1007  else if (option=="-SPECT_c_ang")
1008  {
1009  if (i>=argc-1)
1010  {
1011  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
1012  Exit(EXIT_FAILURE);
1013  }
1014 
1015  // parsing
1016  string input_str = argv[i+1];
1017  size_t colon = input_str.find_first_of(":");
1018 
1019  if (colon==string::npos)
1020  {
1021  Cerr("***** castor-proj() -> Parsing error : colon missing in option: " << option << endl);
1022  Exit(EXIT_FAILURE);
1023  }
1024  else
1025  {
1026  if(ConvertFromString(input_str.substr(0,colon), &SPECT_nb_projection_angles))
1027  {
1028  Cerr("***** castor-proj() -> An error occurred while trying to read the number of SPECT projection values " << input_str.substr(0,colon) << " for option " << option << " !" << endl);
1029  Exit(EXIT_FAILURE);
1030  }
1031 
1032  SPECT_projection_angles = new FLTNB[SPECT_nb_projection_angles];
1033 
1034  if(ReadStringOption(input_str.substr(colon+1), SPECT_projection_angles, SPECT_nb_projection_angles, ",", option))
1035  {
1036  Cerr("***** castor-proj() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
1037  Exit(EXIT_FAILURE);
1038  }
1039  }
1040  i++;
1041  }
1042 
1043  // Generic initialization of SPECT projection angles using a first angle, an angle step, and a number of projection
1044  else if (option=="-SPECT_ang")
1045  {
1046  if (i>=argc-1)
1047  {
1048  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
1049  Exit(EXIT_FAILURE);
1050  }
1051 
1052  // parsing
1053  string input_str = argv[i+1];
1054  size_t colon = input_str.find_first_of(":");
1055 
1056  if (colon==string::npos)
1057  {
1058  Cerr("***** castor-proj() -> Parsing error : colon missing in option: " << option << endl);
1059  Exit(EXIT_FAILURE);
1060  }
1061  else
1062  {
1063  if(ConvertFromString(input_str.substr(0,colon), &SPECT_nb_projection_angles))
1064  {
1065  Cerr("***** castor-proj() -> An error occurred while trying to read the number of SPECT projection values " << input_str.substr(0,colon) << " for option " << option << " !" << endl);
1066  Exit(EXIT_FAILURE);
1067  }
1068 
1069  FLTNB input[2];
1070  if(ReadStringOption(input_str.substr(colon+1), input, 2, ",", option))
1071  {
1072  Cerr("***** castor-proj() -> Invalid argument " << argv[i+1] << " for option " << option << " !" << endl);
1073  Exit(EXIT_FAILURE);
1074  }
1075  else
1076  {
1077  SPECT_first_angle = input[0];
1078  SPECT_step_angle = input[1];
1079  }
1080  }
1081  i++;
1082  }
1083 
1084  else if (option=="-SPECT_radius")
1085  {
1086  if (i>=argc-1)
1087  {
1088  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
1089  Exit(EXIT_FAILURE);
1090  }
1091 
1092  else
1093  {
1094  if(ConvertFromString(argv[i+1], &SPECT_radius) )
1095  {
1096  Cerr("***** castor-proj() -> An error occurred while trying to read the SPECT global radius " << argv[i+1] << " for option " << option << " !" << endl);
1097  Exit(EXIT_FAILURE);
1098  }
1099  }
1100  i++;
1101  }
1102 
1103  else if (option=="-SPECT_rot")
1104  {
1105  if (i>=argc-1)
1106  {
1107  Cerr("***** castor-proj() -> Argument missing for option: " << option << endl);
1108  Exit(EXIT_FAILURE);
1109  }
1110 
1111  else
1112  {
1113  SPECT_rot = argv[i+1];
1114 
1115  if(SPECT_rot != "CW" && SPECT_rot != "CCW")
1116  {
1117  Cerr("***** castor-proj() -> '" << SPECT_rot <<"' is unknown argument for option " << option << ".");
1118  Cerr(" SPECT rotation direction must be either 'CW' (clockwise) or 'CCW' (counter-clockwise) !" << endl);
1119  Exit(EXIT_FAILURE);
1120  }
1121  }
1122  i++;
1123  }
1124 
1125  else
1126  {
1127  if (mpi_rank==0) Cerr("***** castor-proj() -> Unknown option '" << option << "' !" << endl);
1128  Exit(EXIT_FAILURE);
1129  }
1130 
1131  }
1132 
1133  #ifdef CASTOR_MPI
1134  MPI_Barrier(MPI_COMM_WORLD);
1135  #endif
1136 
1137 
1138  // Affect specific verbose levels if not set
1139  if (verbose_algo==-1) verbose_algo = verbose_general;
1140  if (verbose_proj==-1) verbose_proj = verbose_general;
1141  if (verbose_conv==-1) verbose_conv = verbose_general;
1142  if (verbose_scan==-1) verbose_scan = verbose_general;
1143  if (verbose_data==-1) verbose_data = verbose_general;
1144 
1145 
1146 
1147  // ============================================================================================================
1148  // Mandatory checks: the idea is that the most likely problems are checked here, so that we do not apply a
1149  // too much secured approach in the rest of the classes in order to not overload the code
1150  // with checks everywhere, which could also possibly slows down its execution.
1151  // ============================================================================================================
1152 
1153  // Basic initialization checks (minimal initializations mandatory for the next steps)
1154 
1155  // scanner
1156  if (scanner_name.empty())
1157  {
1158  Cerr("***** castor-proj() -> Please provide a scanner name (format: Modality_Constuctor_Model) :" << endl);
1159  Cerr(" -sc scanner_alias: Give the scanner model." << endl);
1160  Cerr(" It must correspond to the name of one of the file in the scanner repository (without file extension)" << endl);
1161  Exit(EXIT_FAILURE);
1162  }
1163  else
1164  {
1165  if (verbose_general>=2) Cout(" selected scanner name: " << scanner_name << endl);
1166  }
1167 
1168  // Output files
1169  if (path_fout.empty() && path_dout.empty())
1170  {
1171  Cerr("***** castor-proj() -> Please provide an output option for output files (-fout or -dout) !" << endl);
1172  Exit(EXIT_FAILURE);
1173  }
1174  // Check that only one option has been provided
1175  if (!path_fout.empty() && !path_dout.empty())
1176  {
1177  Cerr("***** castor-proj() -> Please provide either output option -fout or -dout but not both !" << endl);
1178  Exit(EXIT_FAILURE);
1179  }
1180 
1181  // Image source
1182  if (path_to_initial_img.empty())
1183  {
1184  Cerr("***** castor-proj() -> -img path_to_img.hdr : Give an interfile header of the image to project" << endl);
1185  Exit(EXIT_FAILURE);
1186  }
1187  else
1188  {
1189  if (verbose_general>=2) Cout(" selected input image path: " << path_to_initial_img << endl);
1190  }
1191 
1192  Cout(endl);
1193 
1194 
1195 
1196 
1197  // ============================================================================================================
1198  // Singletons initialization: create here all the needed singletons.
1199  // ============================================================================================================
1200 
1201  // Get user endianness (for interfile)
1203 
1204  // OutputManager
1205  sOutputManager* p_outputManager;
1206  p_outputManager = sOutputManager::GetInstance();
1207  p_outputManager->SetVerbose(verbose_general);
1208 
1209  // Set datafile name(s) in order to be able to recover them from interfile classes
1210  vector <string> vpath_to_initial_img;
1211  vpath_to_initial_img.push_back(path_to_initial_img);
1212  p_outputManager->SetDataFileName(vpath_to_initial_img);
1213  // Set output number precision
1214  p_outputManager->SetOutNbPrec(onb_prec);
1215 
1216  // Set path to the config directory
1217  if (p_outputManager->CheckConfigDir(path_to_config_dir))
1218  {
1219  Cerr("***** castor-proj() -> A problem occurred while checking for the config directory path !" << endl);
1220  Exit(EXIT_FAILURE);
1221  }
1222 
1223  // Initialize output directory and base name
1224  if (p_outputManager->InitOutputDirectory(path_fout, path_dout))
1225  {
1226  Cerr("***** castor-proj() -> A problem occurred while initializing output directory !" << endl);
1227  Exit(EXIT_FAILURE);
1228  }
1229  // Log command line
1230  if (p_outputManager->LogCommandLine(argc,argv))
1231  {
1232  Cerr("***** castor-proj() -> A problem occurred while logging command line arguments !" << endl);
1233  Exit(EXIT_FAILURE);
1234  }
1235 
1236  // ScannerManager
1237  sScannerManager* p_scannermanager = sScannerManager::GetInstance();
1238  p_scannermanager->SetVerbose(verbose_scan);
1239  p_scannermanager->SetSaveLUTFlag(save_LUT_flag);
1240 
1241 
1242 
1243  // ============================================================================================================
1244  // Main part of the program: create all elements needed for the algorithm, create the algorithm, initialize it
1245  // and launch it.
1246  // ============================================================================================================
1247 
1248 
1249  // ============================================================================================================
1250  // Generate system geometry
1251  // ============================================================================================================
1252 
1253  scanner_name = (scanner_name.find(OS_SEP)) ?
1254  scanner_name.substr(scanner_name.find_last_of(OS_SEP)+1) :
1255  scanner_name;
1256 
1257  if(p_scannermanager->FindScannerSystem(scanner_name) )
1258  {
1259  Cerr("***** castor-proj() -> A problem occurred while searching for scanner system !" << endl);
1260  Exit(EXIT_FAILURE);
1261  }
1262 
1263  if(p_scannermanager->BuildScannerObject() ) //TODO verifier si correct d'envoyer uniquement le chemin du premier DataFile (pb si dataFile ne proviennent pas du même scan ou de la même acquisition)
1264  {
1265  Cerr("***** castor-proj() -> A problem occurred during scanner object construction !" << endl);
1266  Exit(EXIT_FAILURE);
1267  }
1268 
1269  if(p_scannermanager->InstantiateScanner() )
1270  {
1271  Cerr("***** castor-proj() -> A problem occurred while creating Scanner object !" << endl);
1272  Exit(EXIT_FAILURE);
1273  }
1274 
1275 
1276  //Set the specific mandatory geometry information of the modality using the SetXXXSpecificParameters functions of the scannerManager
1277  if (p_scannermanager->GetScannerType() == SCANNER_PET)
1278  {
1279  if(p_scannermanager->PROJ_SetPETSpecificParameters(max_axial_diff_mm) )
1280  {
1281  Cerr("***** castor-proj() -> A problem occurred while setting PET geometric parameters !" << endl);
1282  Exit(EXIT_FAILURE);
1283  }
1284  }
1285  else if (p_scannermanager->GetScannerType() == SCANNER_SPECT_CONVERGENT || p_scannermanager->GetScannerType() == SCANNER_SPECT_PINHOLE )
1286  {
1287  if(p_scannermanager->PROJ_SetSPECTSpecificParameters(SPECT_nb_bins,
1288  SPECT_nb_projection_angles,
1289  SPECT_first_angle,
1290  SPECT_step_angle,
1291  SPECT_projection_angles,
1292  SPECT_radius,
1293  SPECT_rot) )
1294  {
1295  Cerr("***** castor-proj() -> A problem occurred while setting SPECT geometric parameters !" << endl);
1296  Exit(EXIT_FAILURE);
1297  }
1298  }
1299 
1300 
1301  if(p_scannermanager->BuildLUT() )
1302  {
1303  Cerr("***** castor-proj() -> A problem occurred while generating/reading the LUT !" << endl);
1304  Exit(EXIT_FAILURE);
1305  }
1306 
1307 
1308  // Check the scanner manager parameters and initialize the scanner
1309  if (p_scannermanager->CheckParameters())
1310  {
1311  Cerr("***** castor-proj() -> A problem occurred while checking scanner manager parameters !" << endl);
1312  Exit(EXIT_FAILURE);
1313  }
1314  if (p_scannermanager->Initialize())
1315  {
1316  Cerr("***** castor-proj() -> A problem occurred while initializing scanner !" << endl);
1317  Exit(EXIT_FAILURE);
1318  }
1319 
1320 
1321  // ============================================================================================================
1322  // Recover image dimensions informations from the interfile header of the image to project
1323  // ============================================================================================================
1324 
1325  Intf_fields IF;
1326  IntfKeyInitFields(&IF);
1327 
1328  if(IntfReadHeader(path_to_initial_img, &IF, verbose_data) )
1329  {
1330  Cerr("***** castor-proj() -> An error occurred while trying to read the interfile header of file reading file " << path_to_initial_img << " !" << endl);
1331  Exit(EXIT_FAILURE);
1332  }
1333 
1334  if(verbose_general >= 3) IntfKeyPrintFields(IF);
1335 
1336  nb_VoxX = nb_VoxX<0 ? IF.mtx_size[0] : nb_VoxX ;
1337  nb_VoxY = nb_VoxY<0 ? IF.mtx_size[1] : nb_VoxY ;
1338  nb_VoxZ = nb_VoxZ<0 ? IF.mtx_size[2] : nb_VoxZ ;
1339 
1340  // TODO : nb_beds ?
1341  // If voxel sizes not provided/found, set them to the default value (1mm)
1342  vox_SizeX = IF.vox_size[0]<0 ? 1. : IF.vox_size[0];
1343  vox_SizeY = IF.vox_size[1]<0 ? 1. : IF.vox_size[1];
1344  vox_SizeZ = IF.vox_size[2]<0 ? 1. : IF.vox_size[2];
1345 
1346  // Add image offsets to user-defined offsets
1347  offsetX -= IF.vox_offset[0];
1348  offsetY -= IF.vox_offset[1];
1349  offsetZ -= IF.vox_offset[2];
1350 
1351  // Get the frame duration from the image in the case it is not provided by the user
1352  if (frame_list == "")
1353  {
1354  vector <string> image_filenames;
1355  if ( IntfIsMHD(path_to_initial_img, image_filenames) )
1356  {
1357  Cerr("***** castor-proj() -> Error : while trying to read the interfile header '"<< path_to_initial_img << "' !" << endl);
1358  Exit(EXIT_FAILURE);
1359  }
1360 
1361  // Image durations have been provided
1362  if(IF.image_duration.size()>0)
1363  {
1364  // Several files (serie of 3D images)
1365  // TODO : fill IF.study_duration with image durations if not init ?
1366  if(image_filenames.size() > 1)
1367  {
1368  // Check nb of frames and parse framing
1369  if(IF.image_duration.size() != (uint32_t)IF.nb_time_frames *
1370  IF.nb_resp_gates *
1371  IF.nb_card_gates )
1372  {
1373  Cerr("***** castor-proj() -> Interfile reading error of the input image :"<<endl);
1374  Cerr(" The number of provided image duration: '"<< IF.image_duration.size()
1375  << "' does not match the actual number of time frames * respiratory gates * cardiac gates ) '"<< IF.nb_time_frames *
1376  IF.nb_resp_gates *
1377  IF.nb_card_gates <<"' !" << endl);
1378  Exit(EXIT_FAILURE);
1379  }
1380 
1381  // If image files are splitted over a serie of 3D image files, we will have image durations for each image, including gates
1382  // As we need to recover the duration for each gate once, we skip gates if the data contains any
1383  for(int fr=0 ; fr<IF.nb_time_frames ; fr++)
1384  {
1385  // Manage start time of the frame, add dead frame if delay
1386  /*
1387  if(fr==0 && IF.image_start_time.at(0) > 0 )
1388  {
1389  stringstream ss;
1390  ss << IF.image_start_time.at(fr);
1391  //frame_list.append(ss.str()).append("df,");
1392  frame_list.append(ss.str());
1393  }
1394  // If the next frame starts after the previous frame, add frame duration
1395  else if(IF.image_start_time.at(fr) > ( IF.image_start_time.at(fr-1) + IF.image_duration.at(fr-1) ) )
1396  {
1397  stringstream ss;
1398  ss << IF.image_start_time.at(fr);
1399  frame_list.append(ss.str()).append("df,");
1400  }
1401  */
1402  // First frame : just add frame start
1403  if( fr==0 )
1404  {
1405  stringstream ss;
1406  ss << IF.image_start_time.at(fr);
1407  frame_list.append(ss.str());
1408  }
1409  // If current frame starts after the previous frame
1410  // -> add ':' and frame duration of the previous frame
1411  // -> add start time of the actual frame
1412  else if(IF.image_start_time.at(fr) > ( IF.image_start_time.at(fr-1) + IF.image_duration.at(fr-1) ) )
1413  {
1414  stringstream ss;
1415  ss << IF.image_duration.at(fr-1);
1416  frame_list.append(":").append(ss.str());
1417  ss.str("");
1418  ss << IF.image_start_time.at(fr);
1419  frame_list.append(",").append(ss.str());
1420  }
1421  // Just add frame start otherwise
1422  else
1423  {
1424  stringstream ss;
1425  ss << IF.image_start_time.at(fr);
1426  frame_list.append(",").append(ss.str());
1427  }
1428 
1429 
1430 
1431  // TODO TM: Check if the following is still required
1432 
1433  // Recover image duration and dead frames (if any) in the frame list
1434  /*
1435  stringstream ss_id, ss_df;
1436  // Go to the next frame (skip gate if any)
1437  ss_id << IF.image_duration.at(fr * IF.nb_resp_gates* IF.nb_card_gates);
1438  string frame_duration_str = ss_id.str();
1439 
1440  // Check if there is any dead frame (pause between frame groups)
1441  if(IF.frame_group_pause.size()>0)
1442  {
1443  FLTNB dead_frame_sec = IF.frame_group_pause.at(fr * IF.nb_resp_gates* IF.nb_card_gates);
1444  if(dead_frame_sec > 0.)
1445  {
1446  ss_df << dead_frame_sec;
1447  frame_duration_str.append(",").append(ss_df.str()).append("df");
1448  }
1449  }
1450  */
1451  //frame_list.append(frame_duration_str);
1452 
1453  /*
1454  // add comma if not last frame
1455  if(fr+1 < IF.nb_time_frames)
1456  frame_list.append(",");
1457  */
1458 
1459  // If last frame : add frame duration
1460  if(fr+1 >= IF.nb_time_frames)
1461  {
1462  stringstream ss;
1463  ss << IF.image_duration.at(fr);
1464  frame_list.append(":").append(ss.str());
1465  }
1466 
1467  }
1468  }
1469  else
1470  {
1471  if(IF.image_duration.size() != IF.nb_time_frames)
1472  {
1473  Cerr("***** castor-proj() -> Interfile reading error of the input image :"<<endl);
1474  Cerr(" The number of provided image duration: '"<< IF.image_duration.size()
1475  << "' does not match the actual number of time frames * respiratory gates * cardiac gates ) '"<< IF.nb_time_frames <<"' !" << endl);
1476  Exit(EXIT_FAILURE);
1477  }
1478 
1479  for(int fr=0 ; fr<IF.nb_time_frames ; fr++)
1480  {
1481  /*
1482  if(fr==0 && IF.image_start_time.at(0) > 0 )
1483  {
1484  stringstream ss;
1485  ss << IF.image_start_time.at(fr);
1486  frame_list.append(ss.str()).append("df,");
1487  }
1488  else if(IF.image_start_time.at(fr) > ( IF.image_start_time.at(fr-1) + IF.image_duration.at(fr-1) ) )
1489  {
1490  stringstream ss;
1491  ss << IF.image_start_time.at(fr);
1492  frame_list.append(ss.str()).append("df,");
1493  }
1494 
1495  stringstream ss;
1496  ss << IF.image_duration.at(fr);
1497  frame_list.append(ss.str());
1498  // add comma if not last frame
1499  if(fr+1 < IF.nb_time_frames)
1500  frame_list.append(",");
1501  */
1502 
1503 
1504  // First frame : just add frame start
1505  if( fr==0 )
1506  {
1507  stringstream ss;
1508  ss << IF.image_start_time.at(fr);
1509  frame_list.append(ss.str());
1510  }
1511  // If current frame starts after the previous frame
1512  // -> add ':' and frame duration of the previous frame
1513  // -> add start time of the actual frame
1514  else if(IF.image_start_time.at(fr) > ( IF.image_start_time.at(fr-1) + IF.image_duration.at(fr-1) ) )
1515  {
1516  stringstream ss;
1517  ss << IF.image_duration.at(fr-1);
1518  frame_list.append(":").append(ss.str());
1519  ss.str("");
1520  ss << IF.image_start_time.at(fr);
1521  frame_list.append(",").append(ss.str());
1522  }
1523  // Just add frame start otherwise
1524  else
1525  {
1526  stringstream ss;
1527  ss << IF.image_start_time.at(fr);
1528  frame_list.append(",").append(ss.str());
1529  }
1530 
1531  // If last frame : add frame duration
1532  if(fr+1 >= IF.nb_time_frames)
1533  {
1534  stringstream ss;
1535  ss << IF.image_duration.at(fr);
1536  frame_list.append(":").append(ss.str());
1537  }
1538  } // end of loop on frames
1539  } // end of condition on dynamic image type (one image or several)
1540  } // end of condition on image duration tag (present or not)
1541  // Image durations have not been provided,
1542  // use study duration which is initialized with 1s (default)
1543  else
1544  {
1545  stringstream ss;
1546  ss << IF.study_duration;
1547  frame_list.append("0:").append(ss.str());
1548  }
1549  }
1550 
1551 
1552  // Check nb gating
1553  (IF.nb_resp_gates >1) ? nb_resp_gates = IF.nb_resp_gates : 1 ;
1554  (IF.nb_card_gates >1) ? nb_card_gates = IF.nb_card_gates : 1 ;
1555 
1556  //TODO : offsets ?
1557 
1558  if(nb_VoxX<0 || nb_VoxY<0 || nb_VoxZ<0)
1559  {
1560  ReadDataASCIIFile(p_scannermanager->GetPathToScannerFile(), "voxels number transaxial", &nb_VoxX, 1, KEYWORD_MANDATORY);
1561  ReadDataASCIIFile(p_scannermanager->GetPathToScannerFile(), "voxels number transaxial", &nb_VoxY, 1, KEYWORD_MANDATORY);
1562  ReadDataASCIIFile(p_scannermanager->GetPathToScannerFile(), "voxels number axial", &nb_VoxZ, 1, KEYWORD_MANDATORY);
1563  }
1564 
1565  if ( (fov_SizeX<0 || fov_SizeY<0 || fov_SizeZ<0) && (vox_SizeX<0 || vox_SizeY<0 || vox_SizeZ<0) )
1566  {
1567  ReadDataASCIIFile(p_scannermanager->GetPathToScannerFile(), "field of view transaxial", &fov_SizeX, 1, KEYWORD_MANDATORY);
1568  ReadDataASCIIFile(p_scannermanager->GetPathToScannerFile(), "field of view transaxial", &fov_SizeY, 1, KEYWORD_MANDATORY);
1569  ReadDataASCIIFile(p_scannermanager->GetPathToScannerFile(), "field of view axial", &fov_SizeZ, 1, KEYWORD_MANDATORY);
1570  }
1571 /*
1572  else if ( (fov_SizeX<0 || fov_SizeY<0 || fov_SizeZ<0) && (vox_SizeX>=0 || vox_SizeY>=0 || vox_SizeZ>=0))
1573  {
1574  fov_SizeX = vox_SizeX*(FLTNB)nb_VoxX;
1575  fov_SizeY = vox_SizeY*(FLTNB)nb_VoxY;
1576  fov_SizeZ = vox_SizeZ*(FLTNB)nb_VoxZ;
1577  cout << vox_SizeX << " " << fov_SizeX << endl;
1578  }
1579  else
1580  {
1581  vox_SizeX = fov_SizeX/(FLTNB)nb_VoxX;
1582  vox_SizeY = fov_SizeY/(FLTNB)nb_VoxY;
1583  vox_SizeZ = fov_SizeZ/(FLTNB)nb_VoxZ;
1584  }
1585 */
1586  if (verbose_general>=2)
1587  {
1588  Cout(" Image dimensions for analytical projections: " << endl);
1589  Cout(" voxels number (X,Y,Z): " << nb_VoxX << "," << nb_VoxY << "," << nb_VoxZ << endl);
1590  Cout(" voxels size (X,Y,Z): " << vox_SizeX << "," << vox_SizeY << "," << vox_SizeZ << endl);
1591  Cout(" FOV (X,Y,Z): " << fov_SizeX << "," << fov_SizeY << "," << fov_SizeZ << endl);
1592  }
1593 
1594  // ============================================================================================================
1595  // oImageDimensionsAndQuantification settings
1596  // ============================================================================================================
1597 
1598  // Create oImageDimensionsAndQuantification
1599  oImageDimensionsAndQuantification* p_ImageDimensionsAndQuantification = new oImageDimensionsAndQuantification();
1600  p_ImageDimensionsAndQuantification->SetNbVoxX(nb_VoxX);
1601  p_ImageDimensionsAndQuantification->SetNbVoxY(nb_VoxY);
1602  p_ImageDimensionsAndQuantification->SetNbVoxZ(nb_VoxZ);
1603  p_ImageDimensionsAndQuantification->SetNbThreads(nb_threads);
1604  p_ImageDimensionsAndQuantification->SetNbBeds(nb_beds);
1605  p_ImageDimensionsAndQuantification->SetVoxSizeX(vox_SizeX);
1606  p_ImageDimensionsAndQuantification->SetVoxSizeY(vox_SizeY);
1607  p_ImageDimensionsAndQuantification->SetVoxSizeZ(vox_SizeZ);
1608  p_ImageDimensionsAndQuantification->SetFOVSizeX(fov_SizeX);
1609  p_ImageDimensionsAndQuantification->SetFOVSizeY(fov_SizeY);
1610  p_ImageDimensionsAndQuantification->SetFOVSizeZ(fov_SizeZ);
1611  p_ImageDimensionsAndQuantification->SetFOVOutMasking(0., 0);
1612  p_ImageDimensionsAndQuantification->SetOffsetX(offsetX);
1613  p_ImageDimensionsAndQuantification->SetOffsetY(offsetY);
1614  p_ImageDimensionsAndQuantification->SetOffsetZ(offsetZ);
1615  p_ImageDimensionsAndQuantification->SetVerbose(verbose_data);
1616  p_ImageDimensionsAndQuantification->SetNbRespGates(nb_resp_gates);
1617  p_ImageDimensionsAndQuantification->SetNbCardGates(nb_card_gates);
1618  p_ImageDimensionsAndQuantification->SetFrames(frame_list);
1619  if (p_ImageDimensionsAndQuantification->CheckParameters())
1620  {
1621  Cerr("***** castor-proj() -> A problem occurred while checking image dimensions parameters !" << endl);
1622  Exit(EXIT_FAILURE);
1623  }
1624  if (p_ImageDimensionsAndQuantification->Initialize())
1625  {
1626  Cerr("***** castor-proj() -> A problem occurred while initializing image dimensions !" << endl);
1627  Exit(EXIT_FAILURE);
1628  }
1629 
1630  // Initialization of DynamicDataManager class, related 4D data splitting management
1631  if (p_ImageDimensionsAndQuantification->InitDynamicData( "", 0, 0, 0, nb_resp_gates, nb_card_gates ) )
1632  {
1633  Cerr("***** castor-proj() -> A problem occurred while initializing Dynamic data manager's class !" << endl);
1634  Exit(EXIT_FAILURE);
1635  }
1636 
1637 
1638  // ----------------------------------------------------------------------------------------
1639  // Random Number Generator initialization: (we first required to know the number of threads to use from p_ImageDimensionsAndQuantification)
1640  // ----------------------------------------------------------------------------------------
1641 
1643  p_RNG->SetVerbose(verbose_general);
1644  // Use a user-provided seed to initialize the RNG if one has been provided. Use random number otherwise.
1645  (seed_RNG>=0 )?
1646  p_RNG->Initialize(seed_RNG, p_ImageDimensionsAndQuantification->GetNbThreadsForProjection(),0):
1647  p_RNG->Initialize(p_ImageDimensionsAndQuantification->GetNbThreadsForProjection(),0);
1648 
1649 
1650  // ============================================================================================================
1651  // DataFile initialization
1652  // ============================================================================================================
1653 
1654  vDataFile** p_DataFile = new vDataFile*[nb_beds];
1655 
1656  if (p_scannermanager->GetScannerType() < 0)
1657  {
1658  Cerr("***** castor-proj() -> Unknown scanner type !" << endl);
1659  Exit(EXIT_FAILURE);
1660  }
1661  else if (p_scannermanager->GetScannerType() == SCANNER_PET)
1662  {
1663  if (datafile_type!=TYPE_PET)
1664  {
1665  Cerr("***** castor-proj() -> Only PET type events are allowed while using a PET scanner !" << endl);
1666  Cerr("***** castor-proj() -> (use '-fileType' to define modality (0=PET, 1=SPECT, 2=CT) )" << endl);
1667  Exit(EXIT_FAILURE);
1668  }
1669  for (int i=0 ; i<nb_beds ; i++)
1670  {
1671  p_DataFile[i] = new iDataFilePET();
1672  if(path_to_attenuation_img != "") // Enable correction factor for attenuation
1673  (dynamic_cast<iDataFilePET*>(p_DataFile[i]))->SetAtnCorrectionFlagOn();
1674  }
1675  }
1676  else if (p_scannermanager->GetScannerType() == SCANNER_SPECT_CONVERGENT)
1677  {
1678  if (datafile_type!=TYPE_SPECT)
1679  {
1680  Cerr("***** castor-proj() -> Only SPECT type events are allowed while using a SPECT scanner !" << endl);
1681  Cerr("***** castor-proj() -> (use '-fileType' to define modality (0=PET, 1=SPECT, 2=CT) )" << endl);
1682  Exit(EXIT_FAILURE);
1683  }
1684  for (int i=0 ; i<nb_beds ; i++)
1685  {
1686  p_DataFile[i] = new iDataFileSPECT();
1687  }
1688  }
1689  else
1690  {
1691  Cerr("***** castor-proj() -> Unsupported scanner type !" << endl);
1692  Exit(EXIT_FAILURE);
1693  }
1694 
1695  // Compute total acquisition duration in seconds
1696  for (int fr=0 ; fr<p_ImageDimensionsAndQuantification->GetNbTimeFrames() ; fr++)
1697  acquisition_duration_sec += p_ImageDimensionsAndQuantification->GetFrameDurationInSec(0, fr);
1698 
1699  // Load raw data in memory and do other stuff if needed.
1700  // TODO TM : Even if the loop is there, no support for multi-bed projection as for now (case we have to project an image as in a multi-bad acquisition)
1701  // It would first require some informations about the FOV of each bed (get this from interfile header of image or for command line options ?)
1702  // In the loop, we need to provide the bed in argument of PROJ_InitFile() in order to correctly initialize the beds
1703  for (int bed=0 ; bed<nb_beds ; bed++)
1704  {
1705  p_DataFile[bed]->SetBedIndex(bed);
1706  p_DataFile[bed]->SetVerbose(verbose_data);
1707  p_DataFile[bed]->SetDataMode(datafile_mode);
1708  p_DataFile[bed]->SetDataType(datafile_type);
1709  p_DataFile[bed]->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
1710  p_DataFile[bed]->PROJ_GetScannerSpecificParameters();
1711  p_DataFile[bed]->PROJ_InitFile();
1712  p_DataFile[bed]->ComputeSizeEvent();
1713  p_DataFile[bed]->SetDuration(acquisition_duration_sec);
1714  // The Check parameters function is dedicated to reconstruction, as it checks things such as consistenties between size of the datafile and user-provided information
1715  if(p_DataFile[bed]->CheckParameters())
1716  {
1717  Cerr("***** castor-proj() -> A problem occurred while checking datafile parameters ! Abort." << endl);
1718  Exit(EXIT_FAILURE);
1719  }
1720  p_DataFile[bed]->PrepareDataFile();
1721 
1722  /*
1723  if(p_DataFile[bed]->SetScannerSpecificParameters())
1724  {
1725  Cerr("***** A problem occurred while setting scanner parameters from the datafile !" << endl);
1726  Exit(EXIT_FAILURE);
1727  }
1728  */
1729 
1730  //p_DataFile[bed]->InitDynamicData(p_ImageDimensionsAndQuantification->GetNbTimeFrames(), nb_resp_gates, nb_card_gates, "", 0, 0, bed);
1731 
1732  /*
1733  if (p_DataFile[bed]->InitDynamicData(nb_resp_gates, nb_card_gates, "", 0, 0, 0, p_DataFile[bed]) )
1734  {
1735  Cerr("***** A problem occurred while initializing Dynamic data !" << endl);
1736  Exit(EXIT_FAILURE);
1737  }
1738  */
1739  }
1740 
1741 
1742  // ============================================================================================================
1743  // Projector manager initialization
1744  // ============================================================================================================
1745 
1746  // Create object
1747  oProjectorManager* p_ProjectorManager = new oProjectorManager();
1748 
1749  // Set all parameters
1750  p_ProjectorManager->SetScanner(p_scannermanager->GetScannerObject());
1751  p_ProjectorManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
1752  p_ProjectorManager->SetDataFile(p_DataFile[0]);
1753  p_ProjectorManager->SetComputationStrategy(projector_computation_strategy);
1754  p_ProjectorManager->SetOptionsForward(options_projector);
1755  p_ProjectorManager->SetOptionsBackward(options_projector);
1756  p_ProjectorManager->SetOptionsCommon("");
1757  p_ProjectorManager->SetVerbose(verbose_proj);
1758 
1759  // Check parameters
1760  if (p_ProjectorManager->CheckParameters())
1761  {
1762  Cerr("***** castor-proj() -> A problem occurred while checking projector manager's parameters !" << endl);
1763  Exit(EXIT_FAILURE);
1764  }
1765 
1766  // Initialize projector manager
1767  if (p_ProjectorManager->Initialize())
1768  {
1769  Cerr("***** castor-proj() -> A problem occurred while initializing projector manager !" << endl);
1770  Exit(EXIT_FAILURE);
1771  }
1772 
1773 
1774 
1775 
1776  // ============================================================================================================
1777  // Image Convolver manager initialization
1778  // ============================================================================================================
1779 
1780  // Create object
1781  oImageConvolverManager* p_ImageConvolverManager = new oImageConvolverManager();
1782  // Set all parameters
1783  p_ImageConvolverManager->SetVerbose(verbose_conv);
1784  p_ImageConvolverManager->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
1785  p_ImageConvolverManager->SetOptions(options_image_convolver);
1786 
1787  // Check parameters
1788  if (p_ImageConvolverManager->CheckParameters())
1789  {
1790  Cerr("***** castor-proj() -> A problem occurred while checking optimizer manager's parameters !" << endl);
1791  Exit(EXIT_FAILURE);
1792  }
1793  // Initialize optimizer manager
1794  if (p_ImageConvolverManager->Initialize())
1795  {
1796  Cerr("***** castor-proj() -> A problem occurred while initializing optimizer manager !" << endl);
1797  Exit(EXIT_FAILURE);
1798  }
1799 
1800 
1801 
1802  // ============================================================================================================
1803  // Image Space initialization
1804  // ============================================================================================================
1805 
1806  oImageSpace* p_ImageSpace = new oImageSpace();
1807  p_ImageSpace->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
1808  p_ImageSpace->SetVerbose(verbose_data);
1809 
1810 
1811 
1812  // ============================================================================================================
1813  // Init alogorithm and proceed to analytical projection
1814  // ============================================================================================================
1815 
1816  oAnalyticProjection* p_Projection = new oAnalyticProjection();
1817  p_Projection->InitOptimizer(p_ImageDimensionsAndQuantification);
1818  if (p_Projection->InitNoiseModel(noise_model) )
1819  {
1820  Cerr("***** castor-proj() -> A problem occurred while initializing noise model !" << endl);
1821  Exit(EXIT_FAILURE);
1822  }
1823 
1824  p_Projection->SetImageDimensionsAndQuantification(p_ImageDimensionsAndQuantification);
1825  p_Projection->SetProjectorManager(p_ProjectorManager);
1826  p_Projection->SetImageConvolverManager(p_ImageConvolverManager);
1827  p_Projection->SetImageSpace(p_ImageSpace);
1828  p_Projection->SetDataFile(p_DataFile);
1829  p_Projection->SetGPUflag(gpu_flag);
1830  p_Projection->SetVerbose(verbose_algo);
1831  p_Projection->SetNbBeds(nb_beds);
1832  p_Projection->SetPathInitImage(path_to_initial_img);
1833  p_Projection->SetPathAtnImage(path_to_attenuation_img);
1834  p_Projection->SetScanner(p_scannermanager->GetScannerObject());
1835  p_Projection->SetNoZeroEvent(discard_nil_events_flag);
1836 
1837  // Launch analytical projection
1838  if (p_Projection->Launch())
1839  {
1840  Cerr("***** castor-proj() ->Error occurred during Projections" << endl;);
1841  }
1842 
1843 
1844  // ============================================================================================================
1845  // End
1846  // ============================================================================================================
1847 
1848  if(SPECT_projection_angles) delete SPECT_projection_angles;
1849 
1850  if (verbose_general>=5) Cout("----- Deleting CASToR objects ... -----" << endl);
1851  delete p_Projection;
1852  delete p_ImageSpace;
1853  delete p_ImageConvolverManager;
1854  delete p_ProjectorManager;
1855 
1856 
1857  // Delete objects
1858  for (int i=0 ; i<nb_beds ; i++) delete p_DataFile[i];
1859  delete[] p_DataFile;
1860  delete p_ImageDimensionsAndQuantification;
1861 
1862 
1863  if (verbose_general>=5) Cout("----- CASToR objects successfully deleted -----" << endl);
1864 
1865  // Ending
1866  if (verbose_general>=1) Cout(endl);
1867  #ifdef CASTOR_MPI
1868  MPI_Finalize();
1869  #endif
1870  return EXIT_SUCCESS;
1871 }
void SetDataMode(int a_dataMode)
This class is designed to be a mother virtual class for DataFile.
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
static sRandomNumberGenerator * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
#define MODE_HISTOGRAM
static void ShowCommonHelp()
This function is used to print out some help about the use of options common to all projectors...
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
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.
This class manages the analytic projection of an image and the computation of the associated datafile...
#define Cerr(MESSAGE)
void SetOptionsCommon(const string &a_optionsCommon)
int Initialize()
A function used to initialize the manager and the projectors or system matrices it manages...
int FindScannerSystem(string a_scannerName)
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
int BuildScannerObject()
Instantiate the specific scanner object related to the modality, and set verbosity of scanner object...
int IntfIsMHD(string a_pathToFile, vector< string > &ap_lPathToImgs)
Check if the string in argument contains the path to a Interfile metaheader.
void SetOptionsForward(const string &a_optionsForward)
int CheckParameters()
A function used to check the parameters settings.
void ShowHelpDynamic()
Display command line options related to the dynamic features for castor-proj.
Definition: castor-proj.cc:273
void SetVerbose(int a_verboseLevel)
void SetDuration(FLTNB a_value)
virtual int ComputeSizeEvent()=0
This function is implemented in child classes Computation of the size of each event according to th...
void Exit(int code)
void SetVerbose(int a_verboseLevel)
Set verbosity level.
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
void ShowHelpProj()
Display command line options related to the Projector module for castor-proj.
Definition: castor-proj.cc:169
void IntfKeyPrintFields(Intf_fields a_IF)
Print all the keys of the Intf_fields structure passed in parameter, as well as their values for debu...
int CheckParameters()
Check if all parameters have been correctly initialized, and call the CheckParameters function of the...
int InstantiateScanner()
Instantiate scanner using the related function in the scanner classes.
int LogCommandLine(int argc, char **argv)
static sAddonManager * GetInstance()
#define FIXED_LIST_COMPUTATION_STRATEGY
int CheckConfigDir(const string &a_path)
int CheckParameters()
A function used to check the parameters settings.
void ShowHelpSPECT()
Definition: castor-proj.cc:306
#define SCANNER_SPECT_CONVERGENT
void SetImageConvolverManager(oImageConvolverManager *ap_ImageConvolverManager)
int BuildLUT()
Call the eponym function of the scanner class.
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 SetComputationStrategy(int a_computationStrategy)
void SetOptionsBackward(const string &a_optionsBackward)
void SetDataType(int a_dataType)
void SetDataFile(vDataFile *ap_DataFile)
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 ...
int PROJ_SetPETSpecificParameters(FLTNB a_maxAxialDiffmm)
void ShowHelpComputation()
Display command line options related to the computation settings for castor-proj. ...
Definition: castor-proj.cc:214
virtual int PrepareDataFile()=0
This function is implemented in child classes Store different kind of information inside arrays (da...
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Inherit from vDataFile. Class that manages the reading of a SPECT input file (header + data)...
int main(int argc, char **argv)
Definition: castor-proj.cc:405
This class is designed to manage the different image convolvers and to apply them.
void ShowHelpInput()
Display command line options related to input settings for castor-proj.
Definition: castor-proj.cc:101
int Launch()
Just call either the LaunchCPU or the LaunchGPU function as asked for.
int CheckParameters()
A function used to check the parameters settings.
int InitDynamicData(string a_pathTo4DDataSplittingFile, int a_respMotionCorrectionFlag, int a_cardMotionCorrectionFlag, int a_invMotionCorrectionFlag, int a_nbRespGates, int a_nbCardGates)
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
void ShowHelpProjector()
Show help about all implemented projectors.
void ShowHelpOutput()
Display command line options related to output settings for castor-proj.
Definition: castor-proj.cc:131
#define KEYWORD_MANDATORY
int PROJ_SetSPECTSpecificParameters(uint16_t *ap_nbOfBins, uint32_t a_nbOfProjections, FLTNB a_firstAngle, FLTNB a_stepAngle, FLTNB *ap_projectionAngles, FLTNB a_CORtoDetectorDistance, string a_rotDirection)
static void ShowCommonHelp()
This function does not take any parameter and is used to display some help about the syntax of the op...
Singleton class that generate a thread-safe random generator number for openMP As singleton...
void IntfKeyInitFields(Intf_fields *ap_IF)
Init the file of an Interfile fields structure passed in parameter to their default values...
void ShowHelp(int a_returnCode, int a_mpiRank)
Definition: castor-proj.cc:30
void SetFOVOutMasking(FLTNB a_fovOutPercent, INTNB a_nbSliceOutMask)
int Initialize()
Initialization : .
void ShowHelpMiscellaneous()
Display command line settings related to SPECT modality for castor-proj.
Definition: castor-proj.cc:369
This class is designed to manage the projection part of the reconstruction.
void ShowHelpPET()
Definition: castor-proj.cc:344
Interfile fields. This structure contains all the Interfile keys currently managed by CASToR Decl...
void SetBedIndex(int a_bedIndex)
void GetUserEndianness()
Check user/host computer endianness and write it to the global variable User_Endianness.
This class holds all the matrices in the image domain that can be used in the algorithm: image...
int InitOutputDirectory(const string &a_pathFout, const string &a_pathDout)
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;.
void SetOptions(vector< string > a_options)
void SetProjectorManager(oProjectorManager *ap_ProjectorManager)
This class is designed to manage all dimensions and quantification related stuff. ...
int GetNbThreadsForProjection()
Get the number of threads used for projections.
void SetVerbose(int a_verboseLevel)
virtual int PROJ_GetScannerSpecificParameters()=0
This function is implemented in child classes It is used to set several variables of the datafile w...
void SetDataFileName(vector< string > ap_dataFileName)
int IntfReadHeader(const string &a_pathToHeaderFile, Intf_fields *ap_IntfFields, int vb)
Read an Interfile header.
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...
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Inherit from vDataFile. Class that manages the reading of a PET input file (header + data)...
#define Cout(MESSAGE)
void InitOptimizer(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
virtual int PROJ_InitFile()=0
This function is implemented in child classes Initialize the fstream objets for output writing as w...
void SetVerbose(int a_verboseLevel)
int Initialize()
A function used to initialize the manager and all image convolvers it manages.
void ShowHelpImageConvolver()
Show help about all implemented image convolvers.