Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
itkDiffusionKurtosisReconstructionImageFilter.h
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #ifndef DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_H
18 #define DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_H
19 
20 #include "itkImageToImageFilter.h"
21 #include "itkVectorImage.h"
22 
24 
25 // vnl includes
26 #include <vnl/algo/vnl_levenberg_marquardt.h>
27 #include <vnl/vnl_least_squares_function.h>
28 
29 namespace itk
30 {
31 
32  // Fitting routines
33 
40  public vnl_least_squares_function
41  {
42  public:
44  kurtosis_fit_lsq_function( unsigned int num_params, unsigned int num_measurements, UseGradient g=no_gradient)
45  : vnl_least_squares_function( num_params, num_measurements, g),
46  m_use_bounds(false),
47  m_use_logscale(false),
48  m_skip_fit(false)
49  {}
50 
52  kurtosis_fit_lsq_function( unsigned int number_measurements)
53  : kurtosis_fit_lsq_function( 2, number_measurements, no_gradient )
54  {}
55 
56 
58  void initialize( vnl_vector< double > const& _meas, vnl_vector< double> const& _bvals )
59  {
60  meas = _meas;
61  if( m_use_logscale )
62  {
63  for( unsigned int i=0; i< meas.size(); ++i)
64  {
65  // would produce NaN values, skip the fit
66  // using the virtual function from the superclass (sets a boolean flag)
67  if( meas[i] < vnl_math::eps )
68  {
69  m_skip_fit = true;
70  throw_failure();
71 
72  continue;
73  }
74 
75  meas[i] = log( meas[i] );
76 
77  }
78  }
79 
80  bvalues = _bvals;
81  }
82 
83 
85  void use_bounds()
86  {
87  m_use_bounds = true;
88 
89  // initialize bounds
90  double upper_bounds[2] = {4e-3, 4 };
91  kurtosis_upper_bounds = vnl_vector<double>(2, 2, upper_bounds);
92  kurtosis_lower_bounds = vnl_vector<double>(2, 0);
93  }
94 
95  void set_fit_logscale( bool flag )
96  {
97  this->m_use_logscale = flag;
98  }
99 
100  void set_K_bounds( const vnl_vector_fixed<double, 2> k_bounds )
101  {
102  // init
103  this->use_bounds();
104 
105  // override K bounds
106  kurtosis_lower_bounds[1] = k_bounds[0];
107  kurtosis_upper_bounds[1] = k_bounds[1];
108  }
109 
110  virtual void f(const vnl_vector<double> &x, vnl_vector<double> &fx)
111  {
112  for ( unsigned int s=0; s < fx.size(); s++ )
113  {
114  const double factor = ( meas[s] - M(x, s) );
115  fx[s] = factor * factor + penalty_term(x);
116  }
117 
118  MITK_DEBUG("Fit.x_and_f") << x << " | " << fx;
119  }
120 
121  protected:
122 
124  double Diff( double x1, double x2, double b)
125  {
126  const double quotient = -1. * b * x1 + b*b * x1 * x1 * x2 / 6;
127 
128  if( m_use_logscale )
129  return quotient;
130  else
131  return exp(quotient);
132  }
133 
135  virtual double M( vnl_vector<double> const& x, unsigned int idx )
136  {
137  const double bvalue = bvalues[idx];
138 
139  double result = Diff( x[0], x[1], bvalue);
140 
141  if( m_use_logscale )
142  return meas[0] + result;
143  else
144  return meas[0] * result ;
145  }
146 
148  virtual double penalty_term( vnl_vector<double> const& x)
149  {
150  double penalty = 0;
151 
152  // skip when turned off
153  if( !m_use_bounds )
154  return penalty;
155 
156  // we have bounds for D and K only (the first two params )
157  for( unsigned int i=0; i< 2; i++)
158  {
159  // 5% penalty boundary
160  // use exponential function to scale the penalty (max when x[i] == bounds )
161  double penalty_boundary = 0.02 * (kurtosis_upper_bounds[i] - kurtosis_lower_bounds[i]);
162 
163  if( x[i] < kurtosis_lower_bounds[i] + penalty_boundary )
164  {
165  penalty += 1e6 * exp( -1 * ( x[i] - kurtosis_lower_bounds[i]) / penalty_boundary );
166  }
167  else if ( x[i] > kurtosis_upper_bounds[i] - penalty_boundary )
168  {
169  penalty += 1e6 * exp( -1 * ( kurtosis_upper_bounds[i] - x[i]) / penalty_boundary );
170  }
171  }
172 
173  MITK_DEBUG("Fit.Orig.Penalty") << x << " || penalty: " << penalty;
174 
175  return penalty;
176  }
177 
179 
181 
183 
184  vnl_vector<double> kurtosis_upper_bounds;
185  vnl_vector<double> kurtosis_lower_bounds;
186 
187  vnl_vector<double> meas;
188  vnl_vector<double> bvalues;
189 
190  };
191 
196  {
197  public:
199  kurtosis_fit_omit_unweighted( unsigned int number_measurements)
200  : kurtosis_fit_lsq_function( 3, number_measurements, no_gradient )
201  {}
202 
203  protected:
204  virtual double M(const vnl_vector<double> &x, unsigned int idx) override
205  {
206  const double bvalue = bvalues[idx];
207 
208  double result = Diff( x[0], x[1], bvalue);
209 
210  if( m_use_logscale )
211  return log( x[2] ) + result;
212  else
213  return x[2] * result ;
214  }
215  };
216 
217  enum FitScale
218  {
219  STRAIGHT = 0,
221  };
222 
224  {
226  : omit_bzero(false),use_K_limits(false),exclude_high_b(false) {}
227 
230 
232  vnl_vector_fixed<double, 2> K_limits;
233 
236  };
237 
245 template< class TInputPixelType, class TOutputPixelType >
247  public ImageToImageFilter< VectorImage< TInputPixelType, 3>, Image<TOutputPixelType, 3> >
248 {
249 public:
250 
257  {
259  : m_f(1), m_BzeroFit(1), m_D(0.001), m_K(0) {}
260 
261  // input data structures
262  //vnl_vector<double> filtered_measurements;
263  vnl_vector<double> bvalues;
264  vnl_vector<double> measurements;
265 
266  vnl_vector<double> fit_bvalues;
267  vnl_vector<double> fit_measurements;
268  vnl_vector<unsigned int> weighted_image_indices;
269 
271 
272  // variables holding the fitted values
273  double m_f;
274  double m_BzeroFit;
275  double m_D;
276  double m_K;
277  };
278 
279  //-- class typedefs
283  typedef ImageToImageFilter< VectorImage< TInputPixelType, 3>,
284  Image< TOutputPixelType,3 > > Superclass;
285 
287  itkFactorylessNewMacro(Self)
288  itkCloneMacro(Self)
289 
291  itkTypeMacro(DiffusionKurtosisReconstructionImageFilter, ImageToImageFilter)
292 
293  typedef TOutputPixelType OutputPixelType;
294  typedef TInputPixelType InputPixelType;
295 
296  typedef typename Superclass::InputImageType InputImageType;
297  typedef Image< OutputPixelType, 3 > OutputImageType;
298 
299  typedef itk::Image< short , 3> MaskImageType;
300 
301  typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
302 
303 
305  typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType
307 
308  // vector image typedefs for regularized fit
309  typedef itk::VectorImage<float,3> VectorImageType;
310  typedef itk::Image<itk::Vector<double, 3>, 3> InitialFitImageType;
311 
312  //-- input (Set) methods
317  void SetInitialSolution(const vnl_vector<double>& x0 );
318 
320  void SetOmitUnweightedValue( bool flag)
321  { this->m_OmitBZero = flag; }
322 
325  KurtosisSnapshot GetSnapshot( const itk::VariableLengthVector< TInputPixelType > &input, vnl_vector<double> bvalues, KurtosisFitConfiguration kf_conf);
326 
330 
336  KurtosisSnapshot GetCurrentSnapshot(bool omit_bzero);
337 
339  void SetReferenceBValue( double bvalue )
340  { this->m_ReferenceBValue = bvalue; }
341 
344 
347  {
348  m_MapOutputRegion = region;
349  this->m_ApplyPriorSmoothing = true;
350  }
351 
353 
355  void SetSmoothingSigma( double sigma )
356  {
357  this->m_SmoothingSigma = sigma;
358  this->m_ApplyPriorSmoothing = true;
359  }
360 
363  {
364  this->m_ApplyPriorSmoothing = flag;
365  }
366 
368  void SetBoundariesForKurtosis( double lower, double upper )
369  {
370  m_UseKBounds = true;
371 
372  m_KurtosisBounds[0] = lower; m_KurtosisBounds[1] = upper;
373  }
374 
376  void SetMaximalBValueUsedForFitting( double max_bvalue )
377  {
378  m_MaxFitBValue = max_bvalue;
379  }
380 
386  void SetFittingScale( FitScale scale )
387  {
388  m_ScaleForFitting = scale;
389  }
390 
391 protected:
394 
395  void GenerateOutputInformation() override;
396 
397  void AfterThreadedGenerateData() override;
398 
399  void BeforeThreadedGenerateData() override;
400 
401  void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) override;
402 
404 
405  vnl_vector<double> m_BValues;
406 
407  vnl_vector<double> m_InitialPosition;
408 
410 
412 
414 
416 
419 
421  vnl_vector_fixed<double, 2> m_KurtosisBounds;
423 
425 
426 private:
427 
428 
429 };
430 
431 } //end namespace itk
432 
433 #ifndef ITK_MANUAL_INSTANTIATION
435 #endif
436 
437 
438 #endif // DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_H
A fitting function handling the unweighted signal b_0 as a fitted parameter.
itk::SmartPointer< Self > Pointer
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
DataCollection - Class to facilitate loading/accessing structured data.
virtual double M(vnl_vector< double > const &x, unsigned int idx)
void initialize(vnl_vector< double > const &_meas, vnl_vector< double > const &_bvals)
virtual double penalty_term(vnl_vector< double > const &x)
kurtosis_fit_lsq_function(unsigned int num_params, unsigned int num_measurements, UseGradient g=no_gradient)
class ITK_EXPORT Image
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType
virtual void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
Struct describing a result (and the data) of a Kurtosis model fit.
ImageToImageFilter< VectorImage< TInputPixelType, 3 >, Image< TOutputPixelType, 3 > > Superclass
KurtosisSnapshot GetCurrentSnapshot(bool omit_bzero)
virtual double M(const vnl_vector< double > &x, unsigned int idx) override
KurtosisSnapshot GetSnapshot(const itk::VariableLengthVector< TInputPixelType > &input, vnl_vector< double > bvalues, KurtosisFitConfiguration kf_conf)
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) override
void set_K_bounds(const vnl_vector_fixed< double, 2 > k_bounds)
void SetGradientDirections(GradientDirectionContainerType::Pointer gradients)
MITKCORE_EXPORT const ScalarType eps
This filter provides the fit of the kurtosis (non-IVIM) signal to the data.