CASToR  2.0
Tomographic Reconstruction (PET/SPECT/CT)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iOptimizerOriginalAML.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-2018 all CASToR contributors listed below:
18 
19  --> current contributors: Thibaut MERLIN, Simon STUTE, Didier BENOIT, Claude COMTAT, Marina FILIPOVIC, Mael MILLARDET
20  --> past contributors: Valentin VIELZEUF
21 
22 This is CASToR version 2.0.
23 */
24 
31 #include "iOptimizerOriginalAML.hh"
32 #include "sOutputManager.hh"
33 
34 // =====================================================================
35 // ---------------------------------------------------------------------
36 // ---------------------------------------------------------------------
37 // =====================================================================
38 
40 {
41  // ---------------------------
42  // Mandatory member parameters
43  // ---------------------------
44 
45  // Initial value at 1
46  m_initialValue = 1.;
47  // Only one backward image for AML
49  // AML does not accept penalties
50  //m_penaltyEnergyFunctionDerivativesOrder = 0;
51  // AML is only compatible with histogram data
54  // AML is only compatible with emission data
57 
58  // --------------------------
59  // Specific member parameters
60  // --------------------------
61 
62  // Threshold applied to the denominator of the data space operation to avoid to high ratios
64  // This is the AML bound parameter
65  m_bound = 1.;
66 }
67 
68 // =====================================================================
69 // ---------------------------------------------------------------------
70 // ---------------------------------------------------------------------
71 // =====================================================================
72 
74 {
75 }
76 
77 // =====================================================================
78 // ---------------------------------------------------------------------
79 // ---------------------------------------------------------------------
80 // =====================================================================
81 
83 {
84  cout << "This optimizer is the AML algorithm derived from the AB-EMML of C. Byrne, Inverse Problems, 1998, vol. 14, pp. 1455-67." << endl;
85  cout << "The bound B is taken to infinity, so only the bound A can be parameterized." << endl;
86  cout << "This bound must be quantitative (same unit as the reconstructed image)." << endl;
87  cout << "It is provided as a single value and thus assuming a uniform bound." << endl;
88  cout << "Subsets can be used." << endl;
89  cout << "With a negative or null bound, this algorithm implements equation 6 of A. Rahmim et al, Phys. Med. Biol., 2012, vol. 57, pp. 733-55." << endl;
90  cout << "If a positive bound is provided, then we suppose that the bound A is taken to minus infinity. In that case, this algorithm implements" << endl;
91  cout << "equation 22 of K. Van Slambrouck et al, IEEE TMI, Jan 2015, vol. 34, pp. 126-136." << endl;
92  cout << "The following options can be used (in this particular order when provided as a list):" << endl;
93  cout << " initial image value: to set the uniform voxel value for the initial image" << endl;
94  cout << " denominator threshold: to set the threshold of the data space denominator under which the ratio is set to 1" << endl;
95  cout << " bound: to set the bound parameter that shift the Poisson law (quantitative, negative or null for standard AML and positive for infinite AML)." << endl;
96 }
97 
98 // =====================================================================
99 // ---------------------------------------------------------------------
100 // ---------------------------------------------------------------------
101 // =====================================================================
102 
103 int iOptimizerOriginalAML::ReadConfigurationFile(const string& a_configurationFile)
104 {
105  string key_word = "";
106  // Read the initial image value option
107  key_word = "initial image value";
108  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_initialValue, 1, KEYWORD_MANDATORY))
109  {
110  Cerr("***** iOptimizerOriginalAML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
111  return 1;
112  }
113  // Read the denominator threshold option
114  key_word = "denominator threshold";
115  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_dataSpaceDenominatorThreshold, 1, KEYWORD_MANDATORY))
116  {
117  Cerr("***** iOptimizerOriginalAML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
118  return 1;
119  }
120  // Read the bound value
121  key_word = "bound";
122  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_bound, 1, KEYWORD_MANDATORY))
123  {
124  Cerr("***** iOptimizerOriginalAML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
125  return 1;
126  }
127  // Normal end
128  return 0;
129 }
130 
131 // =====================================================================
132 // ---------------------------------------------------------------------
133 // ---------------------------------------------------------------------
134 // =====================================================================
135 
136 int iOptimizerOriginalAML::ReadOptionsList(const string& a_optionsList)
137 {
138  // There are 3 floating point variables as options
139  const int nb_options = 3;
140  FLTNB options[nb_options];
141  // Read them
142  if (ReadStringOption(a_optionsList, options, nb_options, ",", "AML configuration"))
143  {
144  Cerr("***** iOptimizerOriginalAML::ReadOptionsList() -> Failed to correctly read the list of options !" << endl);
145  return 1;
146  }
147  // Affect options
148  m_initialValue = options[0];
149  m_dataSpaceDenominatorThreshold = options[1];
150  m_bound = options[2];
151  // Normal end
152  return 0;
153 }
154 
155 // =====================================================================
156 // ---------------------------------------------------------------------
157 // ---------------------------------------------------------------------
158 // =====================================================================
159 
161 {
162  // Check that denominator threshold value is strictly positive
164  {
165  Cerr("***** iOptimizerOriginalAML->CheckSpecificParameters() -> Provided data space denominator threshold (" << m_dataSpaceDenominatorThreshold << ") must be strictly positive !" << endl);
166  return 1;
167  }
168  // If a negative or null bound is provided (standard AML), then check that the initial image value is above the provided bound
169  if (m_bound<=0. && m_initialValue<m_bound)
170  {
171  Cerr("***** iOptimizerOriginalAML::CheckSpecificParameters() -> The initial image value (" << m_initialValue << ") must be higher than or equal to the provided bound value ("
172  << m_bound << ") !" << endl);
173  return 1;
174  }
175  // Normal end
176  return 0;
177 }
178 
179 // =====================================================================
180 // ---------------------------------------------------------------------
181 // ---------------------------------------------------------------------
182 // =====================================================================
183 
185 {
186  // Verbose
188  {
189  Cout("iOptimizerOriginalAML::InitializeSpecific() -> Use the AML optimizer" << endl);
191  {
192  Cout(" --> Initial image value: " << m_initialValue << endl);
193  Cout(" --> Data space denominator threshold: " << m_dataSpaceDenominatorThreshold << endl);
194  if (m_bound<=0.) Cout(" --> Bound value: " << m_bound << endl);
195  else Cout(" --> Bound value taken to minus infinity" << endl);
196  }
197  }
198  // Normal end
199  return 0;
200 }
201 
202 // =====================================================================
203 // ---------------------------------------------------------------------
204 // ---------------------------------------------------------------------
205 // =====================================================================
206 
208  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
209  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
210 {
211  // Line weight here is a simply 1
212  *ap_weight = 1.;
213  // That's all
214  return 0;
215 }
216 
217 // =====================================================================
218 // ---------------------------------------------------------------------
219 // ---------------------------------------------------------------------
220 // =====================================================================
221 
222 int iOptimizerOriginalAML::DataSpaceSpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_backwardValues,
223  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
224  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
225 {
226  // Implementation of the standard AML (bound is negative or null)
227  if (m_bound<=0.)
228  {
229  // Compute the bound projection
230  FLTNB shift = ForwardProject(ap_Line) * m_bound;
231  // Compute denominator (this is the shifted model)
232  FLTNB denominator = a_forwardModel - shift;
233  // If the denominator is to close to zero, then ignore this data
234  if (denominator<=m_dataSpaceDenominatorThreshold) *ap_backwardValues = 1.;
235  // Otherwise, do it normally
236  else
237  {
238  // Compute numerator (this is the shifted data)
239  FLTNB numerator = a_data - shift;
240  // Truncate to 0 if negative
241  if (numerator<0.) *ap_backwardValues = 0.;
242  // Otherwise, update backward values
243  else *ap_backwardValues = numerator / denominator;
244  }
245  }
246  // Implementation of AML with the bound taken to minus infinity (when the provided bound is positive)
247  else
248  {
249  *ap_backwardValues = (a_data - a_forwardModel) / ForwardProject(ap_Line);
250  }
251  // That's all
252  return 0;
253 }
254 
255 // =====================================================================
256 // ---------------------------------------------------------------------
257 // ---------------------------------------------------------------------
258 // =====================================================================
259 
260 int iOptimizerOriginalAML::ImageSpaceSpecificOperations( FLTNB a_currentImageValue, FLTNB* ap_newImageValue,
261  FLTNB a_sensitivity, FLTNB* ap_correctionValues, INTNB a_voxel )
262 {
263  // Compute image update factor
264  FLTNB image_update_factor = *ap_correctionValues / a_sensitivity;
265  // Update image for the standard AML (bound is negative or null)
266  if (m_bound<=0.) *ap_newImageValue = m_bound + (a_currentImageValue - m_bound) * image_update_factor;
267  // Update image for a bound taken to minus infinity (when the provided bound is positive)
268  else *ap_newImageValue = a_currentImageValue + image_update_factor;
269  // End
270  return 0;
271 }
272 
273 // =====================================================================
274 // ---------------------------------------------------------------------
275 // ---------------------------------------------------------------------
276 // =====================================================================
#define FLTNB
Definition: gVariables.hh:81
FLTNB m_initialValue
Definition: vOptimizer.hh:619
bool m_listmodeCompatibility
Definition: vOptimizer.hh:620
iOptimizerOriginalAML()
The constructor of iOptimizerOriginalAML.
int ImageSpaceSpecificOperations(FLTNB a_currentImageValue, FLTNB *ap_newImageValue, FLTNB a_sensitivity, FLTNB *ap_correctionValues, INTNB a_voxel)
This function perform the image update step specific to the optimizer.
#define VERBOSE_DETAIL
FLTNB ForwardProject(oProjectionLine *ap_Line, FLTNB *ap_image=NULL)
A function used to forward project the provided image (or 1 if NULL), based on the provided oProjecti...
Definition: vOptimizer.cc:988
Declaration of class iOptimizerOriginalAML.
#define Cerr(MESSAGE)
bool m_emissionCompatibility
Definition: vOptimizer.hh:622
int m_nbBackwardImages
Definition: vOptimizer.hh:615
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...
Definition: gOptions.cc:123
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
void ShowHelpSpecific()
A function used to show help about the child optimizer.
bool m_histogramCompatibility
Definition: vOptimizer.hh:621
#define VERBOSE_NORMAL
#define KEYWORD_MANDATORY
Definition: gOptions.hh:48
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child optimizer.
#define INTNB
Definition: gVariables.hh:92
bool m_transmissionCompatibility
Definition: vOptimizer.hh:623
This class is designed to generically described any iterative optimizer.
Definition: vOptimizer.hh:59
This class is designed to manage and store system matrix elements associated to a vEvent...
~iOptimizerOriginalAML()
The destructor of iOptimizerOriginalAML.
int InitializeSpecific()
This function is used to initialize specific stuff to the child optimizer.
Declaration of class sOutputManager.
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
#define Cout(MESSAGE)
int ReadStringOption(const string &a_input, T *ap_return, int a_nbElts, const string &sep, const string &a_option)
Parse the 'a_input' string corresponding to the 'a_option' into 'a_nbElts' elements, using the 'sep' separator. The results are returned in the templated 'ap_return' dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
Definition: gOptions.cc:62
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) ...
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...