CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
iOptimizerAPPGML.cc
Go to the documentation of this file.
1 
8 #include "iOptimizerAPPGML.hh"
9 #include "sOutputManager.hh"
10 
11 // =====================================================================
12 // ---------------------------------------------------------------------
13 // ---------------------------------------------------------------------
14 // =====================================================================
15 
17 {
18  // ---------------------------
19  // Mandatory member parameters
20  // ---------------------------
21 
22  // Initial value at 1
23  m_initialValue = 1.;
24  // Only one backward image for APPGML
26  // APPGML accepts penalties
28  // APPGML is only compatible with histogram data
31  // APPGML is only compatible with emission data
34  // APPGML needs pre process loop to convolve region of interest once
35  m_needPreIteration = true;
36 
37  // --------------------------
38  // Specific member parameters
39  // --------------------------
40 
44  m_bound = -1.;
45  m_regionImagePath = "";
46  m4p_imageNotShifted = NULL;
51 }
52 
53 // =====================================================================
54 // ---------------------------------------------------------------------
55 // ---------------------------------------------------------------------
56 // =====================================================================
57 
59 {
60  // Delete the image (not shifted)
62  {
63  // Loop over time basis functions
65  {
66  if (m4p_imageNotShifted[tbf])
67  {
68  // Loop over respiratory basis functions
70  {
71  if (m4p_imageNotShifted[tbf][rbf])
72  {
73  free(m4p_imageNotShifted[tbf][rbf]);
74  }
75  }
76  free(m4p_imageNotShifted[tbf]);
77  }
78  }
79  free(m4p_imageNotShifted);
80  }
81 
82  // Delete the penalty image
84  {
85  // Loop over time basis functions
87  {
89  {
90  // Loop over respiratory basis functions
92  {
93  if (m4p_firstDerivativePenaltyImage[tbf][rbf])
94  {
95  free(m4p_firstDerivativePenaltyImage[tbf][rbf]);
96  }
97  }
99  }
100  }
102  }
103 
104  // Delete the second order derivative penalty image
106  {
107  // Loop over time basis functions
108  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
109  {
111  {
112  // Loop over respiratory basis functions
113  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
114  {
115  if (m4p_secondDerivativePenaltyImage[tbf][rbf])
116  {
117  free(m4p_secondDerivativePenaltyImage[tbf][rbf]);
118  }
119  }
121  }
122  }
124  }
125 }
126 
127 // =====================================================================
128 // ---------------------------------------------------------------------
129 // ---------------------------------------------------------------------
130 // =====================================================================
131 
133 {
134  cout << "This optimizer is the A-Penalized Preconditioned Gradient algorithm (A-PPGML) from M. Millardet et al, IEEE TRPMS," << endl;
135  cout << "2021, vol. 6, pp. 629-640. It is based on the same idea as AML, which is allowing for negative values in the image" << endl;
136  cout << "by shifting an algorithm enforcing positive values. APPGML can be seen as a shifted version of PPGML with a lower" << endl;
137  cout << "bound A. This algorithm allows for negative image values in case the provided bound is also negative. The shift is" << endl;
138  cout << "applied uniformly in the whole image unless a shift image is provided. This shift image allows to customize the" << endl;
139  cout << "shift value applied in each voxel. The algorithm can also use penalized reconstruction because it is based on PPGML." << endl;
140  cout << "The following options can be used (in this particular order when provided as a list):" << endl;
141  cout << " initial image value: to set the uniform voxel value for the initial image" << endl;
142  cout << " denominator threshold: to set the threshold of the data space denominator under which the ratio is set to 1" << endl;
143  cout << " minimum image update: to set the minimum of the image update factor under which it stays constant (0 or a negative value" << endl;
144  cout << " means no minimum thus allowing a 0 update)" << endl;
145  cout << " maximum image update: to set the maximum of the image update factor over which it stays constant (0 or a negative value means" << endl;
146  cout << " no maximum)" << endl;
147  cout << " bound: to set the lower bound value to apply the shift (must be negative to authorize negative values)" << endl;
148  cout << " shift image path: provide an image used to applied non-uniform shift within the reconstructed image. The values of the" << endl;
149  cout << " shift image weight the shift applied to every voxel (0 means the voxel is not shifted, 1 means the" << endl;
150  cout << " voxel is shifted by the bound, and t means the voxel is shifted by t times the bound). If no shift" << endl;
151  cout << " image is provided, the shift is equal to the bound and is applied uniformly on the whole image" << endl;
152 }
153 
154 // =====================================================================
155 // ---------------------------------------------------------------------
156 // ---------------------------------------------------------------------
157 // =====================================================================
158 
159 int iOptimizerAPPGML::ReadConfigurationFile(const string& a_configurationFile)
160 {
161  string key_word = "";
162  string buffer = "";
163 
164  // Read the initial image value option
165  key_word = "initial image value";
166  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_initialValue, 1, KEYWORD_MANDATORY))
167  {
168  Cerr("***** iOptimizerAPPGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
169  return 1;
170  }
171  // Read the denominator threshold option
172  key_word = "denominator threshold";
173  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_dataSpaceDenominatorThreshold, 1, KEYWORD_MANDATORY))
174  {
175  Cerr("***** iOptimizerAPPGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
176  return 1;
177  }
178  // Read the minimum image update option
179  key_word = "minimum image update";
180  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_minimumImageUpdateFactor, 1, KEYWORD_MANDATORY))
181  {
182  Cerr("***** iOptimizerAPPGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
183  return 1;
184  }
185  // Read the maximum image update option
186  key_word = "maximum image update";
187  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_maximumImageUpdateFactor, 1, KEYWORD_MANDATORY))
188  {
189  Cerr("***** iOptimizerAPPGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
190  return 1;
191  }
192  // Read the bound value
193  key_word = "bound";
194  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_bound, 1, KEYWORD_MANDATORY))
195  {
196  Cerr("***** iOptimizerAPPGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
197  return 1;
198  }
199  // Read the path to image defining region to apply the shift
200  key_word = "region image path";
201  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_regionImagePath, 1, KEYWORD_MANDATORY))
202  {
203  Cerr("***** iOptimizerAPPGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
204  return 1;
205  }
206  // Normal end
207  return 0;
208 }
209 
210 // =====================================================================
211 // ---------------------------------------------------------------------
212 // ---------------------------------------------------------------------
213 // =====================================================================
214 
215 int iOptimizerAPPGML::ReadOptionsList(const string& a_optionsList)
216 {
217  // Too complicated to do it that way
218  Cerr("***** iOptimizerAPPGML::ReadOptionsList() -> Options can be specified only using a configuration file !" << endl);
219  return 1;
220 }
221 
222 // =====================================================================
223 // ---------------------------------------------------------------------
224 // ---------------------------------------------------------------------
225 // =====================================================================
226 
228 {
229  // Check that initial image value is strictly positive
230  if (m_initialValue<=0.)
231  {
232  Cerr("***** iOptimizerAPPGML->CheckSpecificParameters() -> Provided initial image value (" << m_initialValue << ") must be strictly positive !" << endl);
233  return 1;
234  }
235  // Check that denominator threshold value is strictly positive
237  {
238  Cerr("***** iOptimizerAPPGML->CheckSpecificParameters() -> Provided data space denominator threshold (" << m_dataSpaceDenominatorThreshold << ") must be strictly positive !" << endl);
239  return 1;
240  }
241  // Check that maximum image update factor is higher than the minimum
243  {
244  Cerr("***** iOptimizerAPPGML->CheckSpecificParameters() -> Provided minimum/maximum (" << m_minimumImageUpdateFactor << "/" << m_maximumImageUpdateFactor << " are inconsistent !" << endl);
245  return 1;
246  }
247  // Check that the initial image value is above the provided bound
249  {
250  Cerr("***** iOptimizerAPPGML::CheckSpecificParameters() -> The initial image value (" << m_initialValue << ") must be higher than or equal to the provided bound value (" << m_bound << ") !" << endl);
251  return 1;
252  }
253  // Normal end
254  return 0;
255 }
256 
257 // =====================================================================
258 // ---------------------------------------------------------------------
259 // ---------------------------------------------------------------------
260 // =====================================================================
261 
263 {
264  // Allocate and create the image (not shifted)
266  // Loop over time basis functions
267  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
268  {
270  // Loop over respiratory basis functions
271  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
272  {
274  // Loop over cardiac basis functions
275  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
276  {
277  m4p_imageNotShifted[tbf][rbf][cbf] = mp_ImageSpace -> AllocateMiscellaneousImage(); //Get a pointer to a newly allocated image
278  //for (int v=0; v<mp_ImageDimensionsAndQuantification->GetNbVoxXYZ(); v++) m4p_imageNotShifted[tbf][rbf][cbf][v] = -1;
279  }
280  }
281  }
282 
283  // Allocate and create the penalty image
285  // Loop over time basis functions
286  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
287  {
289  // Loop over respiratory basis functions
290  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
291  {
293  // Loop over cardiac basis functions
294  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
295  {
296  m4p_firstDerivativePenaltyImage[tbf][rbf][cbf] = mp_ImageSpace -> AllocateMiscellaneousImage(); //Get a pointer to a newly allocated image
297  }
298  }
299  }
300 
301  // Allocate and create the second order derivative penalty image
303  // Loop over time basis functions
304  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
305  {
307  // Loop over respiratory basis functions
308  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
309  {
311  // Loop over cardiac basis functions
312  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
313  {
314  m4p_secondDerivativePenaltyImage[tbf][rbf][cbf] = mp_ImageSpace -> AllocateMiscellaneousImage(); //Get a pointer to a newly allocated image
315  }
316  }
317  }
318 
319  // Allocate the specific region of interest
320  mp_specificRegionOfInterest = mp_ImageSpace -> AllocateMiscellaneousImage(); // Get a pointer to a newly allocated image
321  mp_specificRegionOfInterestConvolved = mp_ImageSpace -> AllocateMiscellaneousImage(); // Get a pointer to a newly allocated image
322  // Initialize/Read the specific region of interest
323  if (m_regionImagePath == "") // whole phantom to be considered, so uniform image
324  {
325  for (int v=0; v<mp_ImageDimensionsAndQuantification->GetNbVoxXYZ(); v++)
326  {
329  }
330  }
331  else
332  {
333  // Interfile image reading (INTF_LERP_ENABLED = interpolation allowed)
335  {
336  Cerr("***** iOptimizerAPPGML::InitializeSpecific() -> Error reading interfile image '" << m_regionImagePath << "' !" << endl);
337  return 1;
338  }
340  {
341  Cerr("***** iOptimizerAPPGML::InitializeSpecific() -> Error reading interfile image '" << m_regionImagePath << "' !" << endl);
342  return 1;
343  }
344  }
345  // Verbose
346  if (m_verbose>=2)
347  {
348  Cout("iOptimizerAPPGML::InitializeSpecific() -> Use the APPGML optimizer" << endl);
349  if (m_verbose>=3)
350  {
351  Cout(" --> Initial image value: " << m_initialValue << endl);
352  Cout(" --> Data space denominator threshold: " << m_dataSpaceDenominatorThreshold << endl);
353  if (m_minimumImageUpdateFactor>0.) Cout(" --> Minimum image update factor: " << m_minimumImageUpdateFactor << endl);
354  else Cerr("!!!!! The minimum update value is not set, if using subsets, voxels could be trapped in 0 value causing some negative bias !" << endl);
355  if (m_maximumImageUpdateFactor>0.) Cout(" --> Maximum image update factor: " << m_maximumImageUpdateFactor << endl);
356  Cout(" --> Bound value: " << m_bound << endl);
357  if (m_regionImagePath != "") Cout(" --> Shift weighted for each voxel by provided image: " << m_regionImagePath << endl);
358  else Cout(" --> Uniform shift across the whole image" << endl);
359  }
360  }
361  // Normal end
362  return 0;
363 }
364 
365 // =====================================================================
366 // ---------------------------------------------------------------------
367 // ---------------------------------------------------------------------
368 // =====================================================================
369 
370 
372 {
373  // Apply convolver in pre iteration to region of interest because image-based PSF not inside ForwardProject function
374  if (m_isInPreIteration)
375  {
377  {
378  Cerr("***** iOptimizerAPPGML::PreDataUpdateSpecificStep() -> A problem occurred while applying image convolver to region to apply shift !" << endl);
379  return 1;
380  }
381  }
382  if (!m_isInPreIteration)
383  {
384  // Set the number of threads
385  #ifdef CASTOR_OMP
387  #endif
388 
389  // Loop over time basis functions
390  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
391  {
392  // Loop over respiratory basis functions
393  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
394  {
395  // Loop over cardiac basis functions
396  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
397  {
398  int v;
399  // multi-threading
400  #pragma omp parallel for private(v) schedule(guided)
402  {
403 
404  // Store the image without shift for penalty computation
405  m4p_imageNotShifted[tbf][rbf][cbf][v] = mp_ImageSpace-> m4p_image[tbf][rbf][cbf][v];
406  mp_ImageSpace-> m4p_image[tbf][rbf][cbf][v] -= mp_specificRegionOfInterest[v]*m_bound;
407  mp_ImageSpace-> m4p_forwardImage[tbf][rbf][cbf][v] -= mp_specificRegionOfInterest[v]*m_bound;
408  }
409  }
410  }
411  }
412  }
413  // End
414  return 0;
415 }
416 
417 // =====================================================================
418 // ---------------------------------------------------------------------
419 // ---------------------------------------------------------------------
420 // =====================================================================
421 
422 int iOptimizerAPPGML::SensitivitySpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_weight,
423  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
424  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
425 {
426  // Line weight here is simply 1
427  *ap_weight = 1.;
428  // That's all
429  return 0;
430 }
431 
432 // =====================================================================
433 // ---------------------------------------------------------------------
434 // ---------------------------------------------------------------------
435 // =====================================================================
436 
437 int iOptimizerAPPGML::DataSpaceSpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_backwardValues,
438  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
439  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
440 {
441  if (!m_isInPreIteration)
442  {
443  // Compute the bound projection
445  a_data -= shift;
446  // Truncate data to 0 if negative
447  if (a_data<0.) a_data = 0.;
448 
449  // Compute numerator
450  FLTNB numerator = a_data - a_forwardModel;
451  // Compute denominator that will be strictly positive
452  FLTNB denominator = max(a_forwardModel,m_dataSpaceDenominatorThreshold);
453  // Update backward values
454  *ap_backwardValues = numerator / denominator;
455  }
456  // That's all
457  return 0;
458 
459 }
460 
461 // =====================================================================
462 // ---------------------------------------------------------------------
463 // ---------------------------------------------------------------------
464 // =====================================================================
465 
467 {
468  if (!m_isInPreIteration)
469  {
470  // ==========================================================================================
471  // If no penalty, then exit (the penalty image term has been initialized to 0)
472  if (mp_Penalty==NULL) return 0;
473  // Set the number of threads
474  #ifdef CASTOR_OMP
476  #endif
477  // Verbose
478  if (m_verbose>=1) Cout("iOptimizerAPPGML::PreImageUpdateSpecificStep() -> Compute penalty term" << endl);
479  // ==========================================================================================
480  // Global precomputation step if needed by the penalty
482  {
483  Cerr("***** iOptimizerAPPGML::PreImageUpdateSpecificStep() -> A problem occurred while computing the penalty pre-processing step !" << endl);
484  return 1;
485  }
486  // ==========================================================================================
487  // Loop over time basis functions
488  for (int tbf=0; tbf<mp_ImageDimensionsAndQuantification->GetNbTimeBasisFunctions(); tbf++)
489  {
490  // Loop over respiratory basis functions
491  for (int rbf=0; rbf<mp_ImageDimensionsAndQuantification->GetNbRespBasisFunctions(); rbf++)
492  {
493  // Loop over cardiac basis functions
494  for (int cbf=0; cbf<mp_ImageDimensionsAndQuantification->GetNbCardBasisFunctions(); cbf++)
495  {
496  // In order to detect problems in the multi-threaded loop
497  bool problem = false;
498  // Voxel index
499  INTNB v;
500  // Multi-threading over voxels
501  #pragma omp parallel for private(v) schedule(guided)
503  {
504  // Get the thread index
505  int th = 0;
506  #ifdef CASTOR_OMP
507  th = omp_get_thread_num();
508  #endif
509  // Local precomputation step if needed by the penalty
510  if (mp_Penalty->LocalPreProcessingStep(tbf,rbf,cbf,v,th))
511  {
512  Cerr("***** iOptimizerAPPGML::PreImageUpdateSpecificStep() -> A problem occurred while computing the penalty local pre-processing step for voxel " << v << " !" << endl);
513  problem = true;
514  }
515  // Compute first and second derivative order penalty terms on image (not shifted)
518  }
519  // Check for problems
520  if (problem)
521  {
522  Cerr("***** iOptimizerAPPGML::PreImageUpdateSpecificStep() -> A problem occurred inside the multi-threaded loop, stop now !" << endl);
523  return 1;
524  }
525  }
526  }
527  }
528  }
529  // End
530  return 0;
531 }
532 
533 // =====================================================================
534 // ---------------------------------------------------------------------
535 // ---------------------------------------------------------------------
536 // =====================================================================
537 
538 int iOptimizerAPPGML::ImageSpaceSpecificOperations( FLTNB a_currentImageValue, FLTNB* ap_newImageValue,
539  FLTNB a_sensitivity, FLTNB* ap_correctionValues, INTNB a_voxel, int tbf, int rbf, int cbf )
540 {
541  if (!m_isInPreIteration)
542  {
543  FLTNB image_update_factor = *ap_correctionValues - m4p_firstDerivativePenaltyImage[tbf][rbf][cbf][a_voxel] / (FLTNB)(mp_nbSubsets[m_currentIteration]); //divide the penalty by the number of subset, otherwise the regularization parameter has to be adapted when we change the number of subsets
544 
545  a_sensitivity += a_currentImageValue * m4p_secondDerivativePenaltyImage[tbf][rbf][cbf][a_voxel] / (FLTNB)(mp_nbSubsets[m_currentIteration]);
546 
547  image_update_factor = 1. + image_update_factor / a_sensitivity;
548  // Apply minimum image update factor
549  if ( m_minimumImageUpdateFactor > 0. && image_update_factor < m_minimumImageUpdateFactor ) image_update_factor = m_minimumImageUpdateFactor;
550  // Apply maximum image update factor
551  if ( m_maximumImageUpdateFactor > 0. && image_update_factor > m_maximumImageUpdateFactor ) image_update_factor = m_maximumImageUpdateFactor;
552  // Update image
553  *ap_newImageValue = a_currentImageValue * image_update_factor;
554  // Check if it is a number, if no, keep the value unchanged
555  if (!isfinite(*ap_newImageValue)) *ap_newImageValue = a_currentImageValue;
556  // Apply the shift to region of interest to obtain final image (will be shifted in next iteration in PreDataUpdateSpecificStep)
557  *ap_newImageValue += mp_specificRegionOfInterest[a_voxel] * m_bound;
558  }
559  // End
560  return 0;
561 }
562 
563 // =====================================================================
564 // ---------------------------------------------------------------------
565 // ---------------------------------------------------------------------
566 // =====================================================================
FLTNB * mp_specificRegionOfInterestConvolved
FLTNB * mp_specificRegionOfInterest
int GetNbCardBasisFunctions()
Get the number of cardiac basis functions.
#define INTF_LERP_ENABLED
#define Cerr(MESSAGE)
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
int InitializeSpecific()
This function is used to initialize specific stuff to the child optimizer.
int ImageSpaceSpecificOperations(FLTNB a_currentImageValue, FLTNB *ap_newImageValue, FLTNB a_sensitivity, FLTNB *ap_correctionValues, INTNB a_voxel, int tbf=-1, int rbf=-1, int cbf=-1)
This function perform the image update step specific to the optimizer.
int PreImageUpdateSpecificStep()
A private function used to compute the penalty term update adaptive alpha of the ADMM algorithm...
int ApplyConvolution(FLTNB *ap_image)
A function that simply calls the eponym function from the vImageConvolver.
int DataSpaceSpecificOperations(FLTNB a_data, FLTNB a_forwardModel, FLTNB *ap_backwardValues, FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue, FLTNB a_quantificationFactor, oProjectionLine *ap_Line)
This function performs the data space operations specific to the optimizer (computes the values to be...
virtual int LocalPreProcessingStep(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)
int GetNbTimeBasisFunctions()
Get the number of time basis functions.
FLTNB ForwardProject(oProjectionLine *ap_Line, FLTNB *ap_image=NULL)
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
FLTNB **** m4p_imageNotShifted
int IntfReadImage(const string &a_pathToHeaderFile, FLTNB *ap_ImgMatrix, oImageDimensionsAndQuantification *ap_ID, int vb, bool a_lerpFlag)
Main function dedicated to Interfile 3D image loading.
virtual int GlobalPreProcessingStep()
A public function computing a global pre-processing step for the penalty.
FLTNB **** m4p_secondDerivativePenaltyImage
void ShowHelpSpecific()
A function used to show help about the child optimizer.
int SensitivitySpecificOperations(FLTNB a_data, FLTNB a_forwardModel, FLTNB *ap_weight, FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue, FLTNB a_quantificationFactor, oProjectionLine *ap_Line)
This function compute the weight associated to the provided event (for sensitivity computation) ...
FLTNB m_dataSpaceDenominatorThreshold
#define KEYWORD_MANDATORY
This class is designed to generically described any iterative optimizer.
This class is designed to manage and store system matrix elements associated to a vEvent...
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child optimizer.
Declaration of class iOptimizerAPPGML.
int GetNbThreadsForImageComputation()
Get the number of threads used for image operations.
virtual FLTNB ComputeSecondDerivative(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)=0
virtual FLTNB ComputeFirstDerivative(int a_tbf, int a_rbf, int a_cbf, INTNB a_voxel, int a_th)=0
iOptimizerAPPGML()
The constructor of iOptimizerAPPGML.
virtual int PreDataUpdateSpecificStep()
A private function used to compute some norms for the image update.
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...
#define Cout(MESSAGE)
int GetNbRespBasisFunctions()
Get the number of respiratory basis functions.
oImageConvolverManager * mp_ImageConvolverManager
FLTNB **** m4p_firstDerivativePenaltyImage
~iOptimizerAPPGML()
The destructor of iOptimizerAPPGML.