DMRITool  v0.1.1-139-g860d86b4
Diffusion MRI Tool
itkODFFromSPFImageFilter.hxx
Go to the documentation of this file.
1 
18 #ifndef __itkODFFromSPFImageFilter_hxx
19 #define __itkODFFromSPFImageFilter_hxx
20 
21 #include <itkProgressReporter.h>
23 #include "utl.h"
26 
27 namespace itk
28 {
29 
30 template< class TInputImage, class TOutputImage >
31 void
34 {
35  Superclass::GenerateOutputInformation();
36  typename TOutputImage::Pointer outputPtr = this->GetOutput();
37  unsigned int numberOfComponentsPerPixel = utl::RankToDimSH(this->GetSHRank());
38  outputPtr->SetNumberOfComponentsPerPixel(numberOfComponentsPerPixel);
39 }
40 
41 template< class TInputImage, class TOutputImage >
42 void
45 {
46  Superclass::VerifyInputParameters();
47  utlGlobalException(this->m_ODFOrder<-1, "m_ODFOrder should be -1, 0, 1, ...");
48  utlGlobalException(this->m_ODFOrder==-1 && this->m_BMax<=0,"for Funk-Radon transform, bvalue can not be negative!");
49 }
50 
51 template< class TInputImage, class TOutputImage >
52 void
55 {
56  utlException(this->m_SHRank<0 || this->m_RadialRank<0, "need to set this->m_SHRank and this->m_RadialRank");
57 
58  double qValue;
59  if (this->m_BMax>0)
60  qValue = std::sqrt(this->m_BMax/(4*M_PI*M_PI*this->m_Tau));
61  else
62  {
63  utlException(this->m_ODFOrder==-1,"for Funk-Radon transform, this->m_BMax can not be negative");
64  qValue = -1;
65  }
66  double C = qValue>0 ? qValue*qValue/this->m_BasisScale : -1;
67  if ( C>0)
68  {
69  if (this->GetDebug())
70  {
71  std::cout << "integration in a disk" << std::endl;
72  std::cout << "C = " << C << std::endl;
73  std::cout << "qValue = " << qValue << ", m_BasisScale = " << this->m_BasisScale << std::endl;
74  }
75  }
76  else
77  {
78  if (this->GetDebug())
79  {
80  std::cout << "integration in the whole plane" << std::endl;
81  // C should be -1
82  std::cout << "C = " << C << ", m_BasisScale = " << this->m_BasisScale << std::endl;
83  }
84  }
85 
86  if (this->m_BasisType==Superclass::SPF || this->m_BasisType==Superclass::DSPF)
87  {
88  typedef SphericalPolarFourierRadialGenerator<double> SPFGenerator;
89  int n_b_sh = (this->m_SHRank+1)*(this->m_SHRank+2)/2;
90  int n_b_ra = this->m_RadialRank+1;
91  int n_b = n_b_sh * n_b_ra;
92  this->m_SPFToFeatureTransform = MatrixPointer (new MatrixType(n_b_sh,n_b) );
93  this->m_SPFToFeatureTransform->Fill(0.0);
94  if (this->m_BasisType==Superclass::SPF)
95  {
96  for ( int n = 0; n <= this->m_RadialRank; n += 1 )
97  {
98  double temp;
99  double first_temp = 2.0 / std::pow((double)this->m_BasisScale,(double)1.5) * utl::Factorial(n) / utl::Gamma(n+1.5);
100  first_temp = std::sqrt(first_temp);
101  switch ( this->m_ODFOrder )
102  {
103  case -1 :
104  {
105  // std::cout << "order 0, ODF by Tuch, Funk-Radon Transform" << std::endl;
106  temp = first_temp * std::exp( -1.0*qValue*qValue / (2*this->m_BasisScale) ) * utl::Lagurre(n, 0.5, qValue*qValue/this->m_BasisScale);
107  for ( int j = 0; j < n_b_sh; j += 1 )
108  (*this->m_SPFToFeatureTransform)(j,n*n_b_sh+j) = m_P(j) * temp;
109  break;
110  }
111  case 0 :
112  {
113  // std::cout << "order 0, ODF by Tuch, integrate in a disk or a plane" << std::endl;
114  double second_temp = 0;
115  if ( C>0 )
116  {
117  // formula (7)
118  for ( int i = 0; i <= n; i += 1 )
119  second_temp += utl::Binomial(n+0.5,n-i) * std::pow((double)-2.0,(double)i) * utl::GammaLower(i+1,0.5*C) / utl::Factorial(i);
120  }
121  else
122  {
123  // formula (6)
124  for ( int i = 0; i <= n; i += 1 )
125  {
126  double tmp = utl::Binomial(i-0.5,i);
127  second_temp += (n-i)%2==0 ? tmp : -tmp;
128  }
129  }
130  second_temp *= this->m_BasisScale;
131  temp = first_temp*second_temp;
132  //**************************************************************
133 
134  for ( int j = 0; j < n_b_sh; j += 1 )
135  (*this->m_SPFToFeatureTransform)(j,n*n_b_sh+j) = m_P(j) * temp;
136  break;
137  }
138  case 2 :
139  {
140  // std::cout << "order 2, OPDF (maginal pdf), integrate in a disk or a plane" << std::endl;
141  // NOTE: -1 is in transformBasis
142  double second_temp = 0;
143  if ( C>0 )
144  {
145  // formula (15)
146  for ( int i = 1; i <= n; i += 1 )
147  {
148  double tmp = utl::Binomial(n+0.5,n-i) * std::pow((double)2.0,(double)i) * utl::GammaLower(i,0.5*C) / utl::Factorial(i);
149  second_temp += (i%2==0 ? tmp : -tmp);
150  }
151  }
152  else
153  {
154  // formula (16)
155  for ( int i = 1; i <= n; i += 1 )
156  {
157  double tmp = utl::Binomial(n+0.5,n-i) * std::pow((double)2.0,(double)i) / i;
158  second_temp += (i%2==0 ? tmp : -tmp);
159  }
160  }
161  second_temp *= 0.5;
162  temp = first_temp*second_temp;
163  //**************************************************************
164 
165  for ( int j = 0; j < n_b_sh; j += 1 )
166  (*this->m_SPFToFeatureTransform)(j,n*n_b_sh+j) = -1.0 * m_P(j) * m_L(j) * temp;
167  break;
168  }
169  default :
170  utlGlobalException(true,"wrong type");
171  break;
172  }
173  }
174 
175  }
176  else
177  {
178  utlGlobalException(true, "TODO");
179  }
180  }
181  if (this->GetDebug())
182  utl::PrintUtlMatrix(*this->m_SPFToFeatureTransform, "m_SPFToFeatureTransform");
183 }
184 
185 template< class TInputImage, class TOutputImage >
186 typename LightObject::Pointer
187 ODFFromSPFImageFilter< TInputImage, TOutputImage >
188 ::InternalClone() const
189 {
190  typename LightObject::Pointer loPtr = Superclass::InternalClone();
191 
192  typename Self::Pointer rval = dynamic_cast<Self *>(loPtr.GetPointer());
193  if(rval.IsNull())
194  {
195  itkExceptionMacro(<< "downcast to type " << this->GetNameOfClass()<< " failed.");
196  }
197  rval->m_P = m_P;
198  rval->m_L = m_L;
199  rval->m_ODFOrder = m_ODFOrder;
200  rval->m_BMax = m_BMax;
201  return loPtr;
202 }
203 
204 template< class TInputImage, class TOutputImage >
205 void
206 ODFFromSPFImageFilter< TInputImage, TOutputImage >
207 ::BeforeThreadedGenerateData ( )
208 {
209  // utlShowPosition(true);
210  this->SetSPFIEstimator();
211 
212  int n_b_sh = (this->m_SHRank+1)*(this->m_SHRank+2)/2;
213  m_P.ReSize(n_b_sh);
214  m_L.ReSize(n_b_sh);
215  int j = 0;
216  double diag;
217  for(int l = 0; l <= this->m_SHRank; l+=2)
218  {
219  diag = 2*M_PI* utl::LegendrePolynomialAt0(l);
220  for(int m = -l; m <= l; m++)
221  {
222  m_L(j) = -l*(l+1);
223  m_P(j) = diag;
224  j++;
225  }
226  }
227  // utl::PrintUtlVector(m_L,"m_L");
228  // utl::PrintUtlVector(m_P,"m_P");
229  Superclass::BeforeThreadedGenerateData();
230 }
231 
232 template <class TInputImage, class TOutputImage>
233 void
234 ODFFromSPFImageFilter<TInputImage,TOutputImage>
235 ::ThreadedGenerateData( const typename TOutputImage::RegionType &outputRegionForThread, ThreadIdType threadId)
236 {
237  // utlShowPosition(true);
238  typename TInputImage::ConstPointer inputPtr = this->GetInput();
239  typename TOutputImage::Pointer outputPtr = this->GetOutput();
240 
241  // Define the iterators
242  ImageRegionConstIteratorWithIndex<TInputImage> inputIt(inputPtr, outputRegionForThread);
243  ImageRegionIteratorWithIndex<TOutputImage> outputIt(outputPtr, outputRegionForThread);
244  ImageRegionIteratorWithIndex<MaskImageType> maskIt;
245  if (this->IsMaskUsed())
246  maskIt = ImageRegionIteratorWithIndex<MaskImageType>(this->m_MaskImage, outputRegionForThread);
247 
248  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
249  typename TInputImage::PixelType inputPixel;
250  typename TInputImage::IndexType inputIndex;
251  typename TOutputImage::PixelType outputPixel;
252 
253  unsigned int outputDim = outputPtr->GetNumberOfComponentsPerPixel();;
254  outputPixel.SetSize(outputDim);
255  unsigned int inputDim = inputPtr->GetNumberOfComponentsPerPixel();
256  inputPixel.SetSize(inputDim);
257 
258  inputIt.GoToBegin();
259  outputIt.GoToBegin();
260  VectorType spfVec, result;
261 
262  Pointer selfClone = this->Clone();
263 
264  while( !inputIt.IsAtEnd() )
265  {
266  if (!this->IsMaskUsed() || (this->IsMaskUsed() && maskIt.Get()>0))
267  {
268  inputPixel = inputIt.Get();
269  if (inputPixel.GetSquaredNorm()>1e-8)
270  {
271  inputIndex = inputIt.GetIndex();
272  if (this->GetDebug())
273  std::cout << "index = " << inputIndex << std::endl << std::flush;
274 
275  if (!IsImageEmpty(this->m_ScaleImage))
276  selfClone->SetBasisScale(this->m_ScaleImage->GetPixel(inputIndex));
277  if (selfClone->m_SPFToFeatureTransform->Size()==0)
278  selfClone->ComputeSPFToFeatureTransform();
279 
280  spfVec = utl::VariableLengthVectorToUtlVector(inputPixel);
281  switch ( this->m_ODFOrder )
282  {
283  case -1 :
284  {
285  // if (this->GetDebug())
286  // std::cout << "order 0, ODF by Tuch, Funk-Radon Transform" << std::endl;
287  utlException(this->m_BMax<=0,"for Funk-Radon transform, bvalue can not be negative");
288  result = (*selfClone->m_SPFToFeatureTransform) * spfVec;
289  double normalizefactor = 1.0 / (std::sqrt(4*M_PI)*result[0]);
290  result %= normalizefactor;
291  break;
292  }
293  case 0 :
294  {
295  // if (this->GetDebug())
296  // std::cout << "order 0, ODF by Tuch, integrate in a disk or a plane" << std::endl;
297  result = (*selfClone->m_SPFToFeatureTransform) * spfVec;
298  double normalizefactor = 1.0 / (std::sqrt(4*M_PI)*result[0]);
299  result %= normalizefactor;
300  break;
301  }
302  case 2 :
303  {
304  // if (this->GetDebug())
305  // std::cout << "order 2, OPDF (maginal pdf), integrate in a disk or a plane" << std::endl;
306  result = (*selfClone->m_SPFToFeatureTransform) * spfVec / (8*M_PI*M_PI);
307  result[0] += 1/std::sqrt(4*M_PI);
308  break;
309  }
310  default :
311  utlGlobalException(true,"Wrong type");
312  break;
313  }
314  if (this->GetDebug())
315  utl::PrintUtlVector(result, "odf");
316 
317  outputPixel = utl::UtlVectorToVariableLengthVector(result);
318 
319  }
320  else
321  outputPixel.Fill(0.0);
322  }
323  else
324  outputPixel.Fill(0.0);
325 
326  outputIt.Set(outputPixel);
327  progress.CompletedPixel();
328  if (this->IsMaskUsed())
329  ++maskIt;
330  ++inputIt;
331  ++outputIt;
332  progress.CompletedPixel(); // potential exception thrown here
333  }
334 }
335 
336 template< class TInputImage, class TOutputImage >
337 void
338 ODFFromSPFImageFilter< TInputImage, TOutputImage >
339 ::PrintSelf(std::ostream &os, Indent indent) const
340 {
341  Superclass::PrintSelf(os, indent);
342  os << indent
343  << ", m_ODFOrder = " << this->m_ODFOrder
344  << ", m_BMax = " << this->m_BMax
345  << std::endl;
346 }
347 
348 }
349 
350 #endif
351 
352 
353 
void GenerateOutputInformation() ITK_OVERRIDE
void VerifyInputParameters() const ITK_OVERRIDE
helper functions specifically used in dmritool
#define utlException(cond, expout)
Definition: utlCoreMacro.h:548
#define utlGlobalException(cond, expout)
Definition: utlCoreMacro.h:372
void ComputeSPFToFeatureTransform() ITK_OVERRIDE
int RankToDimSH(const int shRank)
Definition: utlDMRI.h:193