CASToR  3.0
Tomographic Reconstruction (PET/SPECT/CT)
vAlgorithm.cc
Go to the documentation of this file.
1 /*
2 This file is part of CASToR.
3 
4  CASToR is free software: you can redistribute it and/or modify it under the
5  terms of the GNU General Public License as published by the Free Software
6  Foundation, either version 3 of the License, or (at your option) any later
7  version.
8 
9  CASToR is distributed in the hope that it will be useful, but WITHOUT ANY
10  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  details.
13 
14  You should have received a copy of the GNU General Public License along with
15  CASToR (in file GNU_GPL.TXT). If not, see <http://www.gnu.org/licenses/>.
16 
17 Copyright 2017-2019 all CASToR contributors listed below:
18 
19  --> Didier BENOIT, Claude COMTAT, Marina FILIPOVIC, Thibaut MERLIN, Mael MILLARDET, Simon STUTE, Valentin VIELZEUF
20 
21 This is CASToR version 3.0.
22 */
23 
30 #include "gVariables.hh"
31 #include "vAlgorithm.hh"
32 #include "iEventHistoCT.hh"
33 
34 // =====================================================================
35 // ---------------------------------------------------------------------
36 // ---------------------------------------------------------------------
37 // =====================================================================
38 
40 {
41  // Default number of iterations and subsets (1 for each)
42  m_nbIterations = 1;
43  mp_nbSubsets = (int*)malloc(1*sizeof(int));
44  mp_nbSubsets[0] = 1;
45  mp_outputIterations = NULL;
46  // set all members to default values
47  m_verbose = -1;
48  m_flagGPU = false;
49  mp_ID = NULL;
50  m2p_DataFile= NULL;
51  mp_ProjectorManager = NULL;
52  mp_OptimizerManager = NULL;
53  mp_DeformationManager = NULL;
55  mp_ImageSpace = NULL;
58  m_nbBeds = -1;
59  m_pathToInitialImg = "";
61  m_pathToMaskImg = "";
65 
66 }
67 
68 // =====================================================================
69 // ---------------------------------------------------------------------
70 // ---------------------------------------------------------------------
71 // =====================================================================
72 
74 {
75  // Delete some tables
76  if (mp_nbSubsets!=NULL) free(mp_nbSubsets);
78 }
79 
80 // =====================================================================
81 // ---------------------------------------------------------------------
82 // ---------------------------------------------------------------------
83 // =====================================================================
84 
85 int vAlgorithm::SetNbIterationsAndSubsets(const string& a_nbIterationsSubsets)
86 {
87  // If the string is empty, then just keep the defaults
88  if (a_nbIterationsSubsets=="") return 0;
89  // Otherwise, reset the number of iterations to 0
90  m_nbIterations = 0;
91 
92  // Copy the string
93  string buf = a_nbIterationsSubsets;
94 
95  // Loop to search for commas
96  size_t pos_comma;
97  while ((pos_comma=buf.find_first_of(","))!=string::npos)
98  {
99  // Get the substring before the comma
100  string sub_buf = buf.substr(0,pos_comma);
101  // Search for columns
102  size_t pos_column = sub_buf.find_first_of(":");
103  if (pos_column==string::npos || pos_column==0)
104  {
105  Cerr("***** vAlgorithm::SetNbIterationsAndSubsets() -> Syntax problem in number of iterations and subsets !" << endl);
106  return 1;
107  }
108  int iter = atoi( sub_buf.substr(0,pos_column).c_str() );
109  int subs = atoi( sub_buf.substr(pos_column+1).c_str() );
110  mp_nbSubsets = (int*)realloc(mp_nbSubsets,(m_nbIterations+iter)*sizeof(int));
111  for (int it=0; it<iter; it++) mp_nbSubsets[m_nbIterations+it] = subs;
112  m_nbIterations += iter;
113  buf = buf.substr(pos_comma+1);
114  }
115 
116  // Last couple of iterations:subsets
117  size_t pos_column = buf.find_first_of(":");
118  if (pos_column==string::npos || pos_column==0)
119  {
120  Cerr("***** vAlgorithm::SetNbIterationsAndSubsets() -> Syntax problem in number of iterations and subsets !" << endl);
121  return 1;
122  }
123  int iter = atoi( buf.substr(0,pos_column).c_str() );
124  int subs = atoi( buf.substr(pos_column+1).c_str() );
125  mp_nbSubsets = (int*)realloc(mp_nbSubsets,(m_nbIterations+iter)*sizeof(int));
126  for (int it=0; it<iter; it++) mp_nbSubsets[m_nbIterations+it] = subs;
127  m_nbIterations += iter;
128 
129  if (m_verbose>=3)
130  {
131  Cout("vAlgorithm::SetNbIterationsAndSubsets() -> Selected numbers of subsets for each iteration:" << endl);
132  Cout(" Iteration / number of subsets "<< endl);
133  for (int it=0 ; it<m_nbIterations ; it++) Cout(" " << it+1 << " / " << mp_nbSubsets[it] << endl);
134  }
135  // End
136  return 0;
137 }
138 
139 // =====================================================================
140 // ---------------------------------------------------------------------
141 // ---------------------------------------------------------------------
142 // =====================================================================
143 
144 int vAlgorithm::SetOutputIterations(const string& a_outputIterations)
145 {
146  if (m_verbose>=2) Cout("vAlgorithm::SetOutputIterations ..." << endl);
147 
148  // Allocate the output iterations boolean table
149  mp_outputIterations = (bool*)malloc(m_nbIterations*sizeof(bool));
150  for (int it=0; it<m_nbIterations; it++) mp_outputIterations[it] = false;
151 
152  // If the list is empty, we save all iterations by default
153  if (a_outputIterations=="")
154  {
155  for (int it=0; it<m_nbIterations; it++) mp_outputIterations[it] = true;
156  return 0;
157  }
158 
159  // Copy the string
160  string buf = a_outputIterations;
161 
162  // Loop to search for commas
163  size_t pos_comma;
164  int current_iteration = -1;
165  while ((pos_comma=buf.find_first_of(","))!=string::npos)
166  {
167  // Get the substring before the comma
168  string sub_buf = buf.substr(0,pos_comma);
169  // Search for columns
170  size_t pos_column = sub_buf.find_first_of(":");
171  if (pos_column==string::npos || pos_column==0)
172  {
173  Cerr("***** vAlgorithm::SetOutputIterations() -> Syntax problem in output iteration numbers !" << endl);
174  return 1;
175  }
176  int step_iteration = atoi( sub_buf.substr(0,pos_column).c_str() );
177  if (step_iteration<=0)
178  {
179  Cerr("***** vAlgorithm::SetOutputIterations() -> Iteration step must be strictly positive (here it is " << step_iteration << ") !" << endl);
180  return 1;
181  }
182  int stop_iteration = atoi( sub_buf.substr(pos_column+1).c_str() );
183  if (stop_iteration<=current_iteration)
184  {
185  Cerr("***** oIterationAlgorithm::SetOutputIterations() -> Output iteration number must be increasing through provided couples !" << endl);
186  return 1;
187  }
188  for (int it=current_iteration+step_iteration; it<stop_iteration; it+=step_iteration) if (it<m_nbIterations) mp_outputIterations[it] = true;
189  current_iteration = stop_iteration-1;
190  buf = buf.substr(pos_comma+1);
191  }
192 
193  // Last couple of iterations:subsets
194  size_t pos_column = buf.find_first_of(":");
195  if (pos_column==string::npos || pos_column==0)
196  {
197  // Special case if -1 is provided, it means we save the last iteration
198  if (buf=="-1")
199  {
200  mp_outputIterations[m_nbIterations-1] = true;
201  // We directly exist here
202  return 0;
203  }
204  else
205  {
206  Cerr("***** vAlgorithm::SetOutputIterations() -> Syntax problem in output iteration numbers !" << endl);
207  return 1;
208  }
209  }
210  int step_iteration = atoi( buf.substr(0,pos_column).c_str() );
211  if (step_iteration<=0)
212  {
213  Cerr("***** vAlgorithm::SetOutputIterations() -> Iteration step must be strictly positive (here it is " << step_iteration << ") !" << endl);
214  return 1;
215  }
216  int stop_iteration = atoi( buf.substr(pos_column+1).c_str() );
217  if (stop_iteration<=current_iteration)
218  {
219  Cerr("***** oIterationAlgorithm::SetOutputIterations() -> Output iteration number must be increasing through provided couples !" << endl);
220  return 1;
221  }
222  for (int it=current_iteration+step_iteration; it<stop_iteration; it+=step_iteration) if (it<m_nbIterations) mp_outputIterations[it] = true;
223 
224  // End
225  return 0;
226 }
227 
228 // =====================================================================
229 // ---------------------------------------------------------------------
230 // ---------------------------------------------------------------------
231 // =====================================================================
232 
234 {
235  if(m_verbose>=2) Cout("vAlgorithm::Iterate ..."<< endl);
236 
237  #ifdef CASTOR_GPU
238  if (m_flagGPU)
239  return RunGPU();
240  else
241  return RunCPU();
242  #else
243  return RunCPU();
244  #endif
245 }
246 
247 // =====================================================================
248 // ---------------------------------------------------------------------
249 // ---------------------------------------------------------------------
250 // =====================================================================
251 
253 {
254 // Here is the scheme of all functions call related to each step of the iterative reconstruction:
255 // StepBeforeIterationLoop()
256 // / Loop on iterations
257 // | StepBeforeSubsetLoop(iteration)
258 // | / Loop on subsets
259 // | | StepPreProcessInsideSubsetLoop(iteration,subset)
260 // | | / Loop on bed positions
261 // | | | StepInnerLoopInsideSubsetLoop(iteration,subset,bed)
262 // | | StepPostProcessInsideSubsetLoop(iteration,subset)
263 // | StepAfterSubsetLoop(iteration)
264 // StepAfterIterationLoop()
265 
266  // Synchronize MPI processes
267  #ifdef CASTOR_MPI
268  MPI_Barrier(MPI_COMM_WORLD);
269  #endif
270 
271  // Verbose
272  if (m_verbose>=1) Cout("vAlgorithm::IterateCPU() -> Start algorithm for " << m_nbIterations << " iterations" << endl);
273 
274  // Initial clock for execution time
275  clock_t clock_start_whole = clock();
276  time_t time_start_whole = time(NULL);
277 
278  // Call before iteration function
279  // Call before iteration function
281  {
282  Cerr("***** vAlgorithm::IterateCPU() -> A problem occurred while calling StepBeforeIterationLoop() function !" << endl);
283  return 1;
284  }
285 
286  // Loop on iterations
287  for (int iteration=0 ; iteration<m_nbIterations ; iteration++)
288  {
289 
290  // Call before subset function
291  if (StepBeforeSubsetLoop(iteration))
292  {
293  Cerr("***** vAlgorithm::IterateCPU() -> A problem occurred while calling StepBeforeSubsetLoop() function !" << endl);
294  return 1;
295  }
296 
297  // Loop on subsets
298  for (int subset=0 ; subset<mp_nbSubsets[iteration] ; subset++)
299  {
300  // Verbose
301  if (m_verbose>=1)
302  {
303  Cout("vAlgorithm::IterateCPU() -> Start iteration " << iteration+1 << "/" << m_nbIterations
304  << " subset " << subset+1 << "/" << mp_nbSubsets[iteration] << endl);
305  }
306 
307  // Clock start for subset execution time
308  clock_t clock_start_subset = clock();
309  time_t time_start_subset = time(NULL);
310 
311  // Call pre-process inside subset loop function
312  if (StepPreProcessInsideSubsetLoop(iteration,subset))
313  {
314  Cerr("***** vAlgorithm::IterateCPU() -> A problem occurred while calling StepPreProcessInsideSubsetLoop() function !" << endl);
315  return 1;
316  }
317 
318  // Synchronize MPI processes
319  #ifdef CASTOR_MPI
320  MPI_Barrier(MPI_COMM_WORLD);
321  #endif
322 
323  // Loop on bed positions
324  for (int bed=0 ; bed<m_nbBeds ; bed++)
325  {
326  // Call the inner loop on events inside subset loop function
327  if (StepInnerLoopInsideSubsetLoop(iteration,subset,bed))
328  {
329  Cerr("***** vAlgorithm::IterateCPU() -> A problem occurred while calling StepInnerLoopInsideSubsetLoop() function !" << endl);
330  return 1;
331  }
332  } // End of beds loop
333 
334  // Synchronize MPI processes
335  #ifdef CASTOR_MPI
336  MPI_Barrier(MPI_COMM_WORLD);
337  #endif
338 
339  // Call post-process inside subset loop function
340  if (StepPostProcessInsideSubsetLoop(iteration,subset))
341  {
342  Cerr("***** vAlgorithm::IterateCPU() -> A problem occurred while calling StepPostProcessInsideSubsetLoop() function !" << endl);
343  return 1;
344  }
345 
346  // Clock stop for subset execution time
347  clock_t clock_stop_subset = clock();
348  time_t time_stop_subset = time(NULL);
349  if (m_verbose>=2) Cout ("vAlgorithm::IterateCPU() -> Time spent for subset " << subset+1 << " | User: " << time_stop_subset-time_start_subset
350  << " sec | CPU: " << (clock_stop_subset-clock_start_subset)/((FLTNB)CLOCKS_PER_SEC) << " sec" << endl);
351 
352 
353  } // End of subsets loop
354 
355 
356  // Call after subset function
357  if (StepAfterSubsetLoop(iteration))
358  {
359  Cerr("***** vAlgorithm::IterateCPU() -> A problem occurred while calling StepAfterSubsetLoop() function !" << endl);
360  return 1;
361  }
362 
363 
364  } // End of iterations loop
365 
366  // Call after iteration function
368  {
369  Cerr("***** vAlgorithm::IterateCPU() -> A problem occurred while calling StepAfterIterationLoop() function !" << endl);
370  return 1;
371  }
372 
373  // Final clock for execution time
374  clock_t clock_stop_whole = clock();
375  time_t time_stop_whole = time(NULL);
376  if (m_verbose>=1) Cout("vAlgorithm::IterateCPU() -> Total time spent | User: " << time_stop_whole-time_start_whole
377  << " sec | CPU: " << (clock_stop_whole-clock_start_whole)/((FLTNB)CLOCKS_PER_SEC) << " sec" << endl);
378 
379 
380  return 0;
381 }
382 
383 // =====================================================================
384 // ---------------------------------------------------------------------
385 // ---------------------------------------------------------------------
386 // =====================================================================
387 
389 {
390  if (m_verbose>=2) Cout("vAlgorithm::StepBeforeIterationLoop ... " << endl);
391 
392  // Check that the image space is already allocated
393  if (mp_ImageSpace==NULL || !mp_ImageSpace->Checked())
394  {
395  Cerr("***** vAlgorithm::StepBeforeIterationLoop() -> Image space has not been created or was not checked !" << endl);
396  return 1;
397  }
398 
399  // Instantiate all the required images from the oImageSpace
405 
407  {
408  Cerr("***** vAlgorithm::StepBeforeIterationLoop()-> Error during attenuation image initialization !" << endl);
409  return 1;
410  }
411 
413  {
414  Cerr("***** vAlgorithm::StepBeforeIterationLoop() -> An error occurred while initializing the sensitivity image !" << endl);
415  return 1;
416  }
417 
419  {
420  Cerr("***** vAlgorithm::StepBeforeIterationLoop()-> Error during multimodal image initialization !" << endl);
421  return 1;
422  }
423 
425  {
426  Cerr("***** vAlgorithm::StepBeforeIterationLoop()-> Error during mask image initialization !" << endl);
427  return 1;
428  }
429 
430  // End
431  return 0;
432 }
433 
434 // =====================================================================
435 // ---------------------------------------------------------------------
436 // ---------------------------------------------------------------------
437 // =====================================================================
438 
440 {
441  // End
442  return 0;
443 }
444 
445 // =====================================================================
446 // ---------------------------------------------------------------------
447 // ---------------------------------------------------------------------
448 // =====================================================================
449 
450 int vAlgorithm::StepPreProcessInsideSubsetLoop(int a_iteration, int a_subset)
451 {
452  // End
453  return 0;
454 }
455 
456 // =====================================================================
457 // ---------------------------------------------------------------------
458 // ---------------------------------------------------------------------
459 // =====================================================================
460 
461 int vAlgorithm::StepPostProcessInsideSubsetLoop(int a_iteration, int a_subset)
462 {
463  // End
464  return 0;
465 }
466 
467 // =====================================================================
468 // ---------------------------------------------------------------------
469 // ---------------------------------------------------------------------
470 // =====================================================================
471 
473 {
474  // End
475  return 0;
476 }
477 
478 // =====================================================================
479 // ---------------------------------------------------------------------
480 // ---------------------------------------------------------------------
481 // =====================================================================
482 
484 {
485  if (m_verbose>=2) Cout("vAlgorithm::StepAfterIterationLoop ... " << endl);
486 
487  // Deallocate everything
495 
496  // Normal end
497  return 0;
498 }
499 
500 // =====================================================================
501 // ---------------------------------------------------------------------
502 // ---------------------------------------------------------------------
503 // =====================================================================
504 
505 int vAlgorithm::StepImageOutput(int a_iteration, int a_subset)
506 {
507  // Normal end
508  return 0;
509 }
510 
511 // =====================================================================
512 // ---------------------------------------------------------------------
513 // ---------------------------------------------------------------------
514 // =====================================================================
515 
516 int vAlgorithm::InitSpecificOptions(string a_specificOptions)
517 {
518  (void)a_specificOptions; // avoid 'unused parameter' compil. warnings
519  // Normal end
520  return 0;
521 }
oImageConvolverManager * mp_ImageConvolverManager
Definition: vAlgorithm.hh:359
This header file is mainly used to declare some macro definitions and all includes needed from the st...
oOptimizerManager * mp_OptimizerManager
Definition: vAlgorithm.hh:355
Declaration of class vAlgorithm.
virtual int InitSpecificOptions(string a_specificOptions)
Definition: vAlgorithm.cc:516
oImageProcessingManager * mp_ImageProcessingManager
Definition: vAlgorithm.hh:360
#define FLTNB
Definition: gVariables.hh:81
int SetNbIterationsAndSubsets(const string &a_nbIterationsSubsets)
Set the number of iterations and subsets.
Definition: vAlgorithm.cc:85
int InitMaskImage(const string &a_pathToImage)
Memory allocation and initialization for the mask image.
Definition: oImageSpace.cc:670
void DeallocateImage()
Free memory for the main image matrices.
Definition: oImageSpace.cc:116
int InitMultiModalImage(const vector< string > &a_pathToMultiModalImage)
Memory allocation and initialization for the multimodal image matrices.
Definition: oImageSpace.cc:604
string m_pathToAtnImg
Definition: vAlgorithm.hh:363
int RunCPU()
Perform the iterative loop of the algorithm. Function designed to be executed on the CPU only...
Definition: vAlgorithm.cc:252
void DeallocateMultiModalImage()
Free memory for the multimodal image.
Definition: oImageSpace.cc:651
oProjectorManager * mp_ProjectorManager
Definition: vAlgorithm.hh:354
virtual int StepBeforeSubsetLoop(int a_iteration)
This function is called before starting the data subset loop.
Definition: vAlgorithm.cc:439
int Run()
Just call either the RunCPU or the RunGPU function as asked for.
Definition: vAlgorithm.cc:233
bool m_saveSensitivityHistoFlag
Definition: vAlgorithm.hh:367
void DeallocateSensitivityImage()
Free memory for the sensitivity image matrices.
Definition: oImageSpace.cc:461
void InstantiateImage()
Allocate memory for the main image matrices.
Definition: oImageSpace.cc:80
int m_nbIterations
Definition: vAlgorithm.hh:347
virtual int StepInnerLoopInsideSubsetLoop(int a_iteration, int a_subset, int a_bed)=0
This function is called inside the subset loop. It contains the core operations of the algorithm an...
void InstantiateSensitivityImage(const string &a_pathToSensitivityImage)
Allocate the sensitivity image matrices.
Definition: oImageSpace.cc:386
int InitAttenuationImage(const string &a_pathToAtnImage)
Memory allocation and initialisation for the attenuation image using either :
int * mp_nbSubsets
Definition: vAlgorithm.hh:348
virtual int StepImageOutput(int a_iteration, int a_subset=-1)=0
This function deals with everything about saving output images from the reconstruction.
Definition: vAlgorithm.cc:505
void DeallocateVisitedVoxelsImage()
Free memory for the image matrix containing binary information regarding which 3D voxels have been vi...
Definition: oImageSpace.cc:592
void DeallocateMaskImage()
Free memory for the mask image.
Definition: oImageSpace.cc:711
oImageSpace * mp_ImageSpace
Definition: vAlgorithm.hh:358
virtual int StepPostProcessInsideSubsetLoop(int a_iteration, int a_subset)
Definition: vAlgorithm.cc:461
vAlgorithm()
vAlgorithm constructor. Initialize the member variables to their default values.
Definition: vAlgorithm.cc:39
vDataFile ** m2p_DataFile
Definition: vAlgorithm.hh:353
#define Cerr(MESSAGE)
bool m_saveDynamicBasisCoefficients
Definition: vAlgorithm.hh:369
string m_pathToSensitivityImg
Definition: vAlgorithm.hh:364
void InstantiateVisitedVoxelsImage()
Memory allocation and initialization for the image matrix containing binary information regarding whi...
Definition: oImageSpace.cc:580
string m_pathToInitialImg
Definition: vAlgorithm.hh:362
oDynamicModelManager * mp_DynamicModelManager
Definition: vAlgorithm.hh:357
Declaration of class iEventHistoCT.
virtual int StepPreProcessInsideSubsetLoop(int a_iteration, int a_subset)
This function is called right after starting the data subset loop.
Definition: vAlgorithm.cc:450
virtual int StepBeforeIterationLoop()
This function is called at the beginning of the RunCPU function.
Definition: vAlgorithm.cc:388
bool m_saveImageAfterSubsets
Definition: vAlgorithm.hh:368
virtual ~vAlgorithm()
vAlgorithm destructor.
Definition: vAlgorithm.cc:73
void InstantiateForwardImage()
Allocate memory for the forward image matrices.
Definition: oImageSpace.cc:149
string m_pathToMaskImg
Definition: vAlgorithm.hh:366
bool m_flagGPU
Definition: vAlgorithm.hh:351
oDeformationManager * mp_DeformationManager
Definition: vAlgorithm.hh:356
virtual int StepAfterSubsetLoop(int a_iteration)
This function is called after finishing the data subset loop.
Definition: vAlgorithm.cc:472
oImageDimensionsAndQuantification * mp_ID
Definition: vAlgorithm.hh:352
vector< string > m_pathToMultiModalImg
Definition: vAlgorithm.hh:365
virtual int StepAfterIterationLoop()
This function is called at the end of the RunCPU function.
Definition: vAlgorithm.cc:483
void DeallocateOutputImage()
Free memory for the Image matrices dedicated to output writing on disk.
Definition: oImageSpace.cc:787
int SetOutputIterations(const string &a_outputIterations)
Set the selected output iterations.
Definition: vAlgorithm.cc:144
bool * mp_outputIterations
Definition: vAlgorithm.hh:349
#define Cout(MESSAGE)
bool Checked()
Simply check that the image dimensions and verbosity has been set.
Definition: oImageSpace.hh:653
int InitSensitivityImage(const string &a_pathToSensitivityImage)
Initialization for the sensitivity image matrices.
void DeallocateForwardImage()
Free memory for the forward image matrices.
Definition: oImageSpace.cc:185
void InstantiateOutputImage()
Instanciate Image matrices dedicated to output writing on disk.
Definition: oImageSpace.cc:740