CASToR  2.0
Tomographic Reconstruction (PET/SPECT/CT)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iOptimizerNEGML.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 "iOptimizerNEGML.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 NEGML
49  // NEGML does not accept penalties
50  //m_penaltyEnergyFunctionDerivativesOrder = 0;
51  // NEGML is only compatible with histogram data
54  // NEGML is only compatible with emission data
57 
58  // --------------------------
59  // Specific member parameters
60  // --------------------------
61 
62  // This is the NEGML psi parameter
63  m_psi = -1.;
64 }
65 
66 // =====================================================================
67 // ---------------------------------------------------------------------
68 // ---------------------------------------------------------------------
69 // =====================================================================
70 
72 {
73 }
74 
75 // =====================================================================
76 // ---------------------------------------------------------------------
77 // ---------------------------------------------------------------------
78 // =====================================================================
79 
81 {
82  cout << "This optimizer is the NEGML algorithm from K. Van Slambrouck et al, IEEE TMI, Jan 2015, vol. 34, pp. 126-136." << endl;
83  cout << "Subsets can be used. This implementation only consider the psi parameter, but not the alpha image design parameter" << endl;
84  cout << "which is supposed to be 1 for all voxels. It implements equation 17 of the reference paper." << endl;
85  cout << "The following options can be used (in this particular order when provided as a list):" << endl;
86  cout << " initial image value: to set the uniform voxel value for the initial image" << endl;
87  cout << " psi: to set the psi parameter that sets the transition from Poisson to Gaussian statistics (must be positive)." << endl;
88  cout << " (if set to 0, then it is taken to infinity and implements equation 21 in the reference paper)." << endl;
89 }
90 
91 // =====================================================================
92 // ---------------------------------------------------------------------
93 // ---------------------------------------------------------------------
94 // =====================================================================
95 
96 int iOptimizerNEGML::ReadConfigurationFile(const string& a_configurationFile)
97 {
98  string key_word = "";
99  // Read the initial image value option
100  key_word = "initial image value";
101  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_initialValue, 1, KEYWORD_MANDATORY))
102  {
103  Cerr("***** iOptimizerNEGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
104  return 1;
105  }
106  // Read the psi value option
107  key_word = "psi";
108  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_psi, 1, KEYWORD_MANDATORY))
109  {
110  Cerr("***** iOptimizerNEGML::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
111  return 1;
112  }
113  // Normal end
114  return 0;
115 }
116 
117 // =====================================================================
118 // ---------------------------------------------------------------------
119 // ---------------------------------------------------------------------
120 // =====================================================================
121 
122 int iOptimizerNEGML::ReadOptionsList(const string& a_optionsList)
123 {
124  // There are 2 floating point variables as options
125  const int nb_options = 2;
126  FLTNB options[nb_options];
127  // Read them
128  if (ReadStringOption(a_optionsList, options, nb_options, ",", "NEGML configuration"))
129  {
130  Cerr("***** iOptimizerNEGML::ReadOptionsList() -> Failed to correctly read the list of options !" << endl);
131  return 1;
132  }
133  // Affect options
134  m_initialValue = options[0];
135  m_psi = options[1];
136  // Normal end
137  return 0;
138 }
139 
140 // =====================================================================
141 // ---------------------------------------------------------------------
142 // ---------------------------------------------------------------------
143 // =====================================================================
144 
146 {
147  // Check that the psi value is positive (a zero value means we take psi to infinity)
148  if (m_psi<0.)
149  {
150  Cerr("***** iOptimizerNEGML::CheckSpecificParameters() -> Provided psi value (" << m_psi << ") must be positive !" << endl);
151  return 1;
152  }
153  // Normal end
154  return 0;
155 }
156 
157 // =====================================================================
158 // ---------------------------------------------------------------------
159 // ---------------------------------------------------------------------
160 // =====================================================================
161 
163 {
164  // Verbose
166  {
167  Cout("iOptimizerNEGML::InitializeSpecific() -> Use the NEGML optimizer" << endl);
169  {
170  Cout(" --> Initial image value: " << m_initialValue << endl);
171  if (m_psi>0.) Cout(" --> Psi: " << m_psi << endl);
172  else if (m_psi==0.) Cout(" --> Psi taken to infinity" << endl);
173  }
174  }
175  // Normal end
176  return 0;
177 }
178 
179 // =====================================================================
180 // ---------------------------------------------------------------------
181 // ---------------------------------------------------------------------
182 // =====================================================================
183 
184 int iOptimizerNEGML::SensitivitySpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_weight,
185  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
186  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
187 {
188  // With psi taken to infinity, the weight is the forward projection of a uniform 1 image
189  if (m_psi==0.) *ap_weight = ForwardProject(ap_Line);
190  // Line weight here is a forward projection of alpha image divided by the max between psi and the forward model
191  else *ap_weight = ForwardProject(ap_Line) / max( m_psi , a_forwardModel );
192  // That's all
193  return 0;
194 }
195 
196 // =====================================================================
197 // ---------------------------------------------------------------------
198 // ---------------------------------------------------------------------
199 // =====================================================================
200 
201 int iOptimizerNEGML::DataSpaceSpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_backwardValues,
202  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
203  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
204 {
205  // Compute numerator
206  FLTNB numerator = a_data - a_forwardModel;
207  // Compute denominator that will be strictly positive
208  FLTNB denominator = 1.;
209  if (m_psi>0.) denominator = max( m_psi , a_forwardModel );
210  // Update backward values
211  *ap_backwardValues = numerator / denominator;
212  // That's all
213  return 0;
214 }
215 
216 // =====================================================================
217 // ---------------------------------------------------------------------
218 // ---------------------------------------------------------------------
219 // =====================================================================
220 
221 int iOptimizerNEGML::ImageSpaceSpecificOperations( FLTNB a_currentImageValue, FLTNB* ap_newImageValue,
222  FLTNB a_sensitivity, FLTNB* ap_correctionValues, INTNB a_voxel )
223 {
224  // Compute image update factor
225  FLTNB image_update_factor = *ap_correctionValues / a_sensitivity;
226  // Update image
227  *ap_newImageValue = a_currentImageValue + image_update_factor;
228  // End
229  return 0;
230 }
231 
232 // =====================================================================
233 // ---------------------------------------------------------------------
234 // ---------------------------------------------------------------------
235 // =====================================================================
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) ...
#define FLTNB
Definition: gVariables.hh:81
FLTNB m_initialValue
Definition: vOptimizer.hh:619
bool m_listmodeCompatibility
Definition: vOptimizer.hh:620
#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
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 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.
bool m_histogramCompatibility
Definition: vOptimizer.hh:621
#define VERBOSE_NORMAL
#define KEYWORD_MANDATORY
Definition: gOptions.hh:48
Declaration of class iOptimizerNEGML.
#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...
Declaration of class sOutputManager.
void ShowHelpSpecific()
A function used to show help about the child optimizer.
iOptimizerNEGML()
The constructor of iOptimizerNEGML.
~iOptimizerNEGML()
The destructor of iOptimizerNEGML.
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
#define Cout(MESSAGE)
int InitializeSpecific()
This function is used to initialize specific stuff to the child optimizer.
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...
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child optimizer.
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