Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
itkRadialMultishellToSingleshellImageFilter.cpp
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 
18 Program: Tensor ToolKit - TTK
19 Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx $
20 Language: C++
21 Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
22 Version: $Revision: 68 $
23 
24 Copyright (c) INRIA 2010. All rights reserved.
25 See LICENSE.txt for details.
26 
27 This software is distributed WITHOUT ANY WARRANTY; without even
28 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
29 PURPOSE. See the above copyright notices for more information.
30 
31 =========================================================================*/
32 #ifndef _itk_RadialMultishellToSingleshellImageFilter_cpp_
33 #define _itk_RadialMultishellToSingleshellImageFilter_cpp_
34 #endif
35 
36 #define _USE_MATH_DEFINES
37 
40 
41 
42 namespace itk
43 {
44 
45 
46 template <class TInputScalarType, class TOutputScalarType>
49 {
50  this->SetNumberOfRequiredInputs( 1 );
51  //this->SetNumberOfThreads(1);
52 }
53 
54 template <class TInputScalarType, class TOutputScalarType>
57 {
58  // test whether BvalueMap contains all necessary information
59  if(m_BValueMap.size() == 0)
60  {
61  itkWarningMacro(<< "No BValueMap given: create one using GradientDirectionContainer");
62 
63  GradientDirectionContainerType::ConstIterator gdcit;
64  for( gdcit = m_OriginalGradientDirections->Begin(); gdcit != m_OriginalGradientDirections->End(); ++gdcit)
65  {
66  double bValueKey = int(((m_OriginalBValue * gdcit.Value().two_norm() * gdcit.Value().two_norm())+7.5)/10)*10;
67  m_BValueMap[bValueKey].push_back(gdcit.Index());
68  }
69  }
70 
71  //# BValueMap contains no bZero --> itkException
72  if(m_BValueMap.find(0.0) == m_BValueMap.end())
73  {
74  MITK_INFO << "No ReferenceSignal (BZeroImages) found!";
75  itkExceptionMacro(<< "No ReferenceSignal (BZeroImages) found!");
76  }
77 
78  // [allDirectionsContainer] Gradient DirectionContainer containing all unique directions
79  m_TargetDirectionsIndicies = mitk::gradients::GetAllUniqueDirections(m_BValueMap, m_OriginalGradientDirections);
80  // [sizeAllDirections] size of GradientContainer cointaining all unique directions
81  m_NumberTargetDirections = m_TargetDirectionsIndicies.size();
82  m_TargetGradientDirections = mitk::gradients::CreateNormalizedUniqueGradientDirectionContainer(m_BValueMap,m_OriginalGradientDirections);
83 
84  m_ShellInterpolationMatrixVector.reserve(m_BValueMap.size()-1);
85 
86  // for each shell
87  BValueMap::const_iterator it = m_BValueMap.begin();
88  it++; //skip bZeroIndices
89 
90  unsigned int shellIndex = 0;
91  for(;it != m_BValueMap.end();++it)
92  {
93  //- calculate maxShOrder
94  const IndicesVector currentShell = it->second;
95  unsigned int SHMaxOrder = 12;
96  while( ((SHMaxOrder+1)*(SHMaxOrder+2)/2) > currentShell.size() && ((SHMaxOrder+1)*(SHMaxOrder+2)/2) >= 4 )
97  SHMaxOrder -= 2 ;
98 
99  //- get TragetSHBasis using allDirectionsContainer
100  vnl_matrix<double> sphericalCoordinates;
101  sphericalCoordinates = mitk::gradients::ComputeSphericalFromCartesian(m_TargetDirectionsIndicies, m_OriginalGradientDirections);
102  vnl_matrix<double> TargetSHBasis = mitk::gradients::ComputeSphericalHarmonicsBasis(sphericalCoordinates, SHMaxOrder);
103  //- get ShellSHBasis using currentShellDirections
104  sphericalCoordinates = mitk::gradients::ComputeSphericalFromCartesian(currentShell, m_OriginalGradientDirections);
105  vnl_matrix<double> ShellSHBasis = mitk::gradients::ComputeSphericalHarmonicsBasis(sphericalCoordinates, SHMaxOrder);
106  //- calculate interpolationSHBasis [TargetSHBasis * ShellSHBasis^-1]
107  vnl_matrix_inverse<double> invShellSHBasis(ShellSHBasis);
108  vnl_matrix<double> shellInterpolationMatrix = TargetSHBasis * invShellSHBasis.pinverse();
109  //- save interpolationSHBasis
110  m_ShellInterpolationMatrixVector.push_back(shellInterpolationMatrix);
111 
112  ++shellIndex;
113  }
114 
115  // initialize output image
116  typename OutputImageType::Pointer outImage = static_cast<OutputImageType * >(ProcessObject::GetOutput(0));
117  outImage->SetSpacing( this->GetInput()->GetSpacing() );
118  outImage->SetOrigin( this->GetInput()->GetOrigin() );
119  outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction using bZeroDirection+AllDirectionsContainer
120  outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
121  outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
122  outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
123  outImage->SetVectorLength( 1+m_NumberTargetDirections ); // size of 1(bzeroValue) + AllDirectionsContainer
124  outImage->Allocate();
125 
126  m_ErrorImage = ErrorImageType::New();
127  m_ErrorImage->SetSpacing( this->GetInput()->GetSpacing() );
128  m_ErrorImage->SetOrigin( this->GetInput()->GetOrigin() );
129  m_ErrorImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction using bZeroDirection+AllDirectionsContainer
130  m_ErrorImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
131  m_ErrorImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
132  m_ErrorImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
133  m_ErrorImage->Allocate();
134 
135  MITK_INFO << "Input:" << std::endl << std::endl
136  << " GradientDirections: " << m_OriginalGradientDirections->Size() << std::endl
137  << " Shells: " << (m_BValueMap.size() - 1) << std::endl
138  << " ReferenceImages: " << m_BValueMap[0.0].size() << std::endl;
139 
140  MITK_INFO << "Output:" << std::endl << std::endl
141  << " OutImageVectorLength: " << outImage->GetVectorLength() << std::endl
142  << " TargetDirections: " << m_NumberTargetDirections << std::endl
143  << std::endl;
144 
145 }
146 
147 template <class TInputScalarType, class TOutputScalarType>
148 void
150 ::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType /*threadId*/)
151 {
152  // Get input gradient image pointer
153  typename InputImageType::Pointer inputImage = static_cast< InputImageType * >(ProcessObject::GetInput(0));
154  // ImageRegionIterator for the input image
155  ImageRegionIterator< InputImageType > iit(inputImage, outputRegionForThread);
156  iit.GoToBegin();
157 
158  // Get output gradient image pointer
159  typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(ProcessObject::GetOutput(0));
160  // ImageRegionIterator for the output image
161  ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
162  oit.GoToBegin();
163 
164  // ImageRegionIterator for the output image
165  ImageRegionIterator< ErrorImageType > eit(m_ErrorImage, outputRegionForThread);
166  eit.GoToBegin();
167 
168  // calculate target bZero-Value [b0_t]
169  const IndicesVector IndicesS0 = m_BValueMap[0.0];
170  double AverageS0 = 0.0;
171 
172  unsigned int numberOfShells = m_BValueMap.size()-1;
173 
174  // create empty nxm SignalMatrix containing n->signals/directions (in case of interpolation ~ sizeAllDirections otherwise the size of any shell) for m->shells
175  vnl_matrix<double> SignalMatrix(m_NumberTargetDirections, numberOfShells);
176  // create nx1 targetSignalVector
177 
178  vnl_vector<double> SignalVector(m_NumberTargetDirections);
179  OutputPixelType out;
180  InputPixelType b;
181  BValueMap::const_iterator shellIterator;
182  vnl_matrix<double> NewSignalMatrix (m_NumberTargetDirections, 2);
183  vnl_vector<double> InterpVector;
184  unsigned int shellIndex = 0;
185  // ** walking over each Voxel
186  while(!iit.IsAtEnd())
187  {
188  b = iit.Get();
189  AverageS0=0.0;
190  for(unsigned int i = 0 ; i < IndicesS0.size(); i++){
191  AverageS0 += b[IndicesS0[i]];
192  }
193  AverageS0 /= (double)IndicesS0.size();
194  out = oit.Get();
195  out.SetElement(0,AverageS0);
196 
197  shellIterator = m_BValueMap.begin();
198  shellIterator++; //skip bZeroImages
199 
200  shellIndex = 0;
201  // for each shell
202  while(shellIterator != m_BValueMap.end())
203  {
204  const IndicesVector & currentShell = shellIterator->second;
205  InterpVector.set_size(currentShell.size());
206 
207  // get the raw signal for currente shell (signal for eacht direction)
208  for(unsigned int i = 0 ; i < currentShell.size(); i++)
209  InterpVector.put(i,b[currentShell[i]]);
210 
211  // interpolate the signal using corresponding interpolationSHBasis
212  SignalVector = m_ShellInterpolationMatrixVector.at(shellIndex) * InterpVector;
213 
214  // save interpolated signal column
215  SignalMatrix.set_column(shellIndex, SignalVector);
216 
217  shellIterator++;
218  shellIndex++;
219  }
220 
221  // apply voxel wise signal manipulation functor
222  (*m_Functor)(NewSignalMatrix, /*const &*/SignalMatrix,/*const &*/ AverageS0);
223  SignalVector = NewSignalMatrix.get_column(0);
224 
225  for(unsigned int i = 1 ; i < out.Size(); i ++)
226  out.SetElement(i,SignalVector.get(i-1));
227 
228  eit.Set(NewSignalMatrix.get_column(1).mean());
229 
230  oit.Set(out);
231  ++eit;
232  ++oit;
233  ++iit;
234  }
235 }
236 
237 } // end of namespace
itk::SmartPointer< Self > Pointer
#define MITK_INFO
Definition: mitkLogMacros.h:22
static vnl_matrix< double > ComputeSphericalHarmonicsBasis(const vnl_matrix< double > &QBallReference, const unsigned int &LOrder)
void ThreadedGenerateData(const OutputImageRegionType &, ThreadIdType)
static mitk::gradients::GradientDirectionContainerType::Pointer CreateNormalizedUniqueGradientDirectionContainer(const BValueMap &bValueMap, const GradientDirectionContainerType *origninalGradentcontainer)
static std::vector< unsigned int > GetAllUniqueDirections(const BValueMap &bValueMap, GradientDirectionContainerType *refGradientsContainer)
static vnl_matrix< double > ComputeSphericalFromCartesian(const IndiciesVector &refShell, const GradientDirectionContainerType *refGradientsContainer)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.