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
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.