CASToR  3.0
Tomographic Reconstruction (PET/SPECT/CT)
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-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 "iOptimizerOriginalAML.hh"
31 #include "sOutputManager.hh"
32 
33 // =====================================================================
34 // ---------------------------------------------------------------------
35 // ---------------------------------------------------------------------
36 // =====================================================================
37 
39 {
40  // ---------------------------
41  // Mandatory member parameters
42  // ---------------------------
43 
44  // Initial value at 1
45  m_initialValue = 1.;
46  // Only one backward image for AML
48  // AML is only compatible with histogram data
51  // AML is only compatible with emission data
54 
55  // --------------------------
56  // Specific member parameters
57  // --------------------------
58 
59  // Threshold applied to the denominator of the data space operation to avoid to high ratios
61  // This is the AML bound parameter
62  m_bound = 1.;
63 }
64 
65 // =====================================================================
66 // ---------------------------------------------------------------------
67 // ---------------------------------------------------------------------
68 // =====================================================================
69 
71 {
72 }
73 
74 // =====================================================================
75 // ---------------------------------------------------------------------
76 // ---------------------------------------------------------------------
77 // =====================================================================
78 
80 {
81  cout << "This optimizer is the AML algorithm derived from the AB-EMML of C. Byrne, Inverse Problems, 1998, vol. 14, pp. 1455-67." << endl;
82  cout << "The bound B is taken to infinity, so only the bound A can be parameterized." << endl;
83  cout << "This bound must be quantitative (same unit as the reconstructed image)." << endl;
84  cout << "It is provided as a single value and thus assuming a uniform bound." << endl;
85  cout << "This algorithm allows for negative image values in case the provided bound is also negative." << endl;
86  cout << "Subsets can be used." << endl;
87  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;
88  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;
89  cout << "equation 22 of K. Van Slambrouck et al, IEEE TMI, Jan 2015, vol. 34, pp. 126-136." << endl;
90  cout << "The following options can be used (in this particular order when provided as a list):" << endl;
91  cout << " initial image value: to set the uniform voxel value for the initial image" << endl;
92  cout << " denominator threshold: to set the threshold of the data space denominator under which the ratio is set to 1" << endl;
93  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;
94 }
95 
96 // =====================================================================
97 // ---------------------------------------------------------------------
98 // ---------------------------------------------------------------------
99 // =====================================================================
100 
101 int iOptimizerOriginalAML::ReadConfigurationFile(const string& a_configurationFile)
102 {
103  string key_word = "";
104  // Read the initial image value option
105  key_word = "initial image value";
106  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_initialValue, 1, KEYWORD_MANDATORY))
107  {
108  Cerr("***** iOptimizerOriginalAML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
109  return 1;
110  }
111  // Read the denominator threshold option
112  key_word = "denominator threshold";
113  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_dataSpaceDenominatorThreshold, 1, KEYWORD_MANDATORY))
114  {
115  Cerr("***** iOptimizerOriginalAML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
116  return 1;
117  }
118  // Read the bound value
119  key_word = "bound";
120  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_bound, 1, KEYWORD_MANDATORY))
121  {
122  Cerr("***** iOptimizerOriginalAML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
123  return 1;
124  }
125  // Normal end
126  return 0;
127 }
128 
129 // =====================================================================
130 // ---------------------------------------------------------------------
131 // ---------------------------------------------------------------------
132 // =====================================================================
133 
134 int iOptimizerOriginalAML::ReadOptionsList(const string& a_optionsList)
135 {
136  // There are 3 floating point variables as options
137  const int nb_options = 3;
138  FLTNB options[nb_options];
139  // Read them
140  if (ReadStringOption(a_optionsList, options, nb_options, ",", "AML configuration"))
141  {
142  Cerr("***** iOptimizerOriginalAML::ReadOptionsList() -> Failed to correctly read the list of options !" << endl);
143  return 1;
144  }
145  // Affect options
146  m_initialValue = options[0];
147  m_dataSpaceDenominatorThreshold = options[1];
148  m_bound = options[2];
149  // Normal end
150  return 0;
151 }
152 
153 // =====================================================================
154 // ---------------------------------------------------------------------
155 // ---------------------------------------------------------------------
156 // =====================================================================
157 
159 {
160  // Check that denominator threshold value is strictly positive
162  {
163  Cerr("***** iOptimizerOriginalAML->CheckSpecificParameters() -> Provided data space denominator threshold (" << m_dataSpaceDenominatorThreshold << ") must be strictly positive !" << endl);
164  return 1;
165  }
166  // If a negative or null bound is provided (standard AML), then check that the initial image value is above the provided bound
167  if (m_bound<=0. && m_initialValue<m_bound)
168  {
169  Cerr("***** iOptimizerOriginalAML::CheckSpecificParameters() -> The initial image value (" << m_initialValue << ") must be higher than or equal to the provided bound value ("
170  << m_bound << ") !" << endl);
171  return 1;
172  }
173  // Normal end
174  return 0;
175 }
176 
177 // =====================================================================
178 // ---------------------------------------------------------------------
179 // ---------------------------------------------------------------------
180 // =====================================================================
181 
183 {
184  // Verbose
186  {
187  Cout("iOptimizerOriginalAML::InitializeSpecific() -> Use the AML optimizer" << endl);
189  {
190  Cout(" --> Initial image value: " << m_initialValue << endl);
191  Cout(" --> Data space denominator threshold: " << m_dataSpaceDenominatorThreshold << endl);
192  if (m_bound<=0.) Cout(" --> Bound value: " << m_bound << endl);
193  else Cout(" --> Bound value taken to minus infinity" << endl);
194  }
195  }
196  // Normal end
197  return 0;
198 }
199 
200 // =====================================================================
201 // ---------------------------------------------------------------------
202 // ---------------------------------------------------------------------
203 // =====================================================================
204 
206  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
207  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
208 {
209  // Line weight here is a simply 1
210  *ap_weight = 1.;
211  // That's all
212  return 0;
213 }
214 
215 // =====================================================================
216 // ---------------------------------------------------------------------
217 // ---------------------------------------------------------------------
218 // =====================================================================
219 
220 int iOptimizerOriginalAML::DataSpaceSpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_backwardValues,
221  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
222  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
223 {
224  // Implementation of the standard AML (bound is negative or null)
225  if (m_bound<=0.)
226  {
227  // Compute the bound projection
228  FLTNB shift = ForwardProject(ap_Line) * m_bound;
229  // Compute denominator (this is the shifted model)
230  FLTNB denominator = a_forwardModel - shift;
231  // If the denominator is to close to zero, then ignore this data
232  if (denominator<=m_dataSpaceDenominatorThreshold) *ap_backwardValues = 1.;
233  // Otherwise, do it normally
234  else
235  {
236  // Compute numerator (this is the shifted data)
237  FLTNB numerator = a_data - shift;
238  // Truncate to 0 if negative
239  if (numerator<0.) *ap_backwardValues = 0.;
240  // Otherwise, update backward values
241  else *ap_backwardValues = numerator / denominator;
242  }
243  }
244  // Implementation of AML with the bound taken to minus infinity (when the provided bound is positive)
245  else
246  {
247  *ap_backwardValues = (a_data - a_forwardModel) / ForwardProject(ap_Line);
248  }
249  // That's all
250  return 0;
251 }
252 
253 // =====================================================================
254 // ---------------------------------------------------------------------
255 // ---------------------------------------------------------------------
256 // =====================================================================
257 
258 int iOptimizerOriginalAML::ImageSpaceSpecificOperations( FLTNB a_currentImageValue, FLTNB* ap_newImageValue,
259  FLTNB a_sensitivity, FLTNB* ap_correctionValues,
260  INTNB a_voxel, int a_tbf, int a_rbf, int a_cbf )
261 {
262  // Compute image update factor
263  FLTNB image_update_factor = *ap_correctionValues / a_sensitivity;
264  // Update image for the standard AML (bound is negative or null)
265  if (m_bound<=0.) *ap_newImageValue = m_bound + (a_currentImageValue - m_bound) * image_update_factor;
266  // Update image for a bound taken to minus infinity (when the provided bound is positive)
267  else *ap_newImageValue = a_currentImageValue + image_update_factor;
268  // End
269  return 0;
270 }
271 
272 // =====================================================================
273 // ---------------------------------------------------------------------
274 // ---------------------------------------------------------------------
275 // =====================================================================
#define FLTNB
Definition: gVariables.hh:81
FLTNB m_initialValue
Definition: vOptimizer.hh:663
bool m_listmodeCompatibility
Definition: vOptimizer.hh:664
iOptimizerOriginalAML()
The constructor of iOptimizerOriginalAML.
#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:1120
Declaration of class iOptimizerOriginalAML.
#define Cerr(MESSAGE)
bool m_emissionCompatibility
Definition: vOptimizer.hh:666
int m_nbBackwardImages
Definition: vOptimizer.hh:659
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:129
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:665
#define VERBOSE_NORMAL
#define KEYWORD_MANDATORY
Definition: gOptions.hh:47
int ImageSpaceSpecificOperations(FLTNB a_currentImageValue, FLTNB *ap_newImageValue, FLTNB a_sensitivity, FLTNB *ap_correctionValues, INTNB a_voxel, int a_tbf=-1, int a_rbf=-1, int a_cbf=-1)
This function perform the image update step specific to the optimizer.
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:667
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 &#39;a_input&#39; string corresponding to the &#39;a_option&#39; into &#39;a_nbElts&#39; elements, using the &#39;sep&#39; separator. The results are returned in the templated &#39;ap_return&#39; dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
Definition: gOptions.cc:50
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...