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