CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
toolkits/castor-imageDynamicTools.cc
Go to the documentation of this file.
1 
8 #include "gVariables.hh"
9 #include "gOptions.hh"
10 #include "sOutputManager.hh"
11 #include <iomanip> //std::setprecision
12 
13 #include "oImageSpace.hh"
14 #include "oDynamicModelManager.hh"
15 #include "sRandomNumberGenerator.hh"
16 #include "sChronoManager.hh"
17 
23 void ShowHelp(int a_returnCode)
24 {
25  cout << endl;
26  cout << "Usage: castor-imageDynamicTools -i path_to_ifile.root"<< endl;
27  cout << " -fout name"<< endl;
28  cout << " -OR- "<< endl;
29  cout << " -dout name "<< endl;
30  cout << " -dynamic-model param" << endl;
31  cout << endl;
32  cout << endl;
33  cout << "[Main settings]:" << endl;
34  cout << " -i path_to_in_image : give an input dynamic interfile image" << endl;
35  cout << " -fout name : Give the root name for all output files. All output files will be written as 'name_suffix.ext'." << endl;
36  cout << " So the provided name should not end with '.' or '/' character. (no default, alternative to -dout)" << endl;
37  cout << " -dout name : Give the name of the output directory where all output files will be written. All files will also" << endl;
38  cout << " be prefixed by the name of the directory. The provided name should not end with '.' or '/' character." << endl;
39  cout << " (no default, alternative to -fout)" << endl;
40  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;
41  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;
42  cout << endl;
43  cout << " -delay value : Delay condition in seconds to exclude early frames from the application of the dynamic model, if series of images are provided as input." << endl;
44  cout << endl;
45  cout << " -im param : Provide an image-based deformation model to be used for involuntary motion correction (for testing purposes), along with a configuration file (deformation:file)" << endl;
46  cout << " or the list of parameters associated to the projector (deformation,param1,param2,...)." << endl;
47  cout << endl;
48  cout << endl;
49  cout << "[Optional settings]:" << endl;
50  cout << " -it nb : Number of iterations for both parameters estimation and subsequent dynamic image estimation steps of the dynamic model (default = 1)." << endl;
51  cout << " -omd : (M)erge (D)ynamic images. Indicate if a dynamic serie of 3D images should be written on disk in one file" << endl;
52  cout << " instead of a serie of 3D images associated with an interfile metaheader" << endl;
53  cout << " -odi : Output dynamic images. Generate the serie of dynamic images estimated from the parametric images of the dynamic model. By default, only the parametric images are generated" << endl;
54  cout << endl;
55  cout << " -onbp prec : By default, numbers are displayed using scientific format. This option allows to customize the format and precision" << endl;
56  cout << " : The format is format,precision. f is the format (s=scientific, f=fixed), p is the precision" << endl;
57  cout << " eg: -onbp f,5 --> fixed with 5 digits precision, -onbp --> scientifici with max precision." << endl;
58  cout << endl;
59  #ifdef CASTOR_OMP
60  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;
61  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;
62  cout << endl;
63  #endif
64  cout << "[Miscellaneous settings]:" << endl;
65  cout << " -vb : give the verbosity level, from 0 (no verbose) to above 5 (at the event level) (default: 1)." << endl;
66  cout << endl;
67 
68  Exit(a_returnCode);
69 }
70 
71 
72 /*
73  Main program
74 */
75 
76 int main(int argc, char** argv)
77 {
78 
79  // ============================================================================================================
80  // MPI stuff (we make all instances but the first one returning 0 directly)
81  // ============================================================================================================
82  #ifdef CASTOR_MPI
83  int mpi_rank = 0;
84  int mpi_size = 1;
85  MPI_Init(&argc, &argv);
86  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
87  MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
88  if (mpi_rank!=0) return 0;
89  #endif
90 
91  // No argument, then show help
92  if (argc==1) ShowHelp(0);
93 
94  // ============================================================================================================
95  // Parameterized variables with their default values
96  // ============================================================================================================
97 
98  // String which gathers the path to the input data filename provided by the user. no default
99  string input_file = "";
100  vector<string> path_to_input_image;
101 
102  // Path to user provided data and output files/images
103  string path_fout = "";
104  string path_dout = "";
105  string dynamic_model_options = "";
106  string motion_options = "";
107 
108  // Frame list descriptor
109  string frame_list = "";
110  // Delay for application of dynamic model
111  int delayInSec = 0 ;
112  // Number of images to skip based on delay criteria
113  int nb_FramesToSkip =0;
114  // Number of resp gates
115  int nb_resp_gates = 1;
116  // Number of card gates
117  int nb_card_gates = 1;
118  // Number of iterations for the dynamic model
119  uint32_t nb_ite_dyn = 1;
120  // Number of threads
121  string nb_threads = "1";
122  // Merge output dynamic images on disk into one file or not
123  bool merge_dynamic_imgs_flag = false;
124  // Output dynamic images estimated from the model
125  bool output_dynamic_imgs_from_model = false;
126  // Precision for output number display
127  string onb_prec = "s,0";
128 
129  // Verbosity
130  int vb = 0;
131 
132  // ============================================================================================================
133  // Read command-line parameters
134  // ============================================================================================================
135  for (int i=1; i<argc; i++)
136  {
137  string option = (string)argv[i];
138 
139  if (option=="-h" || option=="--help" || option=="-help") ShowHelp(0);
140 
141  // Just one file is provided
142  if (option=="-i")
143  {
144  if (path_to_input_image.size() > 0)
145  {
146  Cerr("***** castor-imageDynamicTools :: the following file names have already been provided (-i/-il options must be used ONCE): " << endl);
147  for (size_t i=0 ; i<path_to_input_image.size() ; i++)
148  Cout(" Selected input image file: " << path_to_input_image[i] << endl);
149  Exit(EXIT_FAILURE);
150  }
151  else
152  {
153  if (argv[i+1] == NULL)
154  {
155  Cerr("***** castor-imageDynamicTools :: argument missing for option: " << option << endl);
156  Exit(EXIT_FAILURE);
157  }
158  else
159  {
160  input_file = argv[i+1];
161  path_to_input_image.push_back(input_file);
162  }
163  i++;
164  }
165  }
166 
167  // Name of the output directory
168  else if (option=="-dout") // This is a mandatory option
169  {
170  if (i>=argc-1)
171  {
172  Cerr("***** castor-imageDynamicTools() -> Argument missing for option: " << option << endl);
173  Exit(EXIT_FAILURE);
174  }
175  path_dout = argv[i+1];
176  i++;
177  }
178  // Base name of the output files
179  else if (option=="-fout") // This is a mandatory option
180  {
181  if (i>=argc-1)
182  {
183  Cerr("***** castor-imageDynamicTools() -> Argument missing for option: " << option << endl);
184  Exit(EXIT_FAILURE);
185  }
186  path_fout = argv[i+1];
187  i++;
188  }
189 
190  // Flag to say that we want to save time basis functions too
191  else if (option=="-omd")
192  {
193  merge_dynamic_imgs_flag = true;
194  }
195 
196  else if (option=="-odi")
197  {
198  output_dynamic_imgs_from_model = true;
199  }
200 
201  #ifdef CASTOR_OMP
202  else if (option=="-th")
203  {
204  if (i>=argc-1)
205  {
206  Cerr("***** castor-imageDynamicTools() -> Argument missing for option: " << option << endl);
207  Exit(EXIT_FAILURE);
208  }
209  nb_threads = (string)argv[i+1];
210  i++;
211  }
212  #endif
213 
214  // Dynamic model applied to the frames/respiratory gates/cardiac gates of the dynamic acquisition
215  else if (option=="-dynamic-model")
216  {
217  if (i>=argc-1)
218  {
219  Cerr("***** castor-imageDynamicTools() -> Argument missing for option: " << option << endl);
220  Exit(EXIT_FAILURE);
221  }
222  dynamic_model_options = (string)argv[i+1];
223  i++;
224  }
225  // Delay in seconds
226  else if (option=="-delay")
227  {
228  if (i>=argc-1)
229  {
230  Cerr("***** castor-imageDynamicTools :: Argument missing for option: " << option << endl);
231  Exit(EXIT_FAILURE);
232  }
233  delayInSec = atoi(argv[i+1]);
234  i++;
235  }
236  // Number of iterations for the dynamic model
237  else if (option=="-it")
238  {
239  if (i>=argc-1)
240  {
241  Cerr("***** castor-imageDynamicTools() -> Argument missing for option: " << option << endl);
242  Exit(EXIT_FAILURE);
243  }
244 
245  if (ConvertFromString(argv[i+1], &nb_ite_dyn))
246  {
247  Cerr("***** castor-imageDynamicTools() -> Exception when trying to read provided number iterations for the dynamic model (must be strictly positive integer) '" << nb_ite_dyn << " for option: " << option << endl);
248  Exit(EXIT_FAILURE);
249  }
250  i++;
251  }
252 
253  // Data for involuntary motion correction based on deformation
254  else if (option=="-im")
255  {
256  if (i>=argc-1)
257  {
258  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
259  Exit(EXIT_FAILURE);
260  }
261  motion_options = (string)argv[i+1];
262  i++;
263  }
264 
265  // Verbosity level
266  else if (option=="-vb")
267  {
268  if (i>=argc-1)
269  {
270  Cerr("***** castor-imageDynamicTools :: Argument missing for option: " << option << endl);
271  Exit(EXIT_FAILURE);
272  }
273  vb = atoi(argv[i+1]);
274  i++;
275  }
276  // Output number precision
277  else if (option=="-onbp")
278  {
279  if (i>=argc-1)
280  {
281  Cerr("***** castor-recon() -> Argument missing for option: " << option << endl);
282  Exit(EXIT_FAILURE);
283  }
284  onb_prec = argv[i+1];
285  i++;
286  }
287  else
288  {
289  Cerr("***** castor-imageDynamicTools :: Unknown option '" << option << "' !" << endl);
290  Exit(EXIT_FAILURE);
291  }
292  }
293 
294 
295  // ============================================================================================================
296  // Mandatory checks:
297  // ============================================================================================================
298 
299  // Basic initialization checks (minimal initializations mandatory for the next steps)
300 
301  // data files
302  if (path_to_input_image.empty() )
303  {
304  Cerr("***** castor-imageDynamicTools :: Please provide at least one data filename (-i)" << endl);
305  ShowHelp(0);
306  Exit(EXIT_FAILURE);
307  }
308  else
309  {
310  if(vb >= 2)
311  {
312  Cout(" Selected root data-file(s) to convert: " << endl);
313  for (size_t i=0 ; i<path_to_input_image.size() ; i++)
314  Cout(path_to_input_image[i] << endl);
315  }
316  }
317 
318  // Output files
319  if (path_fout.empty() && path_dout.empty())
320  {
321  Cerr("***** castor-imageDynamicTools() -> Please provide an output option for output files (-fout or -dout) !" << endl);
322  Exit(EXIT_FAILURE);
323  }
324  // Check that only one option has been provided
325  if (!path_fout.empty() && !path_dout.empty())
326  {
327  Cerr("***** castor-imageDynamicTools() -> Please provide either output option -fout or -dout but not both !" << endl);
328  Exit(EXIT_FAILURE);
329  }
330 
331  // Check only one option has been enabled between -dynamic-model and -im
332  if (dynamic_model_options != ""
333  && motion_options != "")
334  {
335  Cerr("***** castor-imageDynamicTools() -> Please provide either output option -dynamic-model or -im but not both !" << endl);
336  Exit(EXIT_FAILURE);
337  }
338 
339 
340  // ============================================================================================================
341  // Initialization:
342  // ============================================================================================================
343 
344  // (Required for options using interfile I/O)
346 
347  // ----------------------------------------------------------------------------------------
348  // Create sOutputManager
349  // ----------------------------------------------------------------------------------------
350  sOutputManager* p_outputManager = sOutputManager::GetInstance();
351  // Set verbose level
352  p_outputManager->SetVerbose(vb);
353 
354  // Set output dynamic image policy
355  p_outputManager->SetMergeDynImagesFlag(merge_dynamic_imgs_flag);
356 
357  // Set output number precision
358  p_outputManager->SetOutNbPrec(onb_prec);
359 
360  // Set path to the config directory
361  if (p_outputManager->CheckConfigDir(""))
362  {
363  Cerr("***** castor-imageDynamicTools() -> A problem occurred while checking for the config directory path !" << endl);
364  Exit(EXIT_FAILURE);
365  }
366  // Initialize output directory and base name
367  if (p_outputManager->InitOutputDirectory(path_fout, path_dout))
368  {
369  Cerr("***** castor-imageDynamicTools() -> A problem occurred while initializing output directory !" << endl);
370  Exit(EXIT_FAILURE);
371  }
372  // Log command line
373  if (p_outputManager->LogCommandLine(argc,argv))
374  {
375  Cerr("***** castor-imageDynamicTools() -> A problem occurred while logging command line arguments !" << endl);
376  Exit(EXIT_FAILURE);
377  }
378 
379 
380  // ============================================================================================================
381  // Instanciate/Initialize image objects
382  // ============================================================================================================
383 
384  Intf_fields IF;
385  IntfKeyInitFields(&IF);
386 
387  int i=0; // May implement the application of the dynamic model to a series of images later
388  if(IntfReadHeader(path_to_input_image[i], &IF, vb) )
389  {
390  Cerr("***** castor-imageDynamicTools() -> An error occurred while trying to read the interfile header of file reading file " << path_to_input_image[i] << " !" << endl);
391  Exit(EXIT_FAILURE);
392  }
393 
394  // Get the frame duration from the image interfile
395  vector <string> image_filenames;
396 
397  if ( IntfIsMHD(path_to_input_image[i], image_filenames) < 0 )
398  {
399  Cerr("***** castor-imageDynamicTools() -> Error : while trying to read the interfile header '"<< path_to_input_image[i] << "' !" << endl);
400  Exit(EXIT_FAILURE);
401  }
402 
403  // Generate frame list from image header metadata
404  if(IF.image_duration.size()>0 || image_filenames.size() >0) // Image durations have been provided
405  {
406  // We have one mhd file and a set of several 3D images
407  if(image_filenames.size() > 1)
408  {
409  // If image files are splitted over a series of 3D image files, we will have image durations for each image, including gates
410  // As we need to recover the duration for each gate once, we skip gates if the data contains any
411  for(int fr=0 ; fr<IF.nb_time_frames ; fr++)
412  {
413  // First, initialize IF using the image corresponding to the 'fr' frame
414  if(IntfReadHeader(image_filenames[fr], &IF, vb) )
415  {
416  Cerr("***** castor-imageDynamicTools() -> An error occurred while trying to read the interfile header of file reading file " << path_to_input_image[i] << " !" << endl);
417  Exit(EXIT_FAILURE);
418  }
419 
420  // Recover image duration and dead frames (if any) in the frame list
421  stringstream ss_duration, ss_startTime;
422 
423  // Go to the next frame (skip gate if any)
424  ss_duration << IF.image_duration.at(fr * IF.nb_resp_gates* IF.nb_card_gates);
425  ss_startTime << IF.image_start_time.at(fr * IF.nb_resp_gates* IF.nb_card_gates);
426  string frame_duration_str = ss_duration.str();
427  string frame_start_str = ss_startTime.str();
428 
429  // Building frame_list with as "StartTime:Duration,StartTime:Duration,...."
430  if (stoi(frame_start_str)<delayInSec) nb_FramesToSkip ++;
431  // Applied if the frame start time is greater than the provided Delay
432  else
433  {
434  frame_list.append(frame_start_str);
435  frame_list.append(":");
436  frame_list.append(frame_duration_str);
437 
438  // add comma if not last frame
439  if (fr + 1 < IF.nb_time_frames)
440  frame_list.append(",");
441  }
442  }
443  }
444  // All dynamic images concatenated in one file
445  else
446  {
447  if(IF.image_duration.size() != IF.nb_time_frames)
448  {
449  Cerr("***** castor-imageDynamicTools() -> Interfile reading error of the input image :"<<endl);
450  Cerr(" The number of provided image duration: '"<< IF.image_duration.size()
451  << "' does not match the actual number of time frames * respiratory gates * cardiac gates ) '"<< IF.nb_time_frames <<"' !" << endl);
452  Exit(EXIT_FAILURE);
453  }
454 
455  //----------------------------------------------------------------
456  for(int fr=0 ; fr<IF.nb_time_frames ; fr++)
457  {
458  // First frame : just add frame start
459  if( fr==0 )
460  {
461  stringstream ss;
462  // check if image_start_time key has been initialized
463  // (size == nb frames)
464  // assume and init start time = 0 otherwise
465  if (IF.image_start_time.size() != IF.nb_time_frames)
466  IF.image_start_time.push_back(0);
467 
468  ss << IF.image_start_time.at(fr);
469  frame_list.append(ss.str());
470  }
471  // If current frame starts after the previous frame
472  // -> add ':' and frame duration of the previous frame
473  // -> add start time of the actual frame
474  else if( IF.image_start_time.size() == IF.nb_time_frames // image_start_time key provided
475  && IF.image_start_time.at(fr) > ( IF.image_start_time.at(fr-1) + IF.image_duration.at(fr-1) ) )
476  {
477  stringstream ss;
478  ss << IF.image_duration.at(fr-1);
479  frame_list.append(":").append(ss.str());
480  ss.str("");
481  ss << IF.image_start_time.at(fr);
482  frame_list.append(",").append(ss.str());
483  }
484  // Just add frame start otherwise
485  else
486  {
487  stringstream ss;
488  // init start time if not provided
489  if (IF.image_start_time.size() != IF.nb_time_frames)
490  {
491  FLTNB start_time = IF.image_start_time.at(fr-1) + IF.image_duration.at(fr-1);
492  IF.image_start_time.push_back(start_time);
493  }
494 
495  ss << IF.image_start_time.at(fr);
496  frame_list.append(",").append(ss.str());
497  }
498 
499  // If last frame : add frame duration
500  if(fr+1 >= IF.nb_time_frames)
501  {
502  stringstream ss;
503  ss << IF.image_duration.at(fr);
504  frame_list.append(":").append(ss.str());
505  }
506  } // end of loop on frames
507 
508  }
509 
510  // Print out the skiped frame information
511  if(vb >= 2) Cout ("----- Number of frames to skip from model fit: " << nb_FramesToSkip << endl);
512  if(vb >= 2) Cout ("Frame list is : " << frame_list << endl);
513  }
514 
515  // Instantiate & Initialize oImageDimensionsAndQuantification object, required for datafile generation (number of threads)
517 
518  // Check nb gating
519  (IF.nb_resp_gates >1) ? nb_resp_gates = IF.nb_resp_gates : 1 ;
520  (IF.nb_card_gates >1) ? nb_card_gates = IF.nb_card_gates : 1 ;
521 
522  // --- oImageDimensionsAndQuantification initialization ---
523  p_ID->SetNbVoxX(IF.mtx_size[0]);
524  p_ID->SetNbVoxY(IF.mtx_size[1]);
525  p_ID->SetNbVoxZ(IF.mtx_size[2]);
526  p_ID->SetNbThreads(nb_threads);
527  p_ID->SetNbBeds(1);
528  p_ID->SetVoxSizeX(IF.vox_size[0]);
529  p_ID->SetVoxSizeY(IF.vox_size[1]);
530  p_ID->SetVoxSizeZ(IF.vox_size[2]);
531  p_ID->SetFOVOutMasking(0., 0);
532  p_ID->SetFOVSizeX(-1.);
533  p_ID->SetFOVSizeY(-1.);
534  p_ID->SetFOVSizeZ(-1.);
535  p_ID->SetOffsetX(0);
536  p_ID->SetOffsetY(0);
537  p_ID->SetOffsetZ(0);
538  p_ID->SetVerbose(vb);
539  p_ID->SetNbRespGates(nb_resp_gates);
540  p_ID->SetNbCardGates(nb_card_gates);
541  p_ID->SetFrames(frame_list);
542  p_ID->SetnbFramesToSkip(nb_FramesToSkip);
543 
544  if (p_ID->CheckParameters())
545  {
546  Cerr("***** castor-imageDynamicTools :: A problem occurred while checking image dimensions parameters !" << endl);
547  Exit(1);
548  }
549  if (p_ID->Initialize())
550  {
551  Cerr("***** castor-imageDynamicTools :: A problem occurred while initializing image dimensions !" << endl);
552  Exit(1);
553  }
554 
555  // Initialization of DynamicDataManager class, related 4D data splitting management
556  if (p_ID->InitDynamicData( "", 0, 0, 0, 1, 1 ) )
557  {
558  Cerr("***** castor-imageDynamicTools :: A problem occurred while initializing Dynamic data manager's class !" << endl);
559  Exit(EXIT_FAILURE);
560  }
561 
562 
563 
564  // ----------------------------------------------------------------------------------------
565  // Create Dynamic Model Manager
566  // ----------------------------------------------------------------------------------------
567 
568  // Verbose
569  if (vb>=5) Cout("----- Dynamic model initialization (if any) ... -----" << endl);
570  // Create object
571  oDynamicModelManager* p_DynamicModelManager = new oDynamicModelManager();
572  // Set all parameters
573  p_DynamicModelManager->SetImageDimensionsAndQuantification(p_ID);
574  p_DynamicModelManager->SetOptions(dynamic_model_options);
575  p_DynamicModelManager->SetVerbose(vb);
576  // Check parameters
577  if (p_DynamicModelManager->CheckParameters())
578  {
579  Cerr("***** castor-imageDynamicTools() -> A problem occurred while checking dynamic model manager's parameters !" << endl);
580  Exit(EXIT_FAILURE);
581  }
582  // Initialize optimizer manager
583  if (p_DynamicModelManager->Initialize())
584  {
585  Cerr("***** castor-imageDynamicTools() -> A problem occurred while initializing dynamic model manager !" << endl);
586  Exit(EXIT_FAILURE);
587  }
588 
589  // Verbose
590  if (vb>=5) Cout("----- Dynamic model initialization OK -----" << endl);
591 
592 
593  // ----------------------------------------------------------------------------------------
594  // Set Image Space and initialise Image
595  // ----------------------------------------------------------------------------------------
596 
597  // --- Image space initialization ---
598  oImageSpace* p_ImageSpace = new oImageSpace();
599 
600  p_ImageSpace->SetImageDimensionsAndQuantification(p_ID);
601  p_ImageSpace->SetVerbose(vb);
602 
603  // Allocate memory for main image
604  p_ImageSpace->InstantiateImage();
605  p_ImageSpace->InstantiateForwardImage();
607  p_ImageSpace->InstantiateOutputImage();
608  p_ImageSpace->InitImage(path_to_input_image[i], 0);
609 
610 
611  // ----------------------------------------------------------------------------------------
612  // Create Deformation Manager
613  // ----------------------------------------------------------------------------------------
614 
615  // Verbose
616  if (vb>=5) Cout("----- Image deformation initialization (if any) ... -----" << endl);
617 
618  // Create object
619  oDeformationManager* p_DeformationManager = new oDeformationManager();
620  // Set all parameters
621  p_DeformationManager->SetImageDimensionsAndQuantification(p_ID);
622  p_DeformationManager->SetDataMode(0); // required to know if sensitivity image deformation should be enabled
623 
624  if (motion_options != "")
625  {
626  p_DeformationManager->SetOptions(motion_options);
627  p_DeformationManager->SetNbTransformations(1); // 1 for testing
628  p_DeformationManager->SetMotionType(DEF_IPAT_MOT);
629  }
630  else
631  p_DeformationManager->SetNbTransformations(0);
632 
633  p_DeformationManager->SetVerbose(vb);
634  // Check parameters
635  if (p_DeformationManager->CheckParameters())
636  {
637  Cerr("***** castor-recon() -> A problem occurred while checking image deformation manager's parameters !" << endl);
638  Exit(EXIT_FAILURE);
639  }
640  // Initialize optimizer manager
641  if (p_DeformationManager->Initialize())
642  {
643  Cerr("***** castor-recon() -> A problem occurred while initializing image deformation manager !" << endl);
644  Exit(EXIT_FAILURE);
645  }
646  // Verbose
647  if (vb >=5) Cout("----- Image deformation initialization OK -----" << endl);
648 
649  // Initial clock for execution time
650  clock_t clock_start = clock();
651  time_t time_start = time(NULL);
652 
653  // ============================================================================================================
654  // Apply dynamic Model if initialized
655  // ============================================================================================================
656  if(dynamic_model_options != "")
657  {
658  for(uint32_t it=0; it<nb_ite_dyn ; it++)
659  {
660  Cout(" --- Apply Dynamic Model, iteration" << it+1 << " --- " << endl);
661  if (p_DynamicModelManager->ApplyDynamicModel(p_ImageSpace, 0, 0))
662  {
663  Cerr("***** castor-imageDynamicTools -> A problem occurred while applying dynamic model to current estimate images !" << endl);
664  return 1;
665  }
666  }
667 
668  // Save Parametric images
669  if (p_DynamicModelManager->SaveParametricImages(-1))
670  {
671  Cerr("***** castor-imageDynamicTools -> A problem occurred while saving parametric images related to the dynamic model !" << endl);
672  return 1;
673  }
674 
675  if(output_dynamic_imgs_from_model)
676  {
677  p_ImageSpace->ComputeOutputImage();
678 
679  // Save output image
680  if (p_ImageSpace->SaveOutputImage(-1))
681  {
682  Cerr("***** castor-imageDynamicTools -> A problem occurred while saving output image !" << endl);
683  return 1;
684  }
685  }
686 
687  Cout(endl << " --- Parametric images generated at: " << ((path_fout.empty()) ? path_dout : path_fout) << " --- " << endl);
688  }
689 
690  // ============================================================================================================
691  // Test/Apply deformations if initialized
692  // ============================================================================================================
693 
694  if(motion_options != "")
695  {
696  // Apply deformation on input image
697  if (p_DeformationManager->TestDeformationOnImage(p_ImageSpace->m4p_image[0][0][0], p_ImageSpace->m4p_image[0][0][0], FORWARD_DEFORMATION, 0))
698  {
699  Cerr("***** castor-imageDynamicTools -> A problem occurred while applying dynamic model to current estimate images !" << endl);
700  return 1;
701  }
702 
703  p_ImageSpace->ComputeOutputImage();
704 
705  // Save output image
706  if (p_ImageSpace->SaveOutputImage(-1))
707  {
708  Cerr("***** castor-imageDynamicTools -> A problem occurred while saving output image !" << endl);
709  return 1;
710  }
711 
712  Cout(endl << " --- Parametric images generated at: " << ((path_fout.empty()) ? path_dout : path_fout) << " --- " << endl);
713  }
714 
715 
716  // Final clock for execution time
717  clock_t clock_stop = clock();
718  time_t time_stop = time(NULL);
719 
720  // ============================================================================================================
721  // End
722  // ============================================================================================================
723 
724  if (vb>=2) Cout("oIterativeAlgorithm::IterateCPU() -> Total time spent | User: " << (FLTNB)(time_stop-time_start)
725  << " sec | CPU: " << (clock_stop-clock_start)/((FLTNB)CLOCKS_PER_SEC) << " sec" << endl);
726 
727 
728  // ============================================================================================================
729  // End
730  // ============================================================================================================
731 
732  if (vb>=2) Cout(" Deallocating objects ..." << endl);
733 
734  // Delete objects
735  p_ImageSpace->DeallocateOutputImage();
737  p_ImageSpace->DeallocateForwardImage();
738  p_ImageSpace->DeallocateImage();
739 
740  if(p_ImageSpace) delete p_ImageSpace;
741  if(p_ID) delete p_ID;
742 
743  Cout(" --- END --- " << endl << endl);
744 
745  return 0;
746 }
void ShowHelp(int a_returnCode)
#define Cerr(MESSAGE)
#define FORWARD_DEFORMATION
void DeallocateImage()
Free memory for the main image matrices.
int IntfIsMHD(string a_pathToFile, vector< string > &ap_lPathToImgs)
Check if the string in argument contains the path to a Interfile metaheader.
void InstantiateImage()
Allocate memory for the main image matrices.
int main(int argc, char **argv)
void Exit(int code)
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.
int InitImage(const string &a_pathToInitialImage, FLTNB a_value)
int LogCommandLine(int argc, char **argv)
int CheckConfigDir(const string &a_path)
int CheckParameters()
A function used to check the parameters settings.
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...
This class is designed to manage the use of dynamic model in the reconstruction.
int SaveOutputImage(int a_iteration, int a_subset=-1)
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
int SaveParametricImages(int a_iteration, int a_subset=-1)
int InitDynamicData(string a_pathTo4DDataSplittingFile, int a_respMotionCorrectionFlag, int a_cardMotionCorrectionFlag, int a_invMotionCorrectionFlag, int a_nbRespGates, int a_nbCardGates)
void InstantiateForwardImage()
Allocate memory for the forward image matrices.
int CheckParameters()
This function is used to check parameters after the latter have been all set using Set functions...
void IntfKeyInitFields(Intf_fields *ap_IF)
Init the file of an Interfile fields structure passed in parameter to their default values...
int CheckParameters()
This function is used to check parameters after the latter have been all set using Set functions...
void SetFOVOutMasking(FLTNB a_fovOutPercent, INTNB a_nbSliceOutMask)
This class is designed to manage the image-based deformation part of the reconstruction.
void SetOptions(const string &a_options)
void InstantiateBackwardImageFromDynamicBins()
Allocate memory for the backward image matrices and initialize them.
void DeallocateOutputImage()
Free memory for the Image matrices dedicated to output writing on disk.
Interfile fields. This structure contains all the Interfile keys currently managed by CASToR Decl...
void GetUserEndianness()
Check user/host computer endianness and write it to the global variable User_Endianness.
int Initialize()
Set the flags for the different motion types and instanciate/initialize deformation objects through t...
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;.
int TestDeformationOnImage(FLTNB *ap_inputImage, FLTNB *ap_outputImage, int a_direction, int a_defIdx)
This class is designed to manage all dimensions and quantification related stuff. ...
void SetNbTransformations(int a_nbTransformations)
int IntfReadHeader(const string &a_pathToHeaderFile, Intf_fields *ap_IntfFields, int vb)
Read an Interfile header.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
void DeallocateBackwardImageFromDynamicBins()
Free memory of the backward image matrices.
void DeallocateForwardImage()
Free memory for the forward image matrices.
#define Cout(MESSAGE)
int ApplyDynamicModel(oImageSpace *ap_ImageS, int a_iteration, int a_subset)
void SetVerbose(int a_verboseLevel)
void InstantiateOutputImage()
Instanciate Image matrices dedicated to output writing on disk.