DMRITool  v0.1.1-139-g860d86b4
Diffusion MRI Tool
itkSphericalPolarFourierImageFilter.hxx
Go to the documentation of this file.
1 
18 #ifndef __itkSphericalPolarFourierImageFilter_hxx
19 #define __itkSphericalPolarFourierImageFilter_hxx
20 
21 
24 #include "utlVNLBlas.h"
25 #include "utl.h"
26 
27 #include <itkProgressReporter.h>
28 
29 namespace itk
30 {
31 
32 template< class TInputImage, class TOutputImage >
35  m_Gn0(new STDVectorType()),
36  m_G0DWI(new VectorType())
37 {
38  // NOTE: ComputeScale is a virtual function, thus it must be called in derived calss, not in base class
39  this->ComputeScale(true);
40 }
41 
42 template< class TInputImage, class TOutputImage >
43 void
45 ::SetBasisScale(const double scale)
46 {
47  itkShowPositionThreadedLogger(this->GetDebug());
48  double scale_old = this->m_BasisScale;
49  if (scale>0)
50  this->m_BasisScale = scale;
51  else
52  this->ComputeScale(true);
53  itkDebugMacro("setting this->m_BasisScale to " << this->m_BasisScale);
54 
55  if (scale>0 && std::fabs((scale_old-this->m_BasisScale)/this->m_BasisScale)>1e-8)
56  {
57  this->Modified();
58  this->m_BasisRadialMatrix=MatrixPointer(new MatrixType());
59  this->m_BasisMatrix=MatrixPointer(new MatrixType());
60  this->m_BasisMatrixForB0=MatrixPointer(new MatrixType());
61  this->m_Gn0=STDVectorPointer(new STDVectorType());
62  this->m_G0DWI=VectorPointer(new VectorType());
63  }
64 }
65 
66 template< class TInputImage, class TOutputImage >
67 typename LightObject::Pointer
70 {
71  itkShowPositionThreadedLogger(this->GetDebug());
72  typename LightObject::Pointer loPtr = Superclass::InternalClone();
73 
74  typename Self::Pointer rval = dynamic_cast<Self *>(loPtr.GetPointer());
75  if(rval.IsNull())
76  {
77  itkExceptionMacro(<< "downcast to type " << this->GetNameOfClass()<< " failed.");
78  }
79 
80  rval->m_Gn0 = m_Gn0;
81  rval->m_G0DWI = m_G0DWI;
82  return loPtr;
83 }
84 
85 template< class TInputImage, class TOutputImage >
86 double
88 ::ComputeScale(const bool setScale)
89 {
90  itkShowPositionThreadedLogger(this->GetDebug());
91  double scale;
92  double tau = this->m_SamplingSchemeQSpace->GetTau();
93  if (this->m_IsOriginalBasis)
94  scale = 1.0 / (8*M_PI*M_PI*tau*this->m_MD0); // 714.29 (700) scale for SPF basis, dual scale is 1/(4*pi^2*scale)
95  else
96  scale = 2*tau*this->m_MD0; // 3.5462e-5 scale for SPF basis, dual scale is 1/(4*pi^2*scale)
97 
98  // std::cout << "scale=" << scale << std::endl << std::flush;
99  // utlPrintVar3(true, this->m_IsOriginalBasis, tau, this->m_MD0);
100  if (setScale)
101  this->SetBasisScale(scale);
102  if (this->GetDebug())
103  std::cout << "m_BasisScale = " << this->m_BasisScale << std::endl;
104  return scale;
105 }
106 
107 template< class TInputImage, class TOutputImage >
108 std::vector<int>
110 ::GetIndexNLM ( const int index ) const
111 {
112  int sh_b = (this->m_SHRank+1)*(this->m_SHRank+2)/2;
113  int n = index / sh_b;
114  int residual = index - n*sh_b;
115  int j=0;
116  std::vector<int> nlm;
117  nlm.push_back(n);
118  std::vector<int> lm = utl::GetIndexSHlm(residual);
119  nlm.push_back(lm[0]);
120  nlm.push_back(lm[1]);
121  return nlm;
122 }
123 
124 template< class TInputImage, class TOutputImage >
125 int
127 ::GetIndexJ (const int n, const int l, const int m) const
128 {
129  return n*(this->m_SHRank+1)*(this->m_SHRank+2)/2 + utl::GetIndexSHj(l,m);
130 }
131 
132 template< class TInputImage, class TOutputImage >
133 std::vector<int>
135 ::DimToRank ( const int dimm ) const
136 {
137  std::vector<int> result;
138  int radialRank=-1, shRank=-1;
139  for ( int radialRank = 0; radialRank <= 10; radialRank += 1 )
140  {
141  for ( int shRank = 0; shRank <= 12; shRank += 2 )
142  {
143  int dim = RankToDim(false, radialRank, shRank);
144  if (dim==dimm)
145  {
146  result.push_back(radialRank);
147  result.push_back(shRank);
148  return result;
149  }
150  }
151  }
152  utlException(true, "wrong logic");
153  return result;
154 }
155 
156 template< class TInputImage, class TOutputImage >
157 int
159 ::RankToDim (const bool is_radial, const int radialRank, const int shRank) const
160 {
161  int radialRank_real = radialRank>=0?radialRank:this->m_RadialRank;
162  int shRank_real = shRank>=0?shRank:this->m_SHRank;
163  utlException(radialRank_real<0 || shRank_real<0, "wrong rank");
164  if (is_radial)
165  return radialRank_real+1;
166  else
167  return (shRank_real + 1)*(shRank_real + 2)/2*(radialRank_real+1);
168 }
169 
170 template< class TInputImage, class TOutputImage >
171 void
174 {
175  itkShowPositionThreadedLogger(this->GetDebug());
176  typename SPFGenerator::Pointer spf = SPFGenerator::New();
177  m_Gn0 = STDVectorPointer(new STDVectorType(this->m_RadialRank+1,-100));
178  spf->SetSPFType(SPFGenerator::SPF);
179  spf->SetScale(this->m_BasisScale);
180  for ( int i = 0; i < this->m_RadialRank+1; i += 1 )
181  {
182  spf->SetN(i);
183  (*m_Gn0)[i] = spf->Evaluate(0);
184  }
185 }
186 
187 template< class TInputImage, class TOutputImage >
188 void
191 {
192  itkShowPositionThreadedLogger(this->GetDebug());
193  if (this->m_SamplingSchemeQSpace->GetIndicesInShells()->size()==0)
194  this->m_SamplingSchemeQSpace->GroupRadiusValues();
195 
196  m_G0DWI = VectorPointer(new VectorType(this->m_SamplingSchemeQSpace->GetNumberOfSamples(),-100));
197  typename Superclass::SamplingSchemeQSpaceType::Index2DVectorPointer indices = this->m_SamplingSchemeQSpace->GetIndicesInShells();
198  STDVectorPointer qVector = this->m_SamplingSchemeQSpace->GetRadiusVector();
199  for ( int i = 0; i < indices->size(); i += 1 )
200  {
201  typename Superclass::SamplingSchemeQSpaceType::IndexVectorType indexTemp = (*indices)[i];
202  double qq = (*qVector)[ indexTemp[0] ];
203  double val = std::exp(-qq*qq/(2.0*this->m_BasisScale));
204  for ( int j = 0; j < indexTemp.size(); j += 1 )
205  (*m_G0DWI)[ indexTemp[j] ] = val;
206  }
207 }
208 
209 // template< class TInputImage, class TOutputImage >
210 // void
211 // SphericalPolarFourierImageFilter< TInputImage, TOutputImage >
212 // ::VerifyInputParameters() const
213 // {
214 // itkShowPositionThreadedLogger(this->GetDebug());
215 // Superclass::VerifyInputParameters();
216 // }
217 
218 template< class TInputImage, class TOutputImage >
219 void
222 {
223  itkShowPositionThreadedLogger(this->GetDebug());
224 
225  if (this->m_SamplingSchemeQSpace->GetBVector()->size()>0 && this->m_SamplingSchemeQSpace->GetRadiusVector()->size()==0)
226  this->m_SamplingSchemeQSpace->ConvertBVectorToQVector();
227 
228  if (this->m_SamplingSchemeQSpace->GetIndicesInShells()->size()==0)
229  this->m_SamplingSchemeQSpace->GroupRadiusValues();
230 
231  // NOTE: m_BVector.size()==m_QOrientations.size()
232  int n_s, n_b;
233  n_s = this->m_SamplingSchemeQSpace->GetRadiusVector()->size();
234  utlGlobalException( n_s==0, "no q vector");
235 
236  const STDVectorPointer qVector = this->m_SamplingSchemeQSpace->GetRadiusVector();
237  typename Superclass::SamplingSchemeQSpaceType::Index2DVectorPointer indices = this->m_SamplingSchemeQSpace->GetIndicesInShells();
238 
239  std::string threadIDStr = this->ThreadIDToString();
240  if (this->GetDebug())
241  {
242  std::ostringstream msg;
243  msg << threadIDStr << "m_BasisScale = " << this->m_BasisScale << ", m_Tau = " << this->m_SamplingSchemeQSpace->GetTau() << ", numberOfShell = " << indices->size() << std::endl;
244  this->WriteLogger(msg.str());
245  }
246 
247  MatrixPointer B;
248  typename SPFGenerator::Pointer spf = SPFGenerator::New();
249  spf->SetScale(this->m_BasisScale);
250 
251  if (this->m_IsOriginalBasis)
252  {
253  spf->SetSPFType(SPFGenerator::SPF);
254 
255  // the basis of order N has N+1 terms (0,1,...,N)
256  n_b = this->m_RadialRank + 1;
257 
258 
259  if(this->GetDebug())
260  {
261  std::ostringstream msg;
262  msg << threadIDStr << "Generating the "<< n_s << "x" << n_b << " RadialMatrix...\n";
263  this->WriteLogger(msg.str());
264  }
265 
266  B = MatrixPointer(new MatrixType(n_s,n_b));
267 
268  for ( int ib = 0; ib < n_b; ib += 1 )
269  {
270  spf->SetN(ib);
271  for ( int shell = 0; shell < indices->size(); shell += 1 )
272  {
273  typename Superclass::SamplingSchemeQSpaceType::IndexVectorType indexTemp = (*indices)[shell];
274  double qq = (*qVector)[ indexTemp[0] ];
275  double spfVal = spf->Evaluate(qq,false);
276  for ( int js = 0; js < indexTemp.size(); js += 1 )
277  (*B)(indexTemp[js],ib) = spfVal;
278  }
279  }
280 
281  }
282  else
283  {
284  spf->SetSPFType(SPFGenerator::DSPF);
285 
286  n_b = (this->m_RadialRank+1)*(this->m_SHRank/2+1);
287 
288  if(this->GetDebug())
289  {
290  std::ostringstream msg;
291  msg << threadIDStr << "Generating the "<< n_s << "x" << n_b << " RadialMatrix...\n";
292  this->WriteLogger(msg.str());
293  }
294 
295  B = MatrixPointer(new MatrixType(n_s,n_b));
296 
297  for ( int ib = 0; ib < this->m_RadialRank+1; ib += 1 )
298  {
299  spf->SetN(ib);
300  for ( int l = 0; l <= this->m_SHRank; l += 2 )
301  {
302  spf->SetL(l);
303  int col = ib*(this->m_SHRank/2+1)+l/2;
304  for ( int shell = 0; shell < indices->size(); shell += 1 )
305  {
306  typename Superclass::SamplingSchemeQSpaceType::IndexVectorType indexTemp = (*indices)[shell];
307  double qq = (*qVector)[ indexTemp[0] ];
308  double spfVal = spf->Evaluate(qq,false);
309  for ( int js = 0; js < indexTemp.size(); js += 1 )
310  (*B)(indexTemp[js],col) = spfVal;
311  }
312  }
313  }
314 
315  }
316 
317  if(this->GetDebug())
318  {
319  std::ostringstream msg;
320  utl::PrintUtlMatrix(*B,"RadialMatrix", " ", msg << threadIDStr);
321  this->WriteLogger(msg.str());
322  }
323 
324  this->m_BasisRadialMatrix = B;
325 }
326 
327 template< class TInputImage, class TOutputImage >
328 void
331 {
332  itkShowPositionThreadedLogger(this->GetDebug());
333 
334  if (this->m_SamplingSchemeQSpace->GetBVector()->size()>0 && this->m_SamplingSchemeQSpace->GetRadiusVector()->size()==0)
335  this->m_SamplingSchemeQSpace->ConvertBVectorToQVector();
336 
337  if (this->m_SamplingSchemeQSpace->GetIndicesInShells()->size()==0)
338  this->m_SamplingSchemeQSpace->GroupRadiusValues();
339 
340  if (this->m_BasisSHMatrix->Rows()==0)
341  this->ComputeSHMatrix();
342  MatrixPointer B_sh = this->m_BasisSHMatrix;
343 
344  if (this->m_BasisRadialMatrix->Rows()==0)
345  this->ComputeRadialMatrix();
346  MatrixPointer B_ra = this->m_BasisRadialMatrix;
347 
348  MatrixPointer qOrientations = this->m_SamplingSchemeQSpace->GetOrientationsSpherical();
349 
350  int qVector_size = this->m_SamplingSchemeQSpace->GetRadiusVector()->size();
351  int grad_size = qOrientations->Rows();
352 
353  std::string threadIDStr = this->ThreadIDToString();
354  if (this->GetDebug())
355  {
356  std::ostringstream msg;
357  msg << threadIDStr << "this->m_SamplingSchemeQSpace->GetRadiusVector()->size() = " << this->m_SamplingSchemeQSpace->GetRadiusVector()->size() << std::endl;
358  msg << threadIDStr << "qOrientations->Rows() = " << qOrientations->Rows() << std::endl;
359  msg << threadIDStr << "qVector_size = " << qVector_size << std::endl;
360  msg << threadIDStr << "grad_size = " << grad_size << std::endl;
361  this->WriteLogger(msg.str());
362  }
363  utlException(qVector_size!=grad_size, "qVector_size and grad_size should keep the same size");
364  int n_s = qVector_size;
365 
366  // the basis has two parts
367  int n_b_ra = this->m_RadialRank + 1;
368  int n_b_sh = (this->m_SHRank+1)*(this->m_SHRank+2)/2;
369  int n_b = n_b_ra * n_b_sh;
370 
371  if(this->GetDebug())
372  {
373  std::ostringstream msg;
374  msg << threadIDStr << "n_b_ra = " << n_b_ra << std::endl;
375  msg << threadIDStr << "n_b_sh = " << n_b_sh << std::endl;
376  msg << threadIDStr << "n_b = " << n_b << std::endl;
377  msg << threadIDStr << "Generating the "<< n_s << "x" << n_b << " basis matrix...\n";
378  this->WriteLogger(msg.str());
379  }
380 
381  MatrixPointer B(new MatrixType(n_s, n_b));
382  utlException(B_sh->Columns()!=n_b_sh, "the SHMatrix does not have the right width. B_sh=" << *B_sh << ", n_b_sh="<< n_b_sh);
383  utlException(B_sh->Rows()!=B_ra->Rows(), "the SHMatrix and the RadialMatrix do not have the same samples. B_sh="<< *B_sh << ", B_ra=" << *B_ra);
384  // B_sh.print("B_sh",2);
385  // B.print("B",2);
386  utlException(B_sh->Rows()!=B->Rows(), "the SHMatrix and the basisMatrix do not have the same samples. B_sh="<< *B_sh << ", B="<< *B);
387 
388  if (this->m_IsOriginalBasis)
389  {
390  utlException(B_ra->Columns()!=n_b_ra, "the RadialMatrix does not have the right width");
391 
392  // utl::Tic(std::cout<<"index start");
393  double *B_sh_data = B_sh->GetData();
394  double *B_ra_data = B_ra->GetData();
395  double *B_data = B->GetData();
396  int index_ra=0, index_B=0;
397  std::vector<int> index_sh(n_b_ra,0);
398  for ( int k = 0; k < n_s; k += 1 )
399  {
400  for ( int i = 0; i < n_b_ra; i += 1 )
401  {
402  for ( int j = 0; j < n_b_sh; j += 1 )
403  {
404  B_data[index_B] = B_ra_data[index_ra] * B_sh_data[index_sh[i] ];
405  // (*B)(k,i*n_b_sh+j) = (*B_ra_data)(k,i) * (*B_sh)(k,j);
406  index_sh[i]++;
407  index_B++;
408  }
409  index_ra++;
410  }
411  }
412  // utl::Toc();
413 
414  // utl::Tic(std::cout<<"() start");
415  // for ( int i = 0; i < n_b_ra; i += 1 )
416  // for ( int j = 0; j < n_b_sh; j += 1 )
417  // for ( int k = 0; k < n_s; k += 1 )
418  // {
419  // (*B)(k,i*n_b_sh+j) = (*B_ra)(k,i) * (*B_sh)(k,j);
420  // }
421  // utl::Toc();
422  }
423  else
424  {
425  utlException(B_ra->Columns()!=n_b_ra*(this->m_SHRank/2+1), "the RadialMatrix does not have the right width");
426  for ( int n = 0; n < n_b_ra; n += 1 )
427  {
428  int jj = 0;
429  for ( int l = 0; l <= this->m_SHRank; l += 2 )
430  {
431  int col_ra = n*(this->m_SHRank/2+1)+l/2;
432  for ( int m = -l; m <= l; m += 1 )
433  {
434  int col = n*n_b_sh+jj;
435  for ( int k = 0; k < n_s; k += 1 )
436  {
437  (*B)(k,col) = (*B_ra)(k,col_ra) * (*B_sh)(k,jj);
438  }
439  jj++;
440  }
441  }
442  }
443  }
444 
445  // // add large weight for constrains b=0, (now bVector has no 0)
446  // if ( !this->m_IsAnalyticalB0 && std::abs(this->m_B0Weight-1)>1e-8 && this->m_B0Weight>0)
447  // {
448  // std::vector<int> index = utl::FindVector(*this->m_SamplingSchemeQSpace->GetRadiusVector() , double(0) , double(1e-6));
449  // if (this->GetDebug())
450  // {
451  // std::cout << "use this->m_B0Weight = " << this->m_B0Weight << "when computing basis matrix" << std::endl;
452  // utl::PrintVector(index,"index");
453  // }
454  // for ( int i = 0; i < index.size(); i += 1 )
455  // {
456  // for ( int j = 0; j < B->Columns(); j += 1 )
457  // {
458  // (*B)(index[i],j) *= this->m_B0Weight;
459  // }
460  // }
461  // }
462 
463  if(this->GetDebug())
464  {
465  std::ostringstream msg;
466  utl::PrintUtlMatrix(*B,"BasisMatrix", " ", msg<< threadIDStr);
467  this->WriteLogger(msg.str());
468  }
469 
470  this->m_BasisMatrix = B;
471 }
472 
473 template< class TInputImage, class TOutputImage >
474 void
477 {
478  itkShowPositionThreadedLogger(this->GetDebug());
479  Pointer selfClone = this->Clone();
480  selfClone->m_BasisMatrix = MatrixPointer(new MatrixType());
481  selfClone->m_BasisRadialMatrix = MatrixPointer(new MatrixType());
482  selfClone->m_BasisSHMatrix = MatrixPointer(new MatrixType());
483  selfClone->m_SamplingSchemeQSpace = SamplingSchemeQSpaceType::New();
484  SamplingSchemeQSpacePointer sampling = selfClone->GetSamplingSchemeQSpace();
485  static MatrixPointer grad = utl::ReadGrad<double>(3, DIRECTION_NODUPLICATE, CARTESIAN_TO_CARTESIAN);
486  STDVectorPointer b0Vector = STDVectorPointer( new STDVectorType(grad->Rows(),0.0));
487  sampling->SetBVector(b0Vector);
488  sampling->SetOrientationsCartesian(grad);
489  selfClone->ComputeBasisMatrix();
490  this->m_BasisMatrixForB0 = selfClone->GetBasisMatrix();
491 } // ----- end of method EAP<T>::<method> -----
492 
493 template< class TInputImage, class TOutputImage >
494 void
497 {
498  itkShowPositionThreadedLogger(this->GetDebug());
499 
500  int n_b_sh = (this->m_SHRank+1)*(this->m_SHRank+2)/2;
501  int n_b_ra = this->m_RadialRank + 1;
502 
503  utlException((this->m_EstimationType==Self::LS || this->m_EstimationType==Self::L1_2) && this->m_LambdaSpherical<0 && this->m_LambdaRadial<0, "need to set m_LambdaSpherical and m_LambdaSpherical");
504  utlException((this->m_EstimationType==Self::L1_DL) && this->m_LambdaL1<0, "need to set m_LambdaL1");
505  if (this->m_EstimationType!=Self::L1_DL)
506  {
507  this->m_RegularizationWeight=VectorPointer( new VectorType(!this->m_IsAnalyticalB0?this->RankToDim():(n_b_sh*this->m_RadialRank)) );
508  for ( int i = 0; i <= ((!this->m_IsAnalyticalB0)?this->m_RadialRank:(this->m_RadialRank-1)); i += 1 )
509  {
510  int j = 0;
511  for ( int l = 0; l <= this->m_SHRank; l += 2 )
512  {
513  double lambda=0;
514  if (this->m_IsAnalyticalB0)
515  lambda = this->m_LambdaSpherical*l*l*(l+1)*(l+1) + this->m_LambdaRadial*(i+1)*(i+1)*(i+2)*(i+2); // use order 1,2,...,N, do not use i=0
516  else
517  lambda = this->m_LambdaSpherical*l*l*(l+1)*(l+1) + this->m_LambdaRadial*i*i*(i+1)*(i+1);
518  for ( int m = -l; m <= l; m += 1 )
519  {
520  if (this->m_EstimationType==Self::L1_2 || this->m_EstimationType==Self::LS)
521  (*this->m_RegularizationWeight)[i*n_b_sh+j] = lambda;
522  j++;
523  }
524  }
525  }
526  }
527  else
528  {
529  if (this->m_BasisCombinationMatrix->Size()==0)
530  {
532  }
533  if (this->GetDebug())
534  utl::PrintUtlMatrix(*this->m_BasisCombinationMatrix, "*this->m_BasisCombinationMatrix");
535 
536  if (this->m_BasisEnergyDL->Size()==0)
537  {
538  if (std::abs(this->m_BasisEnergyPowerDL)>1e-10)
539  {
540  std::vector<double> vecTemp;
542  *this->m_BasisEnergyDL = utl::StdVectorToUtlVector(vecTemp);
543  *this->m_BasisEnergyDL /= this->m_BasisEnergyDL->GetMean();
544 
545  if (std::abs(this->m_BasisEnergyPowerDL-1)>1e-10)
546  utl::PowerVector(this->m_BasisEnergyDL->Begin(), this->m_BasisEnergyDL->End(), this->m_BasisEnergyPowerDL);
547  }
548  else
549  {
550  this->m_BasisEnergyDL=VectorPointer(new VectorType(this->m_BasisCombinationMatrix->Columns()));
551  this->m_BasisEnergyDL->Fill(1.0);
552  }
553  }
554  if (this->GetDebug())
555  utl::PrintUtlVector(*this->m_BasisEnergyDL, "*this->m_BasisEnergyDL");
556 
557  utlException(this->m_BasisMatrix->Size()>0 && this->m_BasisCombinationMatrix->Rows()!=this->m_BasisMatrix->Columns()-n_b_sh, "wrong size of dictionary. m_BasisCombinationMatrix->Rows()="<<this->m_BasisCombinationMatrix->Rows() <<", BasisMatrix->Columns()-n_b_sh="<< this->m_BasisMatrix->Columns()-n_b_sh);
558  utlException(this->m_BasisMatrix->Size()>0 && this->m_BasisCombinationMatrix->Columns()!=this->m_BasisEnergyDL->Size(), "wrong size of dictionary. this->m_BasisEnergyDL.size()="<<this->m_BasisEnergyDL->Size());
559 
560  this->m_RegularizationWeight=VectorPointer(new VectorType(this->m_BasisEnergyDL->Size()) );
561  for ( int i = 0; i < this->m_BasisEnergyDL->Size(); i += 1 )
562  {
563  if (this->m_EstimationType==Self::L1_DL)
564  (*this->m_RegularizationWeight)[i] = this->m_LambdaL1 / (*this->m_BasisEnergyDL)[i];
565  else
566  (*this->m_RegularizationWeight)[i] = this->m_LambdaL2 / (*this->m_BasisEnergyDL)[i];
567  }
568  }
569 
570 }
571 
572 template< class TInputImage, class TOutputImage >
573 void
576 {
577  itkShowPositionThreadedLogger(this->GetDebug());
578  Superclass::BeforeThreadedGenerateData();
579 
580  if (this->m_SamplingSchemeQSpace->GetBVector()->size()>0 && this->m_SamplingSchemeQSpace->GetRadiusVector()->size()==0)
581  this->m_SamplingSchemeQSpace->ConvertBVectorToQVector();
582 
583  if (this->m_SamplingSchemeQSpace->GetIndicesInShells()->size()==0)
584  this->m_SamplingSchemeQSpace->GroupRadiusValues();
585 
586  int n_b_sh = (this->m_SHRank+1)*(this->m_SHRank+2)/2;
587  int n_b_ra = this->m_RadialRank + 1;
588  typename SPFGenerator::Pointer spf = SPFGenerator::New();
589 
590  if (!this->m_IsAnalyticalB0)
591  {
592  std::cout << "Use numerical way for constraint E(0)=1" << std::endl << std::flush;
593  this->ComputeBasisMatrixForB0();
594  }
595  else
596  {
597  if (m_Gn0->size()==0)
598  {
599  this->ComputeRadialVectorForE0InBasis();
600  this->ComputeRadialVectorForE0InDWI();
601  }
602  utlGlobalException(!this->m_IsOriginalBasis, "TODO: use analytical way for E(0)=1 and DSPF basis");
603  std::cout << "Use analytical way for constraint E(0)=1" << std::endl << std::flush;
604  }
605 
606  if (!this->IsAdaptiveScale())
607  {
608  std::cout << "Use the same scale for all voxels!" << std::endl << std::flush;
609  this->ComputeBasisMatrix();
610 
611  MatrixPointer basisMatrix(new MatrixType());
612  if (!this->m_IsAnalyticalB0)
613  {
614  utlGlobalException(this->m_EstimationType==Self::L1_DL, "L1-DL only supports analytical way");
615  *basisMatrix = utl::ConnectUtlMatrix(*this->m_BasisMatrix, *utl::ToMatrix<double>(*this->m_BasisMatrixForB0 % this->m_B0Weight), true);
616  }
617  else
618  {
619  basisMatrix = MatrixPointer(new MatrixType(this->m_BasisMatrix->Rows(), n_b_sh*(n_b_ra-1)));
620  utlException((*m_Gn0)[0]==0, "it should be not zero!, (*m_Gn0)[0]="<< (*m_Gn0)[0]);
621  // utlPrintVar2 (this->_is_b0_analytical, this->m_RadialRank, R_N_0);
622 
623  for ( int i = 0; i < this->m_RadialRank; i += 1 )
624  {
625  for ( int j = 0; j < n_b_sh; j += 1 )
626  {
627  for ( int ss = 0; ss < basisMatrix->Rows(); ss += 1 )
628  {
629  (*basisMatrix)(ss,i*n_b_sh+j) = (*this->m_BasisMatrix)(ss,(i+1)*n_b_sh+j) - (*m_Gn0)[i+1]/(*m_Gn0)[0] * (*this->m_BasisMatrix)(ss,j);
630  }
631  }
632  }
633  if (this->m_EstimationType==Self::L1_DL)
634  {
635  if (this->m_BasisCombinationMatrix->Size()==0)
637  // basisMatrix *= (*this->m_BasisCombinationMatrix);
638  MatrixPointer tmpMat (new MatrixType());
639  utl::ProductUtlMM(*basisMatrix, *this->m_BasisCombinationMatrix, *tmpMat);
640  basisMatrix = tmpMat;
641  }
642  }
643  if (this->GetDebug())
644  utl::PrintUtlMatrix(*basisMatrix, "basisMatrix_InSolver");
645 
646  if (this->m_EstimationType==Self::LS)
647  {
648  this->m_L2Solver->SetA(basisMatrix);
649  }
650  else if (this->m_EstimationType==Self::L1_2 || this->m_EstimationType==Self::L1_DL)
651  {
652  if (this->m_L1SolverType==Self::FISTA_LS)
653  {
654  this->m_L1FISTASolver->SetA(basisMatrix);
655  // this->m_L1FISTASolver->Print(std::cout<<"this->m_L1FISTASolver 0 = ");
656  }
657  else if (this->m_L1SolverType==Self::SPAMS)
658  this->m_L1SpamsSolver->SetA(basisMatrix);
659  else
660  utlException(true, "wrong m_L1SolverType");
661  }
662  }
663  else
664  {
665  std::cout << "Use adaptive scale for each voxel!" << std::endl << std::flush;
666  // calculate scale image
668  typename ScaleFromMDfilterType::Pointer scaleFromMDfilter = ScaleFromMDfilterType::New();
669  scaleFromMDfilter->SetMD0(this->m_MD0);
670  scaleFromMDfilter->SetTau(this->m_SamplingSchemeQSpace->GetTau());
671  scaleFromMDfilter->SetIsOriginalBasis(this->m_IsOriginalBasis);
672  scaleFromMDfilter->SetInput(this->m_MDImage);
673  scaleFromMDfilter->SetInPlace(false); // no inplace
674  scaleFromMDfilter->Update();
675  this->m_ScaleImage = scaleFromMDfilter->GetOutput();
676  }
677 
678  this->ComputeRegularizationWeight();
679  if (this->GetDebug())
680  utl::PrintUtlVector(*this->m_RegularizationWeight, "m_RegularizationWeight");
681 
682  STDVectorPointer qVector = this->m_SamplingSchemeQSpace->GetRadiusVector();
683  if (this->m_EstimationType==Self::LS)
684  {
685  if (this->m_LambdaSpherical>0 || this->m_LambdaRadial>0)
686  {
687  MatrixPointer lamMat (new MatrixType());
688  *lamMat = this->m_RegularizationWeight->GetDiagonalMatrix();
689  this->m_L2Solver->SetLambda(lamMat);
690  }
691  }
692  else if (this->m_EstimationType==Self::L1_2)
693  {
694  if (this->m_L1SolverType==Self::FISTA_LS)
695  {
696  this->m_L1FISTASolver->SetwForInitialization(this->m_RegularizationWeight);
697  this->m_L1FISTASolver->Setw(this->m_RegularizationWeight);
698  // this->m_L1FISTASolver->Setw(*this->m_RegularizationWeight * qVector->size());
699  }
700  else if (this->m_L1SolverType==Self::SPAMS)
701  this->m_L1SpamsSolver->Setw(this->m_RegularizationWeight);
702  }
703  else if (this->m_EstimationType==Self::L1_DL)
704  {
705  if (this->m_L1SolverType==Self::FISTA_LS)
706  {
707  // give a small regularization for the initialization in L2Solver
708  // this->m_L1FISTASolver->SetwForInitialization(*this->m_RegularizationWeight/this->m_RegularizationWeight->two_norm()*1e-7);
709  this->m_L1FISTASolver->SetwForInitialization(utl::ToVector<double> (*this->m_RegularizationWeight % qVector->size()) );
710  // tune the weight based on the size of DWI samples
711  this->m_L1FISTASolver->Setw(utl::ToVector<double>(*this->m_RegularizationWeight % qVector->size()) );
712  }
713  else if (this->m_L1SolverType==Self::SPAMS)
714  this->m_L1SpamsSolver->Setw(utl::ToVector<double>(*this->m_RegularizationWeight % qVector->size()));
715  }
716 
718 
719  // this->m_L2Solver->Initialize();
720  // MatrixType ls = this->m_L2Solver->GetLS();
721  // utl::PrintUtlMatrix(ls,"LS");
722 }
723 
724 template< class TInputImage, class TOutputImage >
725 void
727 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,ThreadIdType threadId )
728 {
729  itkShowPositionThreadedLogger(this->GetDebug());
730  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
731  // Pointers
732  InputImageConstPointer inputPtr = this->GetInput();
733  OutputImagePointer outputPtr = this->GetOutput();
734 
735  // iterator for the output image
736  ImageRegionIteratorWithIndex<OutputImageType> outputIt(outputPtr, outputRegionForThread );
737  ImageRegionConstIteratorWithIndex<InputImageType> inputIt(inputPtr, outputRegionForThread );
738  ImageRegionIteratorWithIndex<MaskImageType> maskIt;
739  ImageRegionIteratorWithIndex<ScalarImageType> scaleIt;
740  if (this->IsMaskUsed())
741  maskIt = ImageRegionIteratorWithIndex<MaskImageType>(this->m_MaskImage, outputRegionForThread);
742  if (!IsImageEmpty(this->m_ScaleImage))
743  scaleIt = ImageRegionIteratorWithIndex<ScalarImageType>(this->m_ScaleImage, outputRegionForThread);
744 
745  InputImagePixelType inputPixel;
746  // OutputImageIndexType outputIndex;
747  OutputImagePixelType outputPixel, outputZero;
748 
749  unsigned int numberOfCoeffcients = outputPtr->GetNumberOfComponentsPerPixel();;
750  outputPixel.SetSize(numberOfCoeffcients);
751  outputZero.SetSize(numberOfCoeffcients), outputZero.Fill(0.0);
752  unsigned int numberOfDWIs = inputPtr->GetNumberOfComponentsPerPixel();
753  inputPixel.SetSize(numberOfDWIs);
754  int n_b_sh = (this->m_SHRank+1)*(this->m_SHRank+2)/2;
755  int n_b_ra = this->m_RadialRank + 1;
756  int n_b = n_b_ra * n_b_sh;
757 
758  VectorType dwiPixel(numberOfDWIs+this->m_BasisMatrixForB0->Rows()), dwiPixel_est(numberOfDWIs+this->m_BasisMatrixForB0->Rows()), dwiPixel_first(numberOfDWIs), coef(numberOfCoeffcients), coef_first;
759  InputImageIndexType index;
760 
761 
762  Pointer selfClone = this->Clone();
763  // change selfClone->m_ThreadID and generate threadIDStr
764  selfClone->m_ThreadID = threadId;
765  std::string threadIDStr = selfClone->ThreadIDToString();
766  if (this->GetDebug())
767  {
768  std::ostringstream msg;
769  selfClone->Print(msg << threadIDStr <<"selfClone = ");
770  this->WriteLogger(msg.str());
771  }
772 
773 
774  STDVectorPointer qVector = selfClone->m_SamplingSchemeQSpace->GetRadiusVector();
775 
776  if (!this->IsAdaptiveScale())
777  {
778  selfClone->ComputeRadialVectorForE0InDWI();
779  selfClone->ComputeRadialVectorForE0InBasis();
780  }
781 
782  MatrixPointer basisMatrix(new MatrixType());
783  if (!this->m_IsAnalyticalB0 && !this->IsAdaptiveScale())
784  *basisMatrix = utl::ConnectUtlMatrix(*selfClone->m_BasisMatrix, *utl::ToMatrix<double>(*selfClone->m_BasisMatrixForB0 % selfClone->m_B0Weight), true);
785 
786  for (inputIt.GoToBegin(), outputIt.GoToBegin(), maskIt.GoToBegin(), scaleIt.GoToBegin();
787  !inputIt.IsAtEnd();
788  progress.CompletedPixel(), ++inputIt, ++outputIt, ++maskIt, ++scaleIt)
789  {
790 
791  if (this->IsMaskUsed() && maskIt.Get()<=1e-8)
792  {
793  outputIt.Set(outputZero);
794  continue;
795  }
796 
797  inputPixel=inputIt.Get();
798  if (inputPixel.GetSquaredNorm()<=1e-8)
799  {
800  outputIt.Set(outputZero);
801  continue;
802  }
803 
804  index = inputIt.GetIndex();
805  if (this->GetDebug())
806  {
807  std::ostringstream msg;
808  msg << "\n" << threadIDStr << "index = " << index << std::endl << std::flush;
809  this->WriteLogger(msg.str());
810  }
811 
812  for ( int i = 0; i < numberOfDWIs; i += 1 )
813  dwiPixel[i] = inputPixel[i];
814 
815  if (this->IsAdaptiveScale())
816  {
817  double scale = scaleIt.Get();
818  if (scale<=0)
819  {
820  // use scaleImage as a mask
821  outputIt.Set(outputZero);
822  continue;
823  }
824 
825  selfClone->SetBasisScale(scale);
826  if (selfClone->m_BasisMatrix->Rows()==0)
827  {
828  selfClone->ComputeBasisMatrix();
829  if (!selfClone->m_IsAnalyticalB0)
830  selfClone->ComputeBasisMatrixForB0();
831  else
832  {
833  selfClone->ComputeRadialVectorForE0InDWI();
834  selfClone->ComputeRadialVectorForE0InBasis();
835  }
836  }
837 
838  if (!this->m_IsAnalyticalB0)
839  {
840  basisMatrix=MatrixPointer( new MatrixType() );
841  *basisMatrix = utl::ConnectUtlMatrix(*selfClone->m_BasisMatrix, *utl::ToMatrix<double>((*selfClone->m_BasisMatrixForB0)%this->m_B0Weight), true);
842  }
843  else
844  {
845  if (basisMatrix->Size()==0 || this->m_EstimationType==Self::L1_DL) // resize it for L1_DL
846  basisMatrix=MatrixPointer( new MatrixType(selfClone->m_BasisMatrix->Rows(), n_b_sh*(n_b_ra-1)) );
847  utlException((*selfClone->m_Gn0)[0]==0, "it should be not zero!, (*selfClone->m_Gn0)[0]="<< (*selfClone->m_Gn0)[0]);
848  // utlPrintVar2 (selfClone->_is_b0_analytical, selfClone->m_RadialRank, R_N_0);
849 
850 
851  // utl::Tic(std::cout<<"index start 1");
852  double *selfBasisMatrix_data = selfClone->m_BasisMatrix->GetData();
853  double *basisMatrix_data = basisMatrix->GetData();
854  int index_B=0, index_selfB=0, index_selfB_0=0;
855  for ( int ss = 0; ss < basisMatrix->Rows(); ss += 1 )
856  {
857  for ( int i = 0; i < this->m_RadialRank; i += 1 )
858  {
859  if (i==0)
860  index_selfB += n_b_sh;
861  else
862  index_selfB_0 -= n_b_sh;
863  for ( int j = 0; j < n_b_sh; j += 1 )
864  {
865  basisMatrix_data[index_B] = selfBasisMatrix_data[index_selfB] - (*selfClone->m_Gn0)[i+1]/(*selfClone->m_Gn0)[0] * selfBasisMatrix_data[index_selfB_0];
866  // basisMatrix(ss,i*n_b_sh+j) = (*selfClone->m_BasisMatrix)(ss,(i+1)*n_b_sh+j) - (*selfClone->m_Gn0)[i+1]/(*selfClone->m_Gn0)[0] * (*selfClone->m_BasisMatrix)(ss,j);
867  index_B++;
868  index_selfB++;
869  index_selfB_0++;
870  }
871  }
872  index_selfB_0 += n_b_sh*this->m_RadialRank;
873  }
874  // utl::Toc();
875 
876  // utl::Tic(std::cout<<"() start 1");
877  // for ( int i = 0; i < this->m_RadialRank; i += 1 )
878  // {
879  // double firstTerm = (*selfClone->m_Gn0)[i+1]/(*selfClone->m_Gn0)[0];
880  // for ( int j = 0; j < n_b_sh; j += 1 )
881  // {
882  // int index_B = i*n_b_sh+j;
883  // int index_selfB = (i+1)*n_b_sh+j;
884  // for ( int ss = 0; ss < basisMatrix->Rows(); ss += 1 )
885  // {
886  // (*basisMatrix)(ss,index_B) = (*selfClone->m_BasisMatrix)(ss,index_selfB) - firstTerm * (*selfClone->m_BasisMatrix)(ss,j);
887  // }
888  // }
889  // }
890  // utl::Toc();
891 
892  }
893 
894  if (this->m_EstimationType==Self::L1_DL)
895  {
896  MatrixPointer tmpMat (new MatrixType());
897  utl::ProductUtlMM(*basisMatrix, *this->m_BasisCombinationMatrix, *tmpMat);
898  *basisMatrix = *tmpMat;
899  // utl::MatrixCopy(*tmpMat, *basisMatrix, 1.0, 'N');
900  // basisMatrix = tmpMat;
901  // basisMatrix *= (*this->m_BasisCombinationMatrix);
902  }
903 
904  if (this->GetDebug())
905  {
906  std::ostringstream msg;
907  utl::PrintUtlMatrix(*basisMatrix, "basisMatrix_InSolver", " ", msg << threadIDStr);
908  this->WriteLogger(msg.str());
909  }
910 
911  if (this->m_EstimationType==Self::LS)
912  {
913  selfClone->m_L2Solver->SetA(basisMatrix);
914  }
915  else if (this->m_EstimationType==Self::L1_2 || this->m_EstimationType==Self::L1_DL)
916  {
917  if (this->m_L1SolverType==Self::FISTA_LS)
918  selfClone->m_L1FISTASolver->SetA(basisMatrix);
919  else if (this->m_L1SolverType==Self::SPAMS)
920  selfClone->m_L1SpamsSolver->SetA(basisMatrix);
921  }
922  }
923 
924  if (this->m_IsAnalyticalB0)
925  {
926  for ( int i = 0; i < dwiPixel.Size(); i += 1 )
927  dwiPixel_first[i] = dwiPixel[i] - (*selfClone->m_G0DWI)[i];
928 
929  if (this->m_EstimationType==Self::LS)
930  {
931  selfClone->m_L2Solver->Setb(VectorPointer(new VectorType(dwiPixel_first)));
932  selfClone->m_L2Solver->Solve();
933  coef_first = selfClone->m_L2Solver->Getx();
934  // MatrixType ls = selfClone->m_L2Solver->GetLS();
935  // utl::PrintUtlMatrix(ls, "LS");
936  // VectorType coef_test = ls*dwiPixel_first;
937  // utl::PrintUtlVector(coef_test, "coef_test");
938  }
939  else if (this->m_EstimationType==Self::L1_2 || this->m_EstimationType==Self::L1_DL)
940  {
941  if (this->m_L1SolverType==Self::FISTA_LS)
942  {
943  selfClone->m_L1FISTASolver->Setb(VectorPointer(new VectorType(dwiPixel_first)));
944  // selfClone->m_L1FISTASolver->SetDebug(this->GetDebug());
945  // selfClone->m_L1FISTASolver->Print(std::cout<<"selfClone->m_L1FISTASolver = ");
946  selfClone->m_L1FISTASolver->Solve();
947  coef_first = selfClone->m_L1FISTASolver->Getx();
948  }
949  else if (this->m_L1SolverType==Self::SPAMS)
950  {
951  selfClone->m_L1SpamsSolver->Setb(VectorPointer(new VectorType(dwiPixel_first)));
952  selfClone->m_L1SpamsSolver->Solve();
953  coef_first = selfClone->m_L1SpamsSolver->Getx();
954  }
955 
956  if (this->GetDebug())
957  {
958  std::ostringstream msg;
959  if (selfClone->m_L1SpamsSolver)
960  {
961  msg << threadIDStr << "use m_L1SpamsSolver" << std::endl << std::flush;
962  selfClone->m_L1SpamsSolver->Print(msg << threadIDStr<<"this->m_L1QPSolver = ");
963  double func = selfClone->m_L1SpamsSolver->EvaluateCostFunction();
964  msg << threadIDStr << "func spams = " << func << std::endl << std::flush;
965  }
966  if (selfClone->m_L1FISTASolver)
967  {
968  msg << threadIDStr << "use m_L1FISTASolver" << std::endl << std::flush;
969  selfClone->m_L1FISTASolver->Print(msg << threadIDStr<<"this->m_L1FISTASolver = ");
970  std::vector<double> funcVec = selfClone->m_L1FISTASolver->GetCostFunction();
971  utl::PrintVector(funcVec, "func FISTA", " ", msg << threadIDStr);
972  }
973  this->WriteLogger(msg.str());
974  }
975  }
976 
977  if (this->m_EstimationType==Self::L1_DL)
978  {
979  VectorType coef_first_tmp;
980  utl::ProductUtlMv(*this->m_BasisCombinationMatrix, coef_first,coef_first_tmp);
981  for ( int i = 0; i < coef_first_tmp.Size(); i += 1 )
982  coef[i+n_b_sh] = coef_first_tmp[i];
983  }
984  else
985  {
986  for ( int i = 0; i < coef_first.Size(); i += 1 )
987  coef[i+n_b_sh] = coef_first[i];
988  }
989 
990  int jj=0;
991  for ( int l = 0; l <= this->m_SHRank; l += 2 )
992  {
993  for ( int m = -l; m <= l; m += 1 )
994  {
995  double sum_tmp = 0;
996  for ( int nn = 1; nn <= this->m_RadialRank; nn += 1 )
997  {
998  int index_j = this->GetIndexJ(nn,l,m);
999  sum_tmp += coef[index_j] * (*selfClone->m_Gn0)[nn];
1000  }
1001  if (l==0)
1002  coef[jj] = (std::sqrt(4*M_PI) - sum_tmp)/(*selfClone->m_Gn0)[0];
1003  else
1004  coef[jj] = -sum_tmp/(*selfClone->m_Gn0)[0];
1005  jj++;
1006  }
1007  }
1008 
1009  }
1010  else
1011  {
1012  for ( int i = 0; i < selfClone->m_BasisMatrixForB0->Rows(); i += 1 )
1013  dwiPixel[i+numberOfDWIs] = selfClone->m_B0Weight;
1014  // utl::PrintUtlVector(dwiPixel, "dwiPixel");
1015  // utl::PrintUtlMatrix(selfClone->m_BasisMatrixForB0, "selfClone->m_BasisMatrixForB0");
1016 
1017  if (this->m_EstimationType==Self::LS)
1018  {
1019  selfClone->m_L2Solver->Setb(VectorPointer(new VectorType(dwiPixel)));
1020  selfClone->m_L2Solver->Solve();
1021  coef = selfClone->m_L2Solver->Getx();
1022  }
1023  else if (this->m_EstimationType==Self::L1_2 || this->m_EstimationType==Self::L1_DL)
1024  {
1025  if (this->m_L1SolverType==Self::FISTA_LS)
1026  {
1027  selfClone->m_L1FISTASolver->Setb(VectorPointer(new VectorType(dwiPixel)));
1028  selfClone->m_L1FISTASolver->Solve();
1029  coef = selfClone->m_L1FISTASolver->Getx();
1030  }
1031  else if (this->m_L1SolverType==Self::SPAMS)
1032  {
1033  selfClone->m_L1SpamsSolver->Setb(VectorPointer(new VectorType(dwiPixel)));
1034  selfClone->m_L1SpamsSolver->Solve();
1035  coef = selfClone->m_L1SpamsSolver->Getx();
1036  }
1037  }
1038 
1039  }
1040 
1041  if (this->GetDebug())
1042  {
1043  std::ostringstream msg;
1044  utl::PrintUtlVector(dwiPixel, "dwiPixel", " ", msg << threadIDStr);
1045  utl::PrintUtlVector(coef, "coef", " ", msg << threadIDStr);
1046  if (this->m_IsAnalyticalB0)
1047  {
1048  utl::PrintUtlVector(dwiPixel_first, "dwiPixel_first", " ", msg << threadIDStr);
1049  utl::PrintUtlVector(coef_first, "coef_first", " ", msg << threadIDStr);
1050  utl::ProductUtlMv(*selfClone->m_BasisMatrix, coef, dwiPixel_est);
1051  }
1052  else
1053  {
1054  utl::ProductUtlMv(*basisMatrix, coef, dwiPixel_est);
1055  }
1056  utl::PrintUtlVector(dwiPixel_est, "dwiPixel_est", " ", msg << threadIDStr);
1057  VectorType diff = (dwiPixel - dwiPixel_est); diff.ElementAbsolute();
1058  utl::PrintUtlVector(diff, "dwiPixel_diff", " ", msg << threadIDStr);
1059  if (selfClone->m_BasisMatrixForB0->Size()==0)
1060  selfClone->ComputeBasisMatrixForB0();
1061  VectorType dwiPixel_b0_est;
1062  utl::ProductUtlMv(*selfClone->m_BasisMatrixForB0, coef, dwiPixel_b0_est);
1063  utl::PrintUtlVector(dwiPixel_b0_est, "dwiPixel_b0_est", " ", msg << threadIDStr);
1064  this->WriteLogger(msg.str());
1065  }
1066 
1067  for ( int i = 0; i < numberOfCoeffcients; i += 1 )
1068  outputPixel[i] = coef[i];
1069 
1070  outputIt.Set(outputPixel);
1071  }
1072 }
1073 
1074 template< class TInputImage, class TOutputImage >
1075 void
1077 ::PrintSelf(std::ostream& os, Indent indent) const
1078 {
1079  Superclass::PrintSelf(os, indent);
1080 }
1081 
1082 }
1083 
1084 
1085 #endif
1086 
NDArray is a N-Dimensional array class (row-major, c version)
Definition: utlFunctors.h:131
LightObject::Pointer InternalClone() const ITK_OVERRIDE
void ReadMatrix(const std::string &file, TMatrixType &matrix)
Definition: utlCore.h:1897
base filter for estimation of diffusion models
helper functions specifically used in dmritool
int GetIndexSHj(const int l, const int m)
Definition: utlDMRI.h:204
bool IsImageEmpty(const SmartPointer< ImageType > &image)
Definition: utlITK.h:435
void Print(std::ostream &os, const char *separate=" ") const
Definition: utlNDArray.h:1135
void PrintUtlMatrix(const NDArray< T, 2 > &mat, const std::string &str="", const char *separate=" ", std::ostream &os=std::cout)
static const std::string LearnedSPFDictionary_SH8_RA4_K250
NDArray< T, 2 > ConnectUtlMatrix(const NDArray< T, 2 > &m1, const NDArray< T, 2 > &m2, const bool isConnectRow)
#define utlException(cond, expout)
Definition: utlCoreMacro.h:548
std::vector< int > GetIndexSHlm(const int j)
Definition: utlDMRI.h:211
void PrintSelf(std::ostream &os, Indent indent) const ITK_OVERRIDE
std::vector< int > DimToRank(const int dimm) const ITK_OVERRIDE
int GetIndexJ(const int n, const int l, const int m) const ITK_OVERRIDE
void PowerVector(IteratorType v1, IteratorType v2, const double poww)
Definition: utlCore.h:1619
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) ITK_OVERRIDE
NDArray< T, 1 > StdVectorToUtlVector(const std::vector< T > &vec)
std::shared_ptr< NDArray< T, 2 > > ComputeSHMatrix(const unsigned int rank, const NDArray< T, 2 > &grad, const int mode)
Definition: utl.h:171
std::string CreateExpandedPath(const std::string &path)
Definition: utlCore.h:509
double ComputeScale(const bool setScale=true) ITK_OVERRIDE
void ProductUtlMM(const utl::NDArray< T, 2 > &A, const utl::NDArray< T, 2 > &B, utl::NDArray< T, 2 > &C, const double alpha=1.0, const double beta=0.0)
T abs(const T x)
template version of the fabs function
#define M_PI
Definition: utlCoreMacro.h:57
#define utlGlobalException(cond, expout)
Definition: utlCoreMacro.h:372
static const std::string LearnedSPFEnergy_SH8_RA4_K250
void ReadVector(const std::string &vectorStr, std::vector< T > &vec, const char *cc=" ")
Definition: utlCore.h:1159
void PrintVector(const std::vector< T > &vec, const std::string &str="", const char *separate=" ", std::ostream &os=std::cout, bool showStats=true)
Definition: utlCore.h:1002
static void InitializeThreadedLibraries(const int numThreads)
Definition: utl.h:327
int RankToDim(const bool is_radial=false, const int radialRank=-1, const int shRank=-1) const ITK_OVERRIDE
#define itkShowPositionThreadedLogger(cond)
Definition: utlITKMacro.h:192
NDArrayBase< T, Dim > & ElementAbsolute(T *outVec=NULL)
Definition: utlNDArray.h:841
void PrintUtlVector(const NDArray< T, 1 > &vec, const std::string &str="", const char *separate=" ", std::ostream &os=std::cout, bool showStats=true)
std::vector< int > GetIndexNLM(const int index) const ITK_OVERRIDE
SizeType Size() const
Definition: utlNDArray.h:321
void ProductUtlMv(const utl::NDArray< T, 2 > &A, const utl::NDArray< T, 1 > &b, utl::NDArray< T, 1 > &c, const double alpha=1.0, const double beta=0.0)
void SetBasisScale(const double scale) ITK_OVERRIDE