CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
iOptimizerSens.cc
Go to the documentation of this file.
1 
8 #include "iOptimizerSens.hh"
9 #include "sOutputManager.hh"
10 
11 // =====================================================================
12 // ---------------------------------------------------------------------
13 // ---------------------------------------------------------------------
14 // =====================================================================
15 
17 {
18  // ---------------------------
19  // Mandatory member parameters
20  // ---------------------------
21 
22  // Initial value at 1
23  m_initialValue = 1.;
24  // Only one backward image for MLEM
26  // MLEM does not accept penalties
27  //m_penaltyEnergyFunctionDerivativesOrder = 0;
28  // Compatible with listmode and histogram data
31  // Compatible with both emission and log-converted transmission data
34 
35  // --------------------------
36  // Specific member parameters
37  // --------------------------
38 
42 }
43 
44 // =====================================================================
45 // ---------------------------------------------------------------------
46 // ---------------------------------------------------------------------
47 // =====================================================================
48 
50 {
51 }
52 
53 // =====================================================================
54 // ---------------------------------------------------------------------
55 // ---------------------------------------------------------------------
56 // =====================================================================
57 
59 {
60  cout << "This is a specific optimizer to compute a sensitivity image from a uniform acquisition, such as a uniform cylinder covering the FOV." << endl;
61  cout << "To use it, just add '-opti SENS' in the command-line option." << endl;
62  cout << "The data update step treats the input image as a mumap in cm-1 (data update step = 1 / exp(forwardProj*0.1)" << endl;
63  cout << "The image update step just take the image update factor as the actual image value" << endl;
64  cout << "This is just a quick/cheap implementation of such process, so here is a few remarks to make it work:" << endl;
65  cout << "- Iterations/subsets MUST both be 1 (-it 1:1)" << endl;
66  cout << "- For attenuation, an input mumap (cm-1) could be incorporated with the option -img. Make sure however it has the same numbers of voxel and voxel sizes than reconstruction" << endl;
67  cout << "- Calibration factor in the datafile header MUST be set to 1" << endl;
68  cout << "- The command-line options MUST disable frame duration correction, use the following command: 'ignore-corr fdur' " << endl;
69  cout << "- The algorithm will still try to compute a sensitivity image before the reconstruction process, whereas we just want the reconstruction to compute our sensitivity image" << endl;
70  cout << " Just input any image with the -sens option to bypass that step (the values from this image will not be taken into account anyway)." << endl;
71  cout << " Make sure it is the same dimensions as reconstruction dimensions and voxel sizes" << endl;
72 }
73 
74 // =====================================================================
75 // ---------------------------------------------------------------------
76 // ---------------------------------------------------------------------
77 // =====================================================================
78 
79 int iOptimizerSens::ReadConfigurationFile(const string& a_configurationFile)
80 {
81  string key_word = "";
82  // Read the initial image value option
83  key_word = "initial image value";
84  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_initialValue, 1, KEYWORD_MANDATORY))
85  {
86  Cerr("***** iOptimizerSens::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
87  return 1;
88  }
89  // Read the denominator threshold option
90  key_word = "denominator threshold";
91  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_dataSpaceDenominatorThreshold, 1, KEYWORD_MANDATORY))
92  {
93  Cerr("***** iOptimizerSens::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
94  return 1;
95  }
96  // Read the minimum image update option
97  key_word = "minimum image update";
98  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_minimumImageUpdateFactor, 1, KEYWORD_MANDATORY))
99  {
100  Cerr("***** iOptimizerSens::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
101  return 1;
102  }
103  // Read the maximum image update option
104  key_word = "maximum image update";
105  if (ReadDataASCIIFile(a_configurationFile, key_word, &m_maximumImageUpdateFactor, 1, KEYWORD_MANDATORY))
106  {
107  Cerr("***** iOptimizerSens::ReadConfigurationFile() -> Failed to get the '" << key_word << "' keyword !" << endl);
108  return 1;
109  }
110  // Normal end
111  return 0;
112 }
113 
114 // =====================================================================
115 // ---------------------------------------------------------------------
116 // ---------------------------------------------------------------------
117 // =====================================================================
118 
119 int iOptimizerSens::ReadOptionsList(const string& a_optionsList)
120 {
121  // There are 4 floating point variables as options
122  const int nb_options = 4;
123  FLTNB options[nb_options];
124 
125  // Read them
126  if (ReadStringOption(a_optionsList, options, nb_options, ",", "MLEM configuration"))
127  {
128  Cerr("***** iOptimizerSens::ReadOptionsList() -> Failed to correctly read the list of options !" << endl);
129  return 1;
130  }
131  // Affect options
132  m_initialValue = options[0];
133  m_dataSpaceDenominatorThreshold = options[1];
134  m_minimumImageUpdateFactor = options[2];
135  m_maximumImageUpdateFactor = options[3];
136 
137  // Normal end
138  return 0;
139 }
140 
141 // =====================================================================
142 // ---------------------------------------------------------------------
143 // ---------------------------------------------------------------------
144 // =====================================================================
145 
147 {
148  // Check that initial image value is strictly positive
149  if (m_initialValue<0.)
150  {
151  Cerr("***** iOptimizerSens->CheckSpecificParameters() -> Provided initial image value (" << m_initialValue << ") must be positive !" << endl);
152  return 1;
153  }
154  // Check that denominator threshold value is strictly positive
156  {
157  Cerr("***** iOptimizerSens->CheckSpecificParameters() -> Provided data space denominator threshold (" << m_dataSpaceDenominatorThreshold << ") must be strictly positive !" << endl);
158  return 1;
159  }
160  // Check that maximum image update factor is higher than the minimum
162  {
163  Cerr("***** iOptimizerSens->CheckSpecificParameters() -> Provided minimum/maximum (" << m_minimumImageUpdateFactor << "/" << m_maximumImageUpdateFactor << " are inconsistent !" << endl);
164  return 1;
165  }
166 
167  // Normal end
168  return 0;
169 }
170 
171 // =====================================================================
172 // ---------------------------------------------------------------------
173 // ---------------------------------------------------------------------
174 // =====================================================================
175 
177 {
178  // Verbose
180  {
181  Cout("iOptimizerSens::InitializeSpecific() -> Use the SENS optimizer" << endl);
183  {
184  Cout(" --> Initial image value: " << m_initialValue << endl);
185  Cout(" --> Data space denominator threshold: " << m_dataSpaceDenominatorThreshold << endl);
186  if (m_minimumImageUpdateFactor>0.) Cout(" --> Minimum image update factor: " << m_minimumImageUpdateFactor << endl);
187  else Cerr("!!!!! The minimum update value is not set, if using subsets, voxels could be trapped in 0 value causing some negative bias !" << endl);
188  if (m_maximumImageUpdateFactor>0.) Cout(" --> Maximum image update factor: " << m_maximumImageUpdateFactor << endl);
189  }
190  }
191  // Normal end
192  return 0;
193 }
194 
195 // =====================================================================
196 // ---------------------------------------------------------------------
197 // ---------------------------------------------------------------------
198 // =====================================================================
199 
200 int iOptimizerSens::SensitivitySpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_weight,
201  FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections, FLTNB a_blankValue,
202  FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
203 
204 //int iOptimizerSens::SensitivitySpecificOperations( FLTNB a_data, FLTNB a_forwardModel, FLTNB* ap_weight,
205 // FLTNB a_multiplicativeCorrections, FLTNB a_additiveCorrections,
206 // FLTNB a_quantificationFactor, oProjectionLine* ap_Line )
207 {
208  // Line weight here is simply 1
209  *ap_weight = 1.;
210  // That's all
211  return 0;
212 }
213 
214 
215 
216 // =====================================================================
217 // ---------------------------------------------------------------------
218 // ---------------------------------------------------------------------
219 // =====================================================================
220 
221 
222 int iOptimizerSens::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  // ----------------------------------------------------------------------------------------------
227  // Part 0: check the multiplication and quantification factors
228  // ----------------------------------------------------------------------------------------------
229 
230  // If multiplicative correction factor is null, then skip this event
231  if (a_multiplicativeCorrections<=0.) return 0;
232 
233  // If quantification factor is null, then skip this event
234  if (a_quantificationFactor<=0.) return 0;
235 
236 
237  // compute mu*x correcting by the 'a_quantificationFactor' applied
238  // in 'FLTNB oProjectionLine::ForwardProject()' and convert from cm-1 to mm-1
239 
240  FLTNB mux = a_forwardModel * (FLTNB)0.1;
241 
242  // The Attenuation Correction Factor
243  FLTNB acf = exp(-mux);
244 
245  // '*ap_backwardValues' is taken into account as the sensitivity
246  // not applying 'a_quantificationFactor' because is already included in
247  // 'm_multiplicativeCorrection' in method 'oProjectionLine::BackwardProject()'
248  *ap_backwardValues = acf;
249 
250  // That's all
251  return 0;
252 }
253 
254 // =====================================================================
255 // ---------------------------------------------------------------------
256 // ---------------------------------------------------------------------
257 // =====================================================================
258 int iOptimizerSens::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 {
263  // Compute image update factor
264  FLTNB image_update_factor = *ap_correctionValues ;
265  // Apply minimum image update factor
266  if ( m_minimumImageUpdateFactor > 0. && image_update_factor < m_minimumImageUpdateFactor ) image_update_factor = m_minimumImageUpdateFactor;
267  // Apply maximum image update factor
268  if ( m_maximumImageUpdateFactor > 0. && image_update_factor > m_maximumImageUpdateFactor ) image_update_factor = m_maximumImageUpdateFactor;
269  // Update image
270  *ap_newImageValue = image_update_factor;
271 
272  // End
273  return 0;
274 }
275 
276 // =====================================================================
277 // ---------------------------------------------------------------------
278 // ---------------------------------------------------------------------
279 // =====================================================================
280 
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 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.
#define Cerr(MESSAGE)
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child optimizer.
Declaration of class iOptimizerSens.
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
int InitializeSpecific()
This function is used to initialize specific stuff to the child optimizer.
FLTNB m_dataSpaceDenominatorThreshold
~iOptimizerSens()
The destructor of iOptimizerSens.
FLTNB m_maximumImageUpdateFactor
iOptimizerSens()
The constructor of iOptimizerSens.
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 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 KEYWORD_MANDATORY
This class is designed to generically described any iterative optimizer.
This class is designed to manage and store system matrix elements associated to a vEvent...
FLTNB m_minimumImageUpdateFactor
void ShowHelpSpecific()
A function used to show help about the child optimizer.
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...
#define Cout(MESSAGE)
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.