CASToR  1.1
Tomographic Reconstruction (PET/SPECT)
 All Classes Files Functions Variables Typedefs Macros Groups Pages
iOptimizerMLEM.cc
Go to the documentation of this file.
1 
2 /*
3  Implementation of class iOptimizerMLEM
4 
5  - separators: X
6  - doxygen: X
7  - default initialization: X
8  - CASTOR_DEBUG:
9  - CASTOR_VERBOSE:
10 */
11 
18 #include "iOptimizerMLEM.hh"
19 #include "sOutputManager.hh"
20 
21 // =====================================================================
22 // ---------------------------------------------------------------------
23 // ---------------------------------------------------------------------
24 // =====================================================================
25 
27 {
28  // ---------------------------
29  // Mandatory member parameters
30  // ---------------------------
31 
32  // Initial value at 1
33  m_initialValue = 1.;
34  // Only one backward image for MLEM
36  // MLEM does not accept penalties
37  //m_penaltyEnergyFunctionDerivativesOrder = 0;
38  // MLEM is compatible with listmode and histogram data
41 
42  // --------------------------
43  // Specific member parameters
44  // --------------------------
45 
49 }
50 
51 // =====================================================================
52 // ---------------------------------------------------------------------
53 // ---------------------------------------------------------------------
54 // =====================================================================
55 
57 {
58 }
59 
60 // =====================================================================
61 // ---------------------------------------------------------------------
62 // ---------------------------------------------------------------------
63 // =====================================================================
64 
66 {
67  cout << "This optimizer is the standard MLEM (for Maximum Likelihood Expectation Maximization)." << endl;
68  cout << "If subsets are used, it naturally becomes the OSEM optimizer." << endl;
69  cout << "The following options can be used (in this particular order when provided as a list):" << endl;
70  cout << " initial image value: to set the uniform voxel value for the initial image" << endl;
71  cout << " denominator threshold: to set the threshold of the data space denominator under which the ratio is set to 1" << endl;
72  cout << " minimum image update: to set the minimum of the image update factor under which it stays constant (0 or a negative value" << endl;
73  cout << " means no minimum thus allowing a 0 update)" << endl;
74  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;
75  cout << " no maximum)" << endl;
76 }
77 
78 // =====================================================================
79 // ---------------------------------------------------------------------
80 // ---------------------------------------------------------------------
81 // =====================================================================
82 
83 int iOptimizerMLEM::ReadConfigurationFile(const string& a_configurationFile)
84 {
85  string key_word = "";
86  // Read the initial image value option
87  key_word = "initial image value";
88  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_initialValue, 1, KEYWORD_MANDATORY))
89  {
90  Cerr("***** iOptimizerMLEM::ReadAndCheckConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
91  return 1;
92  }
93  // Read the denominator threshold option
94  key_word = "denominator threshold";
95  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_dataSpaceDenominatorThreshold, 1, KEYWORD_MANDATORY))
96  {
97  Cerr("***** iOptimizerMLEM::ReadAndCheckConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
98  return 1;
99  }
100  // Read the minimum image update option
101  key_word = "minimum image update";
102  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_minimumImageUpdateFactor, 1, KEYWORD_MANDATORY))
103  {
104  Cerr("***** iOptimizerMLEM::ReadAndCheckConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
105  return 1;
106  }
107  // Read the maximum image update option
108  key_word = "maximum image update";
109  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_maximumImageUpdateFactor, 1, KEYWORD_MANDATORY))
110  {
111  Cerr("***** iOptimizerMLEM::ReadAndCheckConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
112  return 1;
113  }
114  // Normal end
115  return 0;
116 }
117 
118 // =====================================================================
119 // ---------------------------------------------------------------------
120 // ---------------------------------------------------------------------
121 // =====================================================================
122 
123 int iOptimizerMLEM::ReadOptionsList(const string& a_optionsList)
124 {
125  // There are 4 floating point variables as options
126  FLTNB options[4];
127 
128  // Read them
129  if (ReadStringOption(a_optionsList, options, 4, ",", "MLEM configuration"))
130  {
131  Cerr("***** iOptimizerMLEM::ReadAndCheckConfigurationFile() -> Failed to correctly read the list of options !" << endl);
132  return 1;
133  }
134  // Affect options
135  m_initialValue = options[0];
136  m_dataSpaceDenominatorThreshold = options[1];
137  m_minimumImageUpdateFactor = options[2];
138  m_maximumImageUpdateFactor = options[3];
139 
140  // Normal end
141  return 0;
142 }
143 
144 // =====================================================================
145 // ---------------------------------------------------------------------
146 // ---------------------------------------------------------------------
147 // =====================================================================
148 
150 {
151  // Check that initial image value is strictly positive
152  if (m_initialValue<=0.)
153  {
154  Cerr("***** iOptimizerMLEM->Initialize() -> Provided initial image value (" << m_initialValue << ") must be strictly positive !" << endl);
155  return 1;
156  }
157  // Check that denominator threshold value is strictly positive
159  {
160  Cerr("***** iOptimizerMLEM->Initialize() -> Provided data space denominator threshold (" << m_dataSpaceDenominatorThreshold << ") must be strictly positive !" << endl);
161  return 1;
162  }
163  // Check that maximum image update factor is higher than the minimum
165  {
166  Cerr("***** iOptimizerMLEM->Initialize() -> Provided minimum/maximum (" << m_minimumImageUpdateFactor << "/" << m_maximumImageUpdateFactor << " are inconsistent !" << endl);
167  return 1;
168  }
169  // Normal end
170  return 0;
171 }
172 
173 // =====================================================================
174 // ---------------------------------------------------------------------
175 // ---------------------------------------------------------------------
176 // =====================================================================
177 
179 {
180  // Verbose
181  if (m_verbose>=2)
182  {
183  Cout("iOptimizerMLEM::Initialize() -> Use the MLEM optimizer" << endl);
184  if (m_verbose>=3)
185  {
186  Cout(" --> Initial image value: " << m_initialValue << endl);
187  Cout(" --> Data space denominator threshold: " << m_dataSpaceDenominatorThreshold << endl);
188  if (m_minimumImageUpdateFactor>0.) Cout(" --> Minimum image update factor: " << m_minimumImageUpdateFactor << endl);
189  else Cerr("!!!!! The minimum update value is not set, if using subsets, voxels could be trapped in 0 value causing some negative bias !" << endl);
190  if (m_maximumImageUpdateFactor>0.) Cout(" --> Maximum image update factor: " << m_maximumImageUpdateFactor << endl);
191  }
192  }
193  // Normal end
194  return 0;
195 }
196 
197 // =====================================================================
198 // ---------------------------------------------------------------------
199 // ---------------------------------------------------------------------
200 // =====================================================================
201 
202 int iOptimizerMLEM::SensitivitySpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_weight,
203  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections,
204  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
205 {
206  // Line weight here is simply 1
207  *ap_weight = 1.;
208  // That's all
209  return 0;
210 }
211 
212 // =====================================================================
213 // ---------------------------------------------------------------------
214 // ---------------------------------------------------------------------
215 // =====================================================================
216 
217 int iOptimizerMLEM::DataSpaceSpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_backwardValues,
218  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections,
219  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
220 {
221  // Truncate data to 0 if negative
222  if (a_data<0.) a_data = 0.;
223  // If the foward model is to close to zero, then ignore this data (set to 1 and not 0 because this line is taken into account in the sensitivity)
224  if (a_forwardModel>m_dataSpaceDenominatorThreshold) *ap_backwardValues = a_data / a_forwardModel;
225  else *ap_backwardValues = 1.;
226  // That's all
227  return 0;
228 }
229 
230 // =====================================================================
231 // ---------------------------------------------------------------------
232 // ---------------------------------------------------------------------
233 // =====================================================================
234 
235 int iOptimizerMLEM::ImageSpaceSpecificOperations( FLTNB a_currentImageValue, FLTNB* ap_newImageValue,
236  FLTNB a_sensitivity, FLTNB* ap_correctionValues )
237 {
238  // Compute image update factor
239  FLTNB image_update_factor = *ap_correctionValues / a_sensitivity;
240  // Apply minimum image update factor
241  if ( m_minimumImageUpdateFactor > 0. && image_update_factor < m_minimumImageUpdateFactor ) image_update_factor = m_minimumImageUpdateFactor;
242  // Apply maximum image update factor
243  if ( m_maximumImageUpdateFactor > 0. && image_update_factor > m_maximumImageUpdateFactor ) image_update_factor = m_maximumImageUpdateFactor;
244  // Update image
245  *ap_newImageValue = a_currentImageValue * image_update_factor;
246  // End
247  return 0;
248 }
249 
250 // =====================================================================
251 // ---------------------------------------------------------------------
252 // ---------------------------------------------------------------------
253 // =====================================================================
FLTNB m_dataSpaceDenominatorThreshold
#define FLTNB
Definition: gVariables.hh:55
FLTNB m_initialValue
Definition: vOptimizer.hh:587
bool m_listmodeCompatibility
Definition: vOptimizer.hh:588
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
int SensitivitySpecificOperations(FLTNB a_data, FLTNB a_forwardModel, FLTNB *ap_weight, FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, 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_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.
#define Cerr(MESSAGE)
int InitializeSpecific()
This function is used to initialize specific stuff to the child optimizer.
int m_nbBackwardImages
Definition: vOptimizer.hh:583
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:111
bool m_histogramCompatibility
Definition: vOptimizer.hh:589
iOptimizerMLEM()
The constructor of iOptimizerMLEM.
#define KEYWORD_MANDATORY
Definition: gOptions.hh:25
Declaration of class iOptimizerMLEM.
FLTNB m_maximumImageUpdateFactor
This class is designed to generically described any iterative optimizer.
Definition: vOptimizer.hh:36
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)
This function perform the image update step specific to the optimizer.
~iOptimizerMLEM()
The destructor of iOptimizerMLEM.
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
FLTNB m_minimumImageUpdateFactor
Declaration of class sOutputManager.
#define Cout(MESSAGE)
void ShowHelpSpecific()
A function used to show help about 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:50