18 #ifndef DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_CXX
19 #define DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_CXX
23 #include <itkImageRegionConstIterator.h>
24 #include <itkImageRegionConstIteratorWithIndex.h>
25 #include <itkImageRegionIteratorWithIndex.h>
26 #include <itkImageRegionIterator.h>
28 #include <itkVectorIndexSelectionCastImageFilter.h>
29 #include <itkComposeImageFilter.h>
30 #include <itkDiscreteGaussianImageFilter.h>
32 template<
class TInputPixelType>
34 const vnl_vector<double>& bvalues,
35 vnl_vector<double>& result,
39 assert( input.Size() == bvalues.size() );
42 auto bvalueIter = bvalues.begin();
43 unsigned int unused_values = 0;
44 while( bvalueIter != bvalues.end() )
54 vnl_vector<double> fit_measurements( input.Size() - unused_values, 0 );
55 vnl_vector<double> fit_bvalues( input.Size() - unused_values, 0 );
57 bvalueIter = bvalues.begin();
58 unsigned int running_index = 0;
59 unsigned int skip_count = 0;
60 while( bvalueIter != bvalues.end() )
71 fit_measurements[ running_index - skip_count ] = input.GetElement(running_index);
72 fit_bvalues[ running_index - skip_count] = *bvalueIter;
80 MITK_DEBUG(
"KurtosisFilter.FitSingleVoxel.Meas") << fit_measurements;
81 MITK_DEBUG(
"KurtosisFilter.FitSingleVoxel.Bval") << fit_bvalues;
89 kurtosis_cost_fn.initialize( fit_measurements, fit_bvalues );
93 kurtosis_cost_fn.set_K_bounds( kf_config.
K_limits );
96 vnl_levenberg_marquardt nonlinear_fit( kurtosis_cost_fn );
97 nonlinear_fit.minimize( result );
104 kurtosis_cost_fn.initialize( fit_measurements, fit_bvalues );
108 kurtosis_cost_fn.set_K_bounds( kf_config.
K_limits );
112 vnl_levenberg_marquardt nonlinear_fit( kurtosis_cost_fn );
113 nonlinear_fit.minimize(result);
116 MITK_DEBUG(
"KurtosisFilter.FitSingleVoxel.Rslt") << result;
121 template<
class TInputPixelType,
class TOutputPixelType>
124 : m_ReferenceBValue(-1),
126 m_MaskImage(nullptr),
127 m_ApplyPriorSmoothing(false),
128 m_SmoothingSigma(1.5),
129 m_MaxFitBValue( 3000 ),
130 m_UseKBounds( false ),
135 this->m_InitialPosition[0] = 0.001;
136 this->m_InitialPosition[1] = 1;
141 this->SetNumberOfRequiredInputs(1);
144 this->SetNumberOfRequiredOutputs(2);
148 this->SetNthOutput(0, outputPtr1.GetPointer() );
149 this->SetNthOutput(1, outputPtr2.GetPointer() );
153 template<
class TInputPixelType,
class TOutputPixelType>
158 Superclass::GenerateOutputInformation();
161 template<
class TInputPixelType,
class TOutputPixelType>
165 this->m_MaskImage = mask;
168 template<
class TInputPixelType,
class TOutputPixelType>
174 if( m_MaskImage.IsNull() )
177 m_MaskImage->SetRegions( this->GetInput()->GetLargestPossibleRegion() );
178 m_MaskImage->CopyInformation( this->GetInput() );
179 m_MaskImage->Allocate();
181 if( this->m_MapOutputRegion.GetNumberOfPixels() > 0 )
184 m_MaskImage->FillBuffer(0);
186 typedef itk::ImageRegionIteratorWithIndex< MaskImageType > MaskIteratorType;
187 MaskIteratorType maskIter( this->m_MaskImage, this->m_MapOutputRegion );
188 maskIter.GoToBegin();
190 while( !maskIter.IsAtEnd() )
199 m_MaskImage->FillBuffer(1);
207 if( this->m_ApplyPriorSmoothing )
210 typedef itk::DiscreteGaussianImageFilter< itk::Image<TInputPixelType, 3 >, itk::Image<TInputPixelType, 3 > > GaussianFilterType;
211 typedef itk::VectorIndexSelectionCastImageFilter< InputImageType, itk::Image<TInputPixelType, 3 > > IndexSelectionType;
212 typedef itk::ComposeImageFilter< itk::Image<TInputPixelType, 3>,
InputImageType > ComposeFilterType;
215 auto vectorImage = this->GetInput();
217 indexSelectionFilter->SetInput( vectorImage );
221 for(
unsigned int i=0; i<vectorImage->GetVectorLength(); ++i)
225 indexSelectionFilter->SetIndex( i );
227 gaussian_filter->SetInput( indexSelectionFilter->GetOutput() );
228 gaussian_filter->SetVariance( m_SmoothingSigma );
230 vec_composer->SetInput(i, gaussian_filter->GetOutput() );
232 gaussian_filter->Update();
237 vec_composer->Update();
239 catch(
const itk::ExceptionObject &e)
241 mitkThrow() <<
"[VectorImage.GaussianSmoothing] !! Failed with ITK Exception: " << e.what();
244 this->m_ProcessedInputImage = vec_composer->GetOutput();
248 this->m_ProcessedInputImage =
const_cast<InputImageType*
>( this->GetInput() );
252 template<
class TInputPixelType,
class TOutputPixelType>
271 template<
class TInputPixelType,
class TOutputPixelType>
277 this->SetReferenceBValue(bvalue);
278 this->SetGradientDirections( gradients );
281 return this->GetSnapshot( input, this->m_BValues, kf_conf );
285 template<
class TInputPixelType,
class TOutputPixelType>
291 vnl_vector<double> initial_position;
296 initial_position.set_size(2);
297 initial_position[0] = this->m_InitialPosition[0];
298 initial_position[1] = this->m_InitialPosition[1];
302 initial_position.set_size(3);
303 initial_position = this->m_InitialPosition;
311 result.
m_D = initial_position[0];
312 result.
m_K = initial_position[1];
316 result.
m_f = 1 - initial_position[2] / std::fmax(0.01, input.GetElement(0));
323 auto bvalueIter = bvalues.begin();
324 unsigned int unused_values = 0;
325 while( bvalueIter != bvalues.end() )
335 vnl_vector<double> fit_measurements( input.Size() - unused_values, 0 );
336 vnl_vector<double> fit_bvalues( input.Size() - unused_values, 0 );
339 vnl_vector<double> orig_measurements( input.Size(), 0 );
341 bvalueIter = bvalues.begin();
342 unsigned int running_index = 0;
343 unsigned int skip_count = 0;
344 while( bvalueIter != bvalues.end() )
352 fit_measurements[ running_index - skip_count ] = input.GetElement(running_index);
353 fit_bvalues[ running_index - skip_count ] = *bvalueIter;
356 orig_measurements[ running_index ] = input.GetElement(running_index);
373 template<
class TInputPixelType,
class TOutputPixelType>
377 if( this->m_ReferenceBValue < 0)
379 itkExceptionMacro( <<
"Specify reference b-value prior to setting the gradient directions." );
382 if( gradients->Size() == 0 )
384 itkExceptionMacro( <<
"Empty gradient directions container retrieved" );
387 vnl_vector<double> vnl_bvalues( gradients->Size(), 0 );
390 auto grIter = gradients->Begin();
391 unsigned int index = 0;
392 while( grIter != gradients->End() )
394 const double twonorm = grIter.Value().two_norm();
395 vnl_bvalues( index++ ) = this->m_ReferenceBValue * twonorm * twonorm;
400 this->m_BValues = vnl_bvalues;
405 template<
class TInputPixelType,
class TOutputPixelType>
409 unsigned int param_size = 2 +
static_cast<int>( this->m_OmitBZero );
410 assert( x0.size() == param_size );
412 this->m_InitialPosition = x0;
415 template<
class TInputPixelType,
class TOutputPixelType>
420 itk::ImageRegionIteratorWithIndex< OutputImageType > dImageIt(dImage, outputRegionForThread);
421 dImageIt.GoToBegin();
424 itk::ImageRegionIteratorWithIndex< OutputImageType > kImageIt(kImage, outputRegionForThread);
425 kImageIt.GoToBegin();
427 typedef itk::ImageRegionConstIteratorWithIndex< InputImageType > InputIteratorType;
428 InputIteratorType inputIter( m_ProcessedInputImage, outputRegionForThread );
429 inputIter.GoToBegin();
431 typedef itk::ImageRegionConstIteratorWithIndex< MaskImageType > MaskIteratorType;
432 MaskIteratorType maskIter( this->m_MaskImage, outputRegionForThread );
433 maskIter.GoToBegin();
437 fit_config.
fit_scale = this->m_ScaleForFitting;
440 fit_config.
K_limits = this->m_KurtosisBounds;
442 vnl_vector<double> initial_position;
443 if( !this->m_OmitBZero )
445 initial_position.set_size(2);
446 initial_position[0] = this->m_InitialPosition[0];
447 initial_position[1] = this->m_InitialPosition[1];
452 initial_position.set_size(3);
453 initial_position = this->m_InitialPosition;
456 while( !inputIter.IsAtEnd() )
459 vnl_vector<double> result = initial_position;
462 if( maskIter.Get() > 0 )
464 FitSingleVoxel( inputIter.Get(), this->m_BValues, result, fit_config );
473 dImageIt.Set( result[0] );
474 kImageIt.Set( result[1] );
A fitting function handling the unweighted signal b_0 as a fitted parameter.
itk::SmartPointer< Self > Pointer
DiffusionKurtosisReconstructionImageFilter()
Image< OutputPixelType, 3 > OutputImageType
vnl_vector< double > measurements
vnl_vector_fixed< double, 2 > m_KurtosisBounds
void set_fit_logscale(bool flag)
vnl_vector< double > m_InitialPosition
void AfterThreadedGenerateData() override
vnl_vector< double > fit_bvalues
vnl_vector_fixed< double, 2 > K_limits
void GenerateOutputInformation() override
Struct describing a result (and the data) of a Kurtosis model fit.
Superclass::InputImageType InputImageType
Superclass::OutputImageRegionType OutputImageRegionType
vnl_vector< double > fit_measurements
KurtosisSnapshot GetSnapshot(const itk::VariableLengthVector< TInputPixelType > &input, vnl_vector< double > bvalues, KurtosisFitConfiguration kf_conf)
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) override
void SetImageMask(MaskImageType::Pointer mask)
void SetGradientDirections(GradientDirectionContainerType::Pointer gradients)
MITKCORE_EXPORT const ScalarType eps
vnl_vector< double > bvalues
static void FitSingleVoxel(const itk::VariableLengthVector< TInputPixelType > &input, const vnl_vector< double > &bvalues, vnl_vector< double > &result, itk::KurtosisFitConfiguration kf_config)
void SetInitialSolution(const vnl_vector< double > &x0)
void BeforeThreadedGenerateData() override
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.