CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
code/toolkits/castor-sumImages.cc
Go to the documentation of this file.
1 
8 #include "gVariables.hh"
9 #include "gOptions.hh"
10 #include "sOutputManager.hh"
11 #include "sScannerManager.hh"
12 #include "oInterfileIO.hh"
13 
14 // =============================================================================================================================================
15 // =============================================================================================================================================
16 // =============================================================================================================================================
17 // H E L P F U N C T I O N S
18 // =============================================================================================================================================
19 // =============================================================================================================================================
20 // =============================================================================================================================================
21 
22 
27 void ShowHelp()
28 {
29  // Show help
30  cout << endl;
31  cout << "Usage: castor-sumImages -img image1.hdr -img image2.hdr -(f/d)out output [settings]" << endl;
32  cout << endl;
33  cout << "This program can be used to perform operations on a bunch of images of the same dimensions." << endl;
34  cout << "The sum or average image can be computed." << endl;
35  cout << "The variance or standard-deviation image can be computed (the biased one, i.e. divided by the number of images and not minus one)." << endl;
36  cout << "If a reference image is provided, the bias as well as the root mean square error images can also be computed." << endl;
37  cout << "All operations are performed independently voxel by voxel." << endl;
38  cout << "Important note: this program only works with 3D images (without time dimension)." << endl;
39  cout << endl;
40  cout << "[Mandatory parameters]:" << endl;
41  cout << " -img imageX.hdr : Give an image (must give at least two images)" << endl;
42  cout << " -fout name : Give the root name for all output files (no default, alternative to -dout)" << endl;
43  cout << " -dout name : Give the name of the output directory where all output files will be written (no default, alternative to -fout)" << endl;
44  cout << endl;
45  cout << "[Options]:" << endl;
46  cout << " -sum : Compute the sum image" << endl;
47  cout << " -avg : Compute the average image" << endl;
48  cout << " -var : Compute the variance image" << endl;
49  cout << " -stdv : Compute the standard-deviation image" << endl;
50  cout << " -ref imageRef.hdr : Provide a reference image (needed for bias and rmse options)" << endl;
51  cout << " -bias : Compute the bias image with respect to the provided reference image" << endl;
52  cout << " -mse : Compute the mean square error image with respect to the provided reference image" << endl;
53  cout << " -rmse : Compute the root mean square error image with respect to the provided reference image" << endl;
54  cout << " -norm : Compute normalized values:" << endl;
55  cout << " - with respect to the average for the standard-deviation" << endl;
56  cout << " - with respect to the reference for the bias and root mean square error" << endl;
57  cout << " - other computations are left unchanged" << endl;
58  cout << " -vb value : Give the verbosity level, from 0 (no verbose) to 2 (default: 1)" << endl;
59  cout << " --help,-h,-help : Print out this help page." << endl; // managed by main
60  cout << endl;
61  #ifdef CASTOR_OMP
62  cout << " Compiled with OpenMP (will use as many cores as available)" << endl;
63  #endif
64  #ifdef BUILD_DATE
65  cout << " Build date: " << BUILD_DATE << endl;
66  cout << endl;
67  #endif
68  #ifdef CASTOR_VERSION
69  cout << " This program is part of the CASToR release version " << CASTOR_VERSION << "." << endl;
70  cout << endl;
71  #endif
72 }
73 
74 // =============================================================================================================================================
75 // =============================================================================================================================================
76 // =============================================================================================================================================
77 // M A I N P R O G R A M
78 // =============================================================================================================================================
79 // =============================================================================================================================================
80 // =============================================================================================================================================
81 
82 int main(int argc, char** argv)
83 {
84  // ============================================================================================================
85  // MPI stuff (we make all instances but the first one returning 0 directly)
86  // ============================================================================================================
87  int mpi_rank = 0;
88  #ifdef CASTOR_MPI
89  int mpi_size = 1;
90  MPI_Init(&argc, &argv);
91  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
92  MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
93  if (mpi_rank!=0) return 0;
94  #endif
95 
96  // No argument, then show help
97  if (argc==1)
98  {
99  ShowHelp();
100  Exit(EXIT_SUCCESS);
101  }
102 
103  // ============================================================================================================
104  // Parameterized variables with their default values
105  // ============================================================================================================
106 
107  // --------------------------------------------------------------------------------
108  // Input settings
109  // --------------------------------------------------------------------------------
110 
111  // Number of images
112  uint32_t nb_images = 0;
113  // Vector containing string pointing to the images filenames
114  vector<string> path_to_image_filename;
115  // String to the reference image filename
116  string path_to_reference_image_filename = "";
117 
118  // --------------------------------------------------------------------------------
119  // Output settings
120  // --------------------------------------------------------------------------------
121 
122  // Output directory name.
123  string path_dout = "";
124  // Or root name
125  string path_fout = "";
126 
127  // --------------------------------------------------------------------------------
128  // Miscellaneous settings
129  // --------------------------------------------------------------------------------
130 
131  // Compute the sum
132  bool flag_sum = false;
133  // Compute the average
134  bool flag_mean = false;
135  // Compute the standard-deviation
136  bool flag_stdv = false;
137  // Compute the variance
138  bool flag_var = false;
139  // Compute the bias
140  bool flag_bias = false;
141  // Compute the mean square error
142  bool flag_mse = false;
143  // Compute the root mean square error
144  bool flag_rmse = false;
145  // Compute normalized values
146  bool flag_norm = false;
147  // Verbose level
148  int verbose = 1;
149 
150  // ============================================================================================================
151  // Read command-line parameters
152  // ============================================================================================================
153 
154  // Must manually increment the option index when an argument is needed after an option
155  for (int i=1; i<argc; i++)
156  {
157  // Get the option as a string
158  string option = (string)argv[i];
159 
160  // --------------------------------------------------------------------------------
161  // Miscellaneous settings
162  // --------------------------------------------------------------------------------
163 
164  // Show help
165  if (option=="-h" || option=="--help" || option=="-help")
166  {
167  ShowHelp();
168  Exit(EXIT_SUCCESS);
169  }
170  // General verbosity level
171  else if (option=="-vb")
172  {
173  if (i>=argc-1)
174  {
175  Cerr("***** castor-sumImages() -> Argument missing for option: " << option << endl);
176  Exit(EXIT_FAILURE);
177  }
178  if (ConvertFromString(argv[i+1], &verbose))
179  {
180  Cerr("***** castor-sumImages() -> Exception when trying to read provided verbosity level '" << verbose << " for option: " << option << endl);
181  Exit(EXIT_FAILURE);
182  }
183  i++;
184  }
185  // Sum option
186  else if (option=="-sum") flag_sum = true;
187  // Average option
188  else if (option=="-avg") flag_mean = true;
189  // Variance option
190  else if (option=="-var") flag_var = true;
191  // Standard deviation option
192  else if (option=="-stdv") flag_stdv = true;
193  // Bias option
194  else if (option=="-bias") flag_bias = true;
195  // Mean square error option
196  else if (option=="-mse") flag_mse = true;
197  // Root mean square error option
198  else if (option=="-rmse") flag_rmse = true;
199  // Normalized values option
200  else if (option=="-norm") flag_norm = true;
201 
202  // --------------------------------------------------------------------------------
203  // Input settings
204  // --------------------------------------------------------------------------------
205 
206  // Images
207  else if (option=="-img") // This is a mandatory option
208  {
209  if (i>=argc-1)
210  {
211  Cerr("***** castor-sumImages() -> Argument missing for option: " << option << endl);
212  Exit(EXIT_FAILURE);
213  }
214  string file_name = (string)argv[i+1];
215  path_to_image_filename.push_back(file_name);
216  nb_images++;
217  i++;
218  }
219  // Reference image
220  else if (option=="-ref")
221  {
222  if (i>=argc-1)
223  {
224  Cerr("***** castor-sumImages() -> Argument missing for option: " << option << endl);
225  Exit(EXIT_FAILURE);
226  }
227  path_to_reference_image_filename = (string)argv[i+1];
228  i++;
229  }
230 
231  // --------------------------------------------------------------------------------
232  // Output settings
233  // --------------------------------------------------------------------------------
234 
235  // Name of the output directory
236  else if (option=="-dout") // This is a mandatory option
237  {
238  if (i>=argc-1)
239  {
240  Cerr("***** castor-sumImages() -> Argument missing for option: " << option << endl);
241  Exit(EXIT_FAILURE);
242  }
243  path_dout = argv[i+1];
244  i++;
245  }
246  // Base name of the output files
247  else if (option=="-fout") // This is a mandatory option
248  {
249  if (i>=argc-1)
250  {
251  Cerr("***** castor-sumImages() -> Argument missing for option: " << option << endl);
252  Exit(EXIT_FAILURE);
253  }
254  path_fout = argv[i+1];
255  i++;
256  }
257 
258  // --------------------------------------------------------------------------------
259  // Unknown option!
260  // --------------------------------------------------------------------------------
261 
262  else
263  {
264  Cerr("***** castor-sumImages() -> Unknown option '" << option << "' !" << endl);
265  Exit(EXIT_FAILURE);
266  }
267  }
268 
269  // ============================================================================================================
270  // Some checks
271  // ============================================================================================================
272 
273  // Number of images
274  if (nb_images < 2)
275  {
276  Cerr("***** castor-sumImages() -> Please provide at least two image filenames !" << endl);
277  Exit(EXIT_FAILURE);
278  }
279  // Output files
280  if (path_fout.empty() && path_dout.empty())
281  {
282  Cerr("***** castor-sumImages() -> Please provide an output option for output files (-fout or -dout) !" << endl);
283  Exit(EXIT_FAILURE);
284  }
285  // Check that only one option has been provided
286  if (!path_fout.empty() && !path_dout.empty())
287  {
288  Cerr("***** castor-sumImages() -> Please provide either output option -fout or -dout but not both !" << endl);
289  Exit(EXIT_FAILURE);
290  }
291  // Check that a reference image is provided if bias, mse or rmse is required
292  if (path_to_reference_image_filename=="" && (flag_bias || flag_rmse || flag_mse))
293  {
294  Cerr("***** castor-sumImages() -> Please provide a reference image for bias or (root) mean square error computation !" << endl);
295  Exit(EXIT_FAILURE);
296  }
297 
298  // ============================================================================================================
299  // Set maximum number of threads if compiled with OpenMP
300  // ============================================================================================================
301 
302  #ifdef CASTOR_OMP
303  omp_set_num_threads(omp_get_max_threads());
304  #endif
305 
306  // ============================================================================================================
307  // Create sOutputManager
308  // ============================================================================================================
309  sOutputManager* p_OutputManager = sOutputManager::GetInstance();
310  // Set verbose level
311  p_OutputManager->SetVerbose(verbose);
312  // Set MPI rank
313  p_OutputManager->SetMPIRank(mpi_rank);
314  // Initialize output directory and base name
315  if (p_OutputManager->InitOutputDirectory(path_fout, path_dout))
316  {
317  Cerr("***** castor-sumImages() -> A problem occurred while initializing output directory !" << endl);
318  Exit(EXIT_FAILURE);
319  }
320  // Log command line
321  if (p_OutputManager->LogCommandLine(argc,argv))
322  {
323  Cerr("***** castor-sumImages() -> A problem occurred while logging command line arguments !" << endl);
324  Exit(EXIT_FAILURE);
325  }
326 
327  // ============================================================================================================
328  // Read all input images
329  // ============================================================================================================
330 
331  // Verbose
332  if (verbose>=VERBOSE_LIGHT) Cout("castor-sumImages() -> Load input images" << endl);
333 
334  // Get user endianness (interfile I/O)
336 
337  // Create interfile image fields and image pointers
338  Intf_fields** p_image_fields = (Intf_fields**)malloc(nb_images*sizeof(Intf_fields*));
339  FLTNB** p_images = (FLTNB**)malloc(nb_images*sizeof(FLTNB*));
340 
341  // Read interfile images
342  for (uint32_t img=0; img<nb_images; img++)
343  {
344  // Create the image fields
345  p_image_fields[img] = new Intf_fields;
346  // Read the image
347  p_images[img] = IntfLoadImageFromScratch(path_to_image_filename[img],p_image_fields[img],verbose);
348  // Check reading
349  if (p_images[img]==NULL)
350  {
351  Cerr("***** castor-sumImages() -> A problem occurred while reading image number " << img+1 << " !" << endl);
352  return 1;
353  }
354  }
355 
356  // Check dimensions consistency between all image fields
357  for (uint32_t img=1; img<nb_images; img++)
358  {
359  if (IntfCheckDimensionsConsistency(*p_image_fields[0],*p_image_fields[img]))
360  {
361  Cerr("***** castor-sumImages() -> Inconsistency between image dimensions !" << endl);
362  Exit(EXIT_FAILURE);
363  }
364  }
365 
366  // Verbose
367  if (verbose>=VERBOSE_NORMAL)
368  {
369  Cout(" --> Image dimensions: [ " << p_image_fields[0]->mtx_size[0] << " : "
370  << p_image_fields[0]->mtx_size[1] << " : "
371  << p_image_fields[0]->mtx_size[2] << " ]" << endl);
372  Cout(" --> Voxel sizes: [ " << p_image_fields[0]->vox_size[0] << " : "
373  << p_image_fields[0]->vox_size[1] << " : "
374  << p_image_fields[0]->vox_size[2] << " ]" << endl);
375  }
376 
377  // Get dimensions locally
378  uint32_t dim_x = p_image_fields[0]->mtx_size[0];
379  uint32_t dim_y = p_image_fields[0]->mtx_size[1];
380  uint32_t dim_z = p_image_fields[0]->mtx_size[2];
381  uint32_t dim_xyz = dim_x * dim_y * dim_z;
382 
383  // ============================================================================================================
384  // If a reference image is provided, then load it
385  // ============================================================================================================
386 
387  // Create the reference image matrix
388  FLTNB* p_reference = NULL;
389 
390  // If we have a reference
391  if (path_to_reference_image_filename!="")
392  {
393  // Verbose
394  if (verbose>=1) Cout("castor-sumImages() -> Load reference image" << endl);
395  // Create interfile image fields and image pointers for sensitivity
396  Intf_fields* p_reference_fields = new Intf_fields;
397  // Read the image
398  p_reference = IntfLoadImageFromScratch(path_to_reference_image_filename,p_reference_fields,verbose);
399  // Check reading
400  if (p_reference==NULL)
401  {
402  Cerr("***** castor-sumImages() -> A problem occurred while reading reference image !" << endl);
403  return 1;
404  }
405  // Check dimensions consistency between input images and reference image
406  if (IntfCheckDimensionsConsistency(*p_image_fields[0],*p_reference_fields))
407  {
408  Cerr("***** castor-sumImages() -> Inconsistency between input images and reference image !" << endl);
409  Exit(EXIT_FAILURE);
410  }
411  }
412 
413  // ============================================================================================================
414  // Images allocations
415  // ============================================================================================================
416 
417  // Usefull images
418  FLTNB* p_mean = NULL;
419  FLTNB* p_misc = NULL;
420 
421  // The mean image is mandatory in all cases expect for (r)mse
422  if (flag_sum || flag_mean || flag_bias || flag_stdv || flag_var)
423  p_mean = (FLTNB*)malloc(dim_xyz*sizeof(FLTNB));
424 
425  // The miscellaneous image is used for all other cases than sum/mean
426  if (flag_bias || flag_mse || flag_rmse || flag_stdv || flag_var)
427  p_misc = (FLTNB*)malloc(dim_xyz*sizeof(FLTNB));
428 
429  // ============================================================================================================
430  // Compute the sum/mean image
431  // ============================================================================================================
432 
433  // The mean image is computed in all cases expect for rmse
434  if (flag_sum || flag_mean || flag_bias || flag_stdv || flag_var)
435  {
436  // Verbose
437  if (verbose>=1) Cout("castor-sumImages() -> Compute sum/average image" << endl);
438  // Reset the image
439  for (uint32_t v=0; v<dim_xyz; v++) p_mean[v] = 0.;
440  // Loop on all voxels
441  uint32_t v;
442  #pragma omp parallel for private(v) schedule(guided)
443  for (v=0; v<dim_xyz; v++)
444  {
445  // High precision computation
446  HPFLTNB sum = 0.;
447  // Loop on all images
448  for (uint32_t img=0; img<nb_images; img++)
449  {
450  // Add the contribution of this image to the sum image
451  sum += ((HPFLTNB)(p_images[img][v]));
452  }
453  // Affect the value
454  p_mean[v] = sum;
455  }
456  // Save sum image if required
457  if (flag_sum)
458  {
459  // Verbose
460  if (verbose>=1) Cout("castor-sumImages() -> Write sum image" << endl);
461  // File name
462  string sum_image_filename = p_OutputManager->GetPathName() + p_OutputManager->GetBaseName() + "_sum";
463  // Write the image
464  if (IntfWriteImageFromIntfFields(sum_image_filename, p_mean, *p_image_fields[0], verbose))
465  {
466  Cerr("***** castor-sumImages() -> A problem occurred while writing sum image !" << endl);
467  Exit(EXIT_FAILURE);
468  }
469  }
470  // Transform the sum image into the mean image
471  #pragma omp parallel for private(v) schedule(guided)
472  for (v=0; v<dim_xyz; v++)
473  {
474  p_mean[v] /= ((FLTNB)nb_images);
475  }
476  // Save mean image if required
477  if (flag_mean)
478  {
479  // Verbose
480  if (verbose>=1) Cout("castor-sumImages() -> Write average image" << endl);
481  // File name
482  string mean_image_filename = p_OutputManager->GetPathName() + p_OutputManager->GetBaseName() + "_avg";
483  // Write the image
484  if (IntfWriteImageFromIntfFields(mean_image_filename, p_mean, *p_image_fields[0], verbose))
485  {
486  Cerr("***** castor-sumImages() -> A problem occurred while writing average image !" << endl);
487  Exit(EXIT_FAILURE);
488  }
489  }
490  }
491 
492  // ============================================================================================================
493  // Compute the variance/standard-deviation image
494  // ============================================================================================================
495 
496  if (flag_var || flag_stdv)
497  {
498  // Verbose
499  if (verbose>=1) Cout("castor-sumImages() -> Compute variance image" << endl);
500  // Reset the image
501  for (uint32_t v=0; v<dim_xyz; v++) p_misc[v] = 0.;
502  // Loop on all voxels
503  uint32_t v;
504  #pragma omp parallel for private(v) schedule(guided)
505  for (v=0; v<dim_xyz; v++)
506  {
507  // High precision computation
508  HPFLTNB sum_square = 0.;
509  // Loop on all images
510  for (uint32_t img=0; img<nb_images; img++)
511  {
512  // Add the contribution of this image to the variance image
513  HPFLTNB diff = ((HPFLTNB)(p_images[img][v])) - ((HPFLTNB)(p_mean[v]));
514  sum_square += diff * diff;
515  }
516  // Divide by the number of images
517  p_misc[v] = (sum_square / ((HPFLTNB)nb_images));
518  }
519  // Save variance image if required
520  if (flag_var)
521  {
522  // Verbose
523  if (verbose>=1) Cout("castor-sumImages() -> Write variance image" << endl);
524  // File name
525  string var_image_filename = p_OutputManager->GetPathName() + p_OutputManager->GetBaseName() + "_var";
526  // Write the image
527  if (IntfWriteImageFromIntfFields(var_image_filename, p_misc, *p_image_fields[0], verbose))
528  {
529  Cerr("***** castor-sumImages() -> A problem occurred while writing variance image !" << endl);
530  Exit(EXIT_FAILURE);
531  }
532  }
533  // Compute standard deviation if required
534  if (flag_stdv)
535  {
536  // Verbose
537  if (verbose>=1)
538  {
539  if (flag_norm) Cout("castor-sumImages() -> Compute normalized standard-deviation image" << endl);
540  else Cout("castor-sumImages() -> Compute standard-deviation image" << endl);
541  }
542  // Loop on all voxels
543  #pragma omp parallel for private(v) schedule(guided)
544  for (v=0; v<dim_xyz; v++)
545  {
546  // Apply square root
547  p_misc[v] = sqrt(p_misc[v]);
548  // Normalize if required
549  if (flag_norm) p_misc[v] /= p_mean[v];
550  }
551  // Verbose
552  if (verbose>=1) Cout("castor-sumImages() -> Write standard deviation image" << endl);
553  // File name
554  string stdv_image_filename = p_OutputManager->GetPathName() + p_OutputManager->GetBaseName() + "_stdv";
555  // Write the image
556  if (IntfWriteImageFromIntfFields(stdv_image_filename, p_misc, *p_image_fields[0], verbose))
557  {
558  Cerr("***** castor-sumImages() -> A problem occurred while writing standard deviation image !" << endl);
559  Exit(EXIT_FAILURE);
560  }
561  }
562  }
563 
564  // ============================================================================================================
565  // Compute the bias image
566  // ============================================================================================================
567 
568  if (flag_bias)
569  {
570  // Verbose
571  if (verbose>=1)
572  {
573  if (flag_norm) Cout("castor-sumImages() -> Compute normalized bias image" << endl);
574  else Cout("castor-sumImages() -> Compute bias image" << endl);
575  }
576  // Reset the image
577  for (uint32_t v=0; v<dim_xyz; v++) p_misc[v] = 0.;
578  // Loop on all voxels
579  uint32_t v;
580  #pragma omp parallel for private(v) schedule(guided)
581  for (v=0; v<dim_xyz; v++)
582  {
583  // Simply the mean minus the reference
584  p_misc[v] = p_mean[v] - p_reference[v];
585  // Normalize if required
586  if (flag_norm) p_misc[v] /= p_reference[v];
587  }
588  // Verbose
589  if (verbose>=1) Cout("castor-sumImages() -> Write bias image" << endl);
590  // File name
591  string bias_image_filename = p_OutputManager->GetPathName() + p_OutputManager->GetBaseName() + "_bias";
592  // Write the image
593  if (IntfWriteImageFromIntfFields(bias_image_filename, p_misc, *p_image_fields[0], verbose))
594  {
595  Cerr("***** castor-sumImages() -> A problem occurred while writing bias image !" << endl);
596  Exit(EXIT_FAILURE);
597  }
598  }
599 
600  // ============================================================================================================
601  // Compute the (R)MSE image
602  // ============================================================================================================
603 
604  if (flag_rmse || flag_mse)
605  {
606  // Verbose
607  if (verbose>=1) Cout("castor-sumImages() -> Compute mean square error image" << endl);
608  // Reset the image
609  for (uint32_t v=0; v<dim_xyz; v++) p_misc[v] = 0.;
610  // Loop on all voxels
611  uint32_t v;
612  #pragma omp parallel for private(v) schedule(guided)
613  for (v=0; v<dim_xyz; v++)
614  {
615  // High precision computation
616  HPFLTNB sum_square = 0.;
617  // Loop on all images
618  for (uint32_t img=0; img<nb_images; img++)
619  {
620  // Add the contribution of this image to the rmse image
621  HPFLTNB diff = ((HPFLTNB)(p_images[img][v])) - ((HPFLTNB)(p_reference[v]));
622  sum_square += diff * diff;
623  }
624  // Divide by the number of images
625  p_misc[v] = (sum_square / ((HPFLTNB)nb_images));
626  }
627  // Write MSE if required
628  if (flag_mse)
629  {
630  // Verbose
631  if (verbose>=1) Cout("castor-sumImages() -> Write mean square error image" << endl);
632  // File name
633  string mse_image_filename = p_OutputManager->GetPathName() + p_OutputManager->GetBaseName() + "_mse";
634  // Write the image
635  if (IntfWriteImageFromIntfFields(mse_image_filename, p_misc, *p_image_fields[0], verbose))
636  {
637  Cerr("***** castor-sumImages() -> A problem occurred while writing mean square error image !" << endl);
638  Exit(EXIT_FAILURE);
639  }
640  }
641  // Compute RMSE if required
642  if (flag_rmse)
643  {
644  // Verbose
645  if (verbose>=1)
646  {
647  if (flag_norm) Cout("castor-sumImages() -> Compute normalized root mean square error image" << endl);
648  else Cout("castor-sumImages() -> Compute root mean square error image" << endl);
649  }
650  // Loop on all voxels
651  #pragma omp parallel for private(v) schedule(guided)
652  for (v=0; v<dim_xyz; v++)
653  {
654  // Apply square root
655  p_misc[v] = sqrt(p_misc[v]);
656  // Normalize if required
657  if (flag_norm) p_misc[v] /= p_reference[v];
658  }
659  // Verbose
660  if (verbose>=1) Cout("castor-sumImages() -> Write root mean square error image" << endl);
661  // File name
662  string rmse_image_filename = p_OutputManager->GetPathName() + p_OutputManager->GetBaseName() + "_rmse";
663  // Write the image
664  if (IntfWriteImageFromIntfFields(rmse_image_filename, p_misc, *p_image_fields[0], verbose))
665  {
666  Cerr("***** castor-sumImages() -> A problem occurred while writing root mean square error image !" << endl);
667  Exit(EXIT_FAILURE);
668  }
669  }
670  }
671 
672  // ============================================================================================================
673  // Free memory properly
674  // ============================================================================================================
675 
676  // Input images
677  if (p_images)
678  {
679  for (uint32_t img=0; img<nb_images; img++) if (p_images[img]) free(p_images[img]);
680  free(p_images);
681  }
682  // Reference image
683  if (p_reference) free(p_reference);
684  // Mean image
685  if (p_mean) free(p_mean);
686  // Miscellaneous image
687  if (p_misc) free(p_misc);
688 
689  // Ending
690  #ifdef CASTOR_MPI
691  MPI_Finalize();
692  #endif
693  return EXIT_SUCCESS;
694 }
#define Cerr(MESSAGE)
void Exit(int code)
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
int LogCommandLine(int argc, char **argv)
int IntfWriteImageFromIntfFields(const string &a_pathToImg, FLTNB *ap_ImgMatrix, Intf_fields Img_fields, int vb)
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
int IntfCheckDimensionsConsistency(Intf_fields ImgFields1, Intf_fields ImgFields2)
Interfile fields. This structure contains all the Interfile keys currently managed by CASToR Decl...
int main(int argc, char **argv)
void GetUserEndianness()
Check user/host computer endianness and write it to the global variable User_Endianness.
FLTNB * IntfLoadImageFromScratch(const string &a_pathToHeaderFile, Intf_fields *ap_ImgFields, int vb)
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;.
#define Cout(MESSAGE)