RTK  2.6.0
Reconstruction Toolkit
rtkProjectionsDecompositionNegativeLogLikelihood.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright RTK Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * https://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #ifndef rtkProjectionsDecompositionNegativeLogLikelihood_h
20 #define rtkProjectionsDecompositionNegativeLogLikelihood_h
21 
23 #include <itkVectorImage.h>
25 #include <itkVariableSizeMatrix.h>
26 #include "rtkMacro.h"
27 
28 namespace rtk
29 {
38 // We have to define the cost function first
40 {
41 public:
42  ITK_DISALLOW_COPY_AND_MOVE(ProjectionsDecompositionNegativeLogLikelihood);
43 
48  itkNewMacro(Self);
49  itkOverrideGetNameOfClassMacro(ProjectionsDecompositionNegativeLogLikelihood);
50 
51  // enum { SpaceDimension=m_NumberOfMaterials };
52 
56 
57  using DetectorResponseType = vnl_matrix<double>;
58  using MaterialAttenuationsType = vnl_matrix<double>;
59  using IncidentSpectrumType = vnl_matrix<float>;
63 
64  // Constructor
66  {
69  m_Initialized = false;
70  }
71 
72  // Destructor
74 
76  GetValue(const ParametersType & itkNotUsed(parameters)) const override
77  {
78  long double measure = 0;
79  return measure;
80  }
81  void
82  GetDerivative(const ParametersType & itkNotUsed(lineIntegrals),
83  DerivativeType & itkNotUsed(derivatives)) const override
84  {
85  itkExceptionMacro(<< "Not implemented");
86  }
87  virtual void
89  {}
90 
93  {
94  // Return the inverses of the diagonal components (i.e. the inverse variances, to be used directly in WLS
95  // reconstruction)
97  diag.SetSize(m_NumberOfMaterials);
98  diag.Fill(0);
99 
100  for (unsigned int mat = 0; mat < m_NumberOfMaterials; mat++)
101  diag[mat] = 1. / m_Fischer.GetInverse()[mat][mat];
102  return diag;
103  }
104 
107  {
108  // Return the inverses of the diagonal components (i.e. the inverse variances, to be used directly in WLS
109  // reconstruction)
111  diag.SetSize(m_NumberOfMaterials);
112  diag.Fill(0);
113 
114  for (unsigned int mat = 0; mat < m_NumberOfMaterials; mat++)
115  diag[mat] = m_Fischer.GetInverse()[mat][mat];
116  return diag;
117  }
118 
121  {
122  // Return the whole Fischer information matrix
124  fischer.SetSize(m_NumberOfMaterials * m_NumberOfMaterials);
125  fischer.Fill(0);
126 
127  for (unsigned int i = 0; i < m_NumberOfMaterials; i++)
128  for (unsigned int j = 0; j < m_NumberOfMaterials; j++)
129  fischer[i * m_NumberOfMaterials + j] = m_Fischer[i][j];
130  return fischer;
131  }
132 
133  virtual void
134  ComputeFischerMatrix(const ParametersType & itkNotUsed(lineIntegrals))
135  {}
136 
137  unsigned int
138  GetNumberOfParameters() const override
139  {
140  return m_NumberOfMaterials;
141  }
142 
143  virtual vnl_vector<double>
144  ForwardModel(const ParametersType & lineIntegrals) const
145  {
146  vnl_vector<double> attenuationFactors;
147  attenuationFactors.set_size(m_NumberOfEnergies);
148  GetAttenuationFactors(lineIntegrals, attenuationFactors);
149 
150  // Apply detector response, getting the lambdas
151  return (m_IncidentSpectrumAndDetectorResponseProduct * attenuationFactors);
152  }
153 
154  void
155  GetAttenuationFactors(const ParametersType & lineIntegrals, vnl_vector<double> & attenuationFactors) const
156  {
157  // Apply attenuation at each energy
158  vnl_vector<double> vnlLineIntegrals;
159 
160  // Initialize the line integrals vnl vector
161  vnlLineIntegrals.set_size(m_NumberOfMaterials);
162  for (unsigned int m = 0; m < m_NumberOfMaterials; m++)
163  vnlLineIntegrals[m] = lineIntegrals[m];
164 
165  // Apply the material attenuations matrix
166  attenuationFactors = this->m_MaterialAttenuations * vnlLineIntegrals;
167 
168  // Compute the negative exponential
169  for (unsigned int energy = 0; energy < m_NumberOfEnergies; energy++)
170  {
171  attenuationFactors[energy] = std::exp(-attenuationFactors[energy]);
172  }
173  }
174 
177  {
179  initialGuess.SetSize(m_NumberOfMaterials);
180 
181  // Compute the mean attenuation in each bin, weighted by the input spectrum
182  // Needs to be done for each pixel, since the input spectrum is variable
183  MeanAttenuationInBinType MeanAttenuationInBin;
184  MeanAttenuationInBin.SetSize(this->m_NumberOfMaterials, this->m_NumberOfSpectralBins);
185  MeanAttenuationInBin.Fill(0);
186 
187  for (unsigned int mat = 0; mat < this->m_NumberOfMaterials; mat++)
188  {
189  for (unsigned int bin = 0; bin < m_NumberOfSpectralBins; bin++)
190  {
191  double accumulate = 0;
192  double accumulateWeights = 0;
193  for (int energy = m_Thresholds[bin] - 1;
194  (energy < m_Thresholds[bin + 1]) && (energy < (int)(this->m_MaterialAttenuations.rows()));
195  energy++)
196  {
197  accumulate += this->m_MaterialAttenuations[energy][mat] * this->m_IncidentSpectrum[0][energy];
198  accumulateWeights += this->m_IncidentSpectrum[0][energy];
199  }
200  MeanAttenuationInBin[mat][bin] = accumulate / accumulateWeights;
201  }
202  }
203 
204  for (unsigned int mat = 0; mat < m_NumberOfMaterials; mat++)
205  {
206  // Initialise to a very high value
207  initialGuess[mat] = 1e10;
208  for (unsigned int bin = 0; bin < m_NumberOfSpectralBins; bin++)
209  {
210  // Compute the length of current material required to obtain the attenuation
211  // observed in current bin. Keep only the minimum among all bins
212  double requiredLength = this->BinwiseLogTransform()[bin] / MeanAttenuationInBin[mat][bin];
213  if (initialGuess[mat] > requiredLength)
214  initialGuess[mat] = requiredLength;
215  }
216  }
217 
218  return initialGuess;
219  }
220 
223  {
224  itk::VariableLengthVector<double> logTransforms;
225  logTransforms.SetSize(m_NumberOfSpectralBins);
226 
227  vnl_vector<double> ones, nonAttenuated;
228  ones.set_size(m_NumberOfEnergies);
229  ones.fill(1.0);
230 
231  // The way m_IncidentSpectrumAndDetectorResponseProduct works is
232  // it is mutliplied by the vector of attenuations factors (here
233  // filled with ones, since we want the non-attenuated signal)
234  nonAttenuated = m_IncidentSpectrumAndDetectorResponseProduct * ones;
235 
236  for (unsigned int i = 0; i < m_MeasuredData.GetSize(); i++)
237  {
238  // Divide by the actually measured photon counts and apply log
239  if (m_MeasuredData[i] > 0)
240  logTransforms[i] = log(nonAttenuated[i] / m_MeasuredData[i]);
241  }
242 
243  return logTransforms;
244  }
245 
246  virtual vnl_vector<double>
247  GetVariances(const ParametersType & itkNotUsed(lineIntegrals)) const
248  {
249  vnl_vector<double> meaninglessResult;
250  meaninglessResult.set_size(m_NumberOfSpectralBins);
251  meaninglessResult.fill(0.);
252  return (meaninglessResult);
253  }
254 
255  itkSetMacro(MeasuredData, MeasuredDataType);
256  itkGetMacro(MeasuredData, MeasuredDataType);
257 
258  itkSetMacro(DetectorResponse, DetectorResponseType);
259  itkGetMacro(DetectorResponse, DetectorResponseType);
260 
261  itkSetMacro(MaterialAttenuations, MaterialAttenuationsType);
262  itkGetMacro(MaterialAttenuations, MaterialAttenuationsType);
263 
264  itkSetMacro(NumberOfEnergies, unsigned int);
265  itkGetMacro(NumberOfEnergies, unsigned int);
266 
267  itkSetMacro(NumberOfMaterials, unsigned int);
268  itkGetMacro(NumberOfMaterials, unsigned int);
269 
270  itkSetMacro(IncidentSpectrum, IncidentSpectrumType);
271  itkGetMacro(IncidentSpectrum, IncidentSpectrumType);
272 
273  itkSetMacro(NumberOfSpectralBins, unsigned int);
274  itkGetMacro(NumberOfSpectralBins, unsigned int);
275 
276  itkSetMacro(Thresholds, ThresholdsType);
277  itkGetMacro(Thresholds, ThresholdsType);
278 
279 protected:
286  unsigned int m_NumberOfEnergies;
287  unsigned int m_NumberOfMaterials;
291 };
292 
293 } // namespace rtk
294 
295 #endif
virtual vnl_vector< double > ForwardModel(const ParametersType &lineIntegrals) const
void GetAttenuationFactors(const ParametersType &lineIntegrals, vnl_vector< double > &attenuationFactors) const
void GetDerivative(const ParametersType &, DerivativeType &) const override
#define itkSetMacro(name, type)
Superclass::ParametersType ParametersType
Array< ParametersValueType > DerivativeType
virtual vnl_vector< double > GetVariances(const ParametersType &) const