1 /*===================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 See LICENSE.txt or http://www.mitk.org for details.
15 ===================================================================*/
16 /*=========================================================================
18 3 Program: Tensor ToolKit - TTK
19 4 Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.txx $
21 6 Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
22 7 Version: $Revision: 68 $
24 9 Copyright (c) INRIA 2010. All rights reserved.
25 10 See LICENSE.txt for details.
27 12 This software is distributed WITHOUT ANY WARRANTY; without even
28 13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
29 14 PURPOSE. See the above copyright notices for more information.
31 16 =========================================================================*/
32 #ifndef _itk_TensorImageToDiffusionImageFilter_txx_
33 #define _itk_TensorImageToDiffusionImageFilter_txx_
36 #include "itkTensorImageToDiffusionImageFilter.h"
37 #include "itkTensorToL2NormImageFilter.h"
38 #include "itkRescaleIntensityImageFilter.h"
39 #include <itkImageRegionIterator.h>
40 #include <itkImageRegionConstIterator.h>
45 template <class TInputScalarType, class TOutputScalarType>
47 TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
48 ::BeforeThreadedGenerateData()
51 if( m_GradientList->Size()==0 )
53 throw itk::ExceptionObject (__FILE__,__LINE__,"Error: gradient list is empty, cannot generate DWI.");
56 if( m_BaselineImage.IsNull() )
58 // create a B0 image by taking the norm of the tensor field * scale:
59 typedef itk::TensorToL2NormImageFilter<InputImageType, itk::Image<InputScalarType,3> >
60 TensorToL2NormFilterType;
62 typename TensorToL2NormFilterType::Pointer myFilter1 = TensorToL2NormFilterType::New();
63 myFilter1->SetInput (this->GetInput());
69 catch (itk::ExceptionObject &e)
75 typename itk::RescaleIntensityImageFilter< itk::Image<InputScalarType,3>, BaselineImageType>::Pointer rescaler=
76 itk::RescaleIntensityImageFilter<itk::Image<InputScalarType,3>, BaselineImageType>::New();
78 rescaler->SetOutputMinimum ( m_Min );
79 rescaler->SetOutputMaximum ( m_Max );
80 rescaler->SetInput ( myFilter1->GetOutput() );
85 catch (itk::ExceptionObject &e)
91 m_BaselineImage = rescaler->GetOutput();
94 typename OutputImageType::Pointer outImage = OutputImageType::New();
95 outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
96 outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
97 outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
98 outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
99 outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
100 outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
101 outImage->SetVectorLength(m_GradientList->Size());
102 outImage->Allocate();
104 this->SetNumberOfRequiredOutputs (1);
105 this->SetNthOutput (0, outImage);
109 template <class TInputScalarType, class TOutputScalarType>
110 void TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
111 ::ThreadedGenerateData (const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId )
113 typedef ImageRegionIterator<OutputImageType> IteratorOutputType;
114 typedef ImageRegionConstIterator<InputImageType> IteratorInputType;
115 typedef ImageRegionConstIterator<BaselineImageType> IteratorBaselineType;
117 unsigned long numPixels = outputRegionForThread.GetNumberOfPixels();
118 unsigned long step = numPixels/100;
119 unsigned long progress = 0;
121 IteratorOutputType itOut (this->GetOutput(), outputRegionForThread);
122 IteratorInputType itIn (this->GetInput(), outputRegionForThread);
123 IteratorBaselineType itB0 (m_BaselineImage, outputRegionForThread);
125 typedef ImageRegionConstIterator< MaskImageType > IteratorMaskImageType;
126 IteratorMaskImageType itMask;
128 if( m_MaskImage.IsNotNull() )
130 itMask = IteratorMaskImageType( m_MaskImage, outputRegionForThread);
136 this->UpdateProgress (0.0);
139 while(!itIn.IsAtEnd())
142 if( this->GetAbortGenerateData() )
144 throw itk::ProcessAborted(__FILE__,__LINE__);
147 InputPixelType T = itIn.Get();
149 BaselinePixelType b0 = itB0.Get();
152 out.SetSize(m_GradientList->Size());
156 if( m_MaskImage.IsNotNull() )
158 maskvalue = itMask.Get();
162 std::vector<unsigned int> b0_indices;
165 for( unsigned int i=0; i<m_GradientList->Size(); i++)
167 GradientType g = m_GradientList->at(i);
169 // normalize vector so the following computations work
170 const double twonorm = g.two_norm();
171 if( twonorm < vnl_math::eps )
173 b0_indices.push_back(i);
177 GradientType gn = g.normalize();
189 2 * T[1]*S[1] + T[3]*S[3] +
190 2 * T[2]*S[2] + 2 * T[4]*S[4] + T[5]*S[5];
192 // check for corrupted tensor
195 // estimate the bvalue from the base value and the norm of the gradient
196 // - because of this estimation the vector have to be normalized beforehand
197 // otherwise the modelled signal is wrong ( i.e. not scaled properly )
198 const double bval = m_BValue * twonorm * twonorm;
199 out[i] = static_cast<OutputScalarType>( maskvalue * 1.0 * b0 * exp ( -1.0 * bval * res ) );
204 for(unsigned int idx = 0; idx < b0_indices.size(); idx++ )
206 out[b0_indices.at(idx)] = b0;
212 if( threadId==0 && step>0)
214 if( (progress%step)==0 )
216 this->UpdateProgress ( double(progress)/double(numPixels) );
229 this->UpdateProgress (1.0);
233 template <class TInputScalarType, class TOutputScalarType>
235 TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
236 ::UpdateOutputInformation()
238 // Calls to superclass updateoutputinformation
239 Superclass::UpdateOutputInformation();
241 this->GetOutput()->SetVectorLength( m_GradientList->size() );
244 } // end of namespace