17 #ifndef __itkSamplingSchemeQSpaceIMOCEstimationFilter_hxx    18 #define __itkSamplingSchemeQSpaceIMOCEstimationFilter_hxx    29 template< 
class TSamplingType >
    37 template< 
class TSamplingType >
    43   if (this->m_FineOrientations->Size()==0)
    47   m_FineScheme->SetOrientationsCartesian(m_FineOrientations);
    51   m_MinDistanceInFineScheme = m_FineScheme->CalculateMinDistance(0,
true);
    52   m_MinDistanceInFineScheme = std::sqrt(2-2*std::cos(m_MinDistanceInFineScheme));
    55   m_Sample = SampleType::New();
    56   m_Sample->SetMeasurementVectorSize( 3 );
    57   unsigned int numberOfSamples = m_FineOrientations->Rows();
    59   for (
unsigned int i = 0; i < numberOfSamples; ++i )
    61     mv = (*m_FineScheme)[i];
    62     m_Sample->PushBack( mv );
    63     for ( 
int j = 0; j < 3; ++j ) 
    65     m_Sample->PushBack( mv );
    68   m_TreeGenerator = TreeGeneratorType::New();
    69   m_TreeGenerator->SetSample( m_Sample );
    70   m_TreeGenerator->SetBucketSize( 16 );
    71   m_TreeGenerator->Update();
    74   m_KDTree = m_TreeGenerator->GetOutput();
    77 template< 
class TSamplingType >
    82   std::vector<double> euclideanDistances(angles.size()), overlapBallsInnerProduct(angles.size());
    83   for ( 
int i = 0; i < angles.size(); ++i ) 
    85     overlapBallsInnerProduct[i] = std::fabs(std::cos(2*angles[i]));
    86     euclideanDistances[i] = std::sqrt(2-2*std::cos(angles[i]));
    89   unsigned int numberOfShells = this->m_NumbersInShell.size();
    90   unsigned int numberOfSamples = m_FineScheme->GetNumberOfSamples();
    91   int totalNumberOfSamples = std::accumulate(this->m_NumbersInShell.begin(), this->m_NumbersInShell.end(), 0);
    94   std::vector<int> coverageInShells(numberOfShells,0);
    95   bool isSameAngle = 
true;
    96   for ( 
int j = 1; j < numberOfShells; ++j ) 
    98     if (std::fabs(angles[0]-angles[j])>1e-4)
   104   bool needCoverageInshells = m_ChooseMinimalCoverageShell && !isSameAngle;
   107   typedef typename TreeType::InstanceIdentifierVectorType InstanceIdentifierVectorType;
   108   InstanceIdentifierVectorType neighbors, neighbors_1, candidates, candidates_1, neighbors_jj;
   109   InstanceIdentifierVectorType candidateNumbersInOverlap;
   116   typedef utl_unordered_map<int, InstanceIdentifierVectorType> NeighborMapType;
   117   typedef typename NeighborMapType::const_iterator NeighborMapIterator;
   118   NeighborMapType neighborMap;
   121   if (numberOfShells==1)
   124     std::set<int> nextCandidateIndices;
   126     int currentIndex = -1;
   127     if (chosenIndices[0].size()==0)
   130     while (chosenIndices[0].size()< this->m_NumbersInShell[0] )
   134       hasChosen[currentIndex]=0;
   135       chosenIndices[0].push_back(currentIndex);
   136       queryPoint = (*m_FineScheme)[currentIndex];
   139       indexDistPair=currentIndex;
   141       NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
   142       if (mapIter==neighborMap.end())
   144         m_KDTree->Search( queryPoint, euclideanDistances[0], neighbors );
   145         neighborMap[indexDistPair] = neighbors;
   148         neighbors = mapIter->second;
   149       for ( 
int i = 0; i < neighbors.size(); ++i ) 
   150         hasChosen[neighbors[i]/2] = 0;
   152       m_KDTree->Search( queryPoint, euclideanDistances[0]+1*m_MinDistanceInFineScheme, candidates );
   153       utlException(candidates.size()<=neighbors.size(), 
"the size of candidates should be larger than the size of neighbors.");
   155       for ( 
int i = 0; i < candidates.size(); ++i ) 
   157         int jj = candidates[i]/2;
   158         if (hasChosen[jj] == -1)
   159           nextCandidateIndices.insert(jj);
   162       int indexMaxOverlap=-1;
   163       int sumMaxOverlap=-1;
   164       int numberOfCandidates=0, numberSearch=0;
   167       for ( 
typename std::set<int>::iterator iter = nextCandidateIndices.begin(); iter!=nextCandidateIndices.end(); ++iter ) 
   170         if (hasChosen[jj]==-1)
   172           queryCandidate = (*m_FineScheme)[jj];
   173           bool overlapBall = 
true;
   174           double innerProduct = 0;
   175           for ( 
int kk = 0; kk < 3; ++kk ) 
   176             innerProduct+= queryPoint[kk]*queryCandidate[kk];
   177           if (std::fabs(innerProduct) < overlapBallsInnerProduct[0])
   181           if (sumOverlapVec[0][jj]>=0 && !overlapBall)
   182             sumOverlap = sumOverlapVec[0][jj];
   188             NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
   189             if (mapIter==neighborMap.end())
   191               m_KDTree->Search( queryCandidate, euclideanDistances[0], neighbors_jj );
   192               neighborMap[indexDistPair] = neighbors_jj;
   195               neighbors_jj = mapIter->second;
   197             for ( 
int k = 0; k < neighbors_jj.size(); ++k ) 
   199               if (hasChosen[neighbors_jj[k]/2]==0)
   202             sumOverlapVec[0][jj]=sumOverlap;
   205           if (sumMaxOverlap<sumOverlap)
   207             indexMaxOverlap = jj;
   208             sumMaxOverlap = sumOverlap;
   210           numberOfCandidates++;
   216       if (numberOfCandidates==0)
   219       currentIndex = indexMaxOverlap;
   222     if (chosenIndices[0].size()==this->m_NumbersInShell[0])
   224       *indices = chosenIndices;
   237     for ( 
int s = 0; s < numberOfShells; ++s ) 
   240       if (euclideanDistances[s]<= euclideanDistances.back())
   245     std::vector<std::set<int> > nextCandidateIndices(numberOfShells+1);
   248     int currentIndex = 0;
   249     for ( 
int s = 0; s < numberOfShells; ++s ) 
   251       hasChosen[currentIndex][s]=0;
   252       hasChosen[currentIndex][numberOfShells]=s;
   254       chosenIndices[s].push_back(currentIndex);
   255       queryPoint = (*m_FineScheme)[currentIndex];
   260       indexDistPair=currentIndex + s*numberOfSamples;
   261       NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
   262       if (mapIter==neighborMap.end())
   264         m_KDTree->Search( queryPoint, euclideanDistances[s], neighbors );
   265         neighborMap[indexDistPair] = neighbors;
   268         neighbors = mapIter->second;
   269       for ( 
int i = 0; i < neighbors.size(); ++i ) 
   270         hasChosen[neighbors[i]/2][s] = 0;
   272       if (needCoverageInshells)
   273         coverageInShells[s] += neighbors.size();
   275       indexDistPair=currentIndex + numberOfShells*numberOfSamples;
   276       mapIter = neighborMap.find(indexDistPair);
   277       if (mapIter==neighborMap.end())
   279         m_KDTree->Search( queryPoint, euclideanDistances.back(), neighbors_1 );
   280         neighborMap[indexDistPair] = neighbors_1;
   283         neighbors_1 = mapIter->second;
   284       for ( 
int i = 0; i < neighbors_1.size(); ++i ) 
   285         hasChosen[neighbors_1[i]/2][numberOfShells] = s;
   287       m_KDTree->Search( queryPoint, euclideanDistances[s]+1*m_MinDistanceInFineScheme, candidates );
   288       utlException(candidates.size()<=neighbors.size(), 
"the size of candidates should be larger than the size of neighbors.");
   290       m_KDTree->Search( queryPoint, euclideanDistances.back()+1*m_MinDistanceInFineScheme, candidates_1 );
   291       utlException(candidates_1.size()<=neighbors_1.size(), 
"the size of candidates should be larger than the size of neighbors.");
   293       for ( 
int i = 0; i < candidates.size(); ++i ) 
   295         int jj = candidates[i]/2;
   296         if ( hasChosen[jj][s]==-1 && hasChosen[jj][numberOfShells]==-1)
   297           nextCandidateIndices[s].insert(jj);
   300       for ( 
int i = 0; i < candidates_1.size(); ++i ) 
   302         int jj = candidates_1[i]/2;
   303         if ( hasChosen[jj][numberOfShells]==-1)
   305           for ( 
int sss = 0; sss < numberOfShells; ++sss ) 
   307             if (sss!=s && hasChosen[jj][sss]==-1)
   308               nextCandidateIndices[sss].insert(jj);
   310           nextCandidateIndices[numberOfShells].insert(jj);
   314       int indexMaxOverlap=-1;
   315       int sumMaxOverlap=-1;
   316       int numberOfCandidates=0, numberSearch=0;
   318       for ( 
typename std::set<int>::iterator iter = nextCandidateIndices[numberOfShells].begin(); iter!=nextCandidateIndices[numberOfShells].end(); ++iter ) 
   321         if (hasChosen[jj][numberOfShells]==-1)
   323           queryCandidate = (*m_FineScheme)[jj];
   324           bool overlapBall = 
true;
   325           double innerProduct = 0;
   326           for ( 
int kk = 0; kk < 3; ++kk ) 
   327             innerProduct+= queryPoint[kk]*queryCandidate[kk];
   328           if (std::fabs(innerProduct) < overlapBallsInnerProduct[numberOfShells])
   332           if (sumOverlapVec[numberOfShells][jj]>=0 && !overlapBall)
   333             sumOverlap = sumOverlapVec[numberOfShells][jj];
   338             indexDistPair = jj + numberOfShells*numberOfSamples;
   339             mapIter = neighborMap.find(indexDistPair);
   340             if (mapIter==neighborMap.end())
   342               m_KDTree->Search( queryCandidate, euclideanDistances.back(), neighbors_jj );
   343               neighborMap[indexDistPair] = neighbors_jj;
   346               neighbors_jj = mapIter->second;
   348             for ( 
int k = 0; k < neighbors_jj.size(); ++k ) 
   350               if (hasChosen[neighbors_jj[k]/2][numberOfShells]>=0)
   353             sumOverlapVec[numberOfShells][jj]=sumOverlap;
   356           if (sumMaxOverlap<sumOverlap)
   358             indexMaxOverlap = jj;
   359             sumMaxOverlap = sumOverlap;
   361           numberOfCandidates++;
   365       currentIndex = indexMaxOverlap;
   373     int indexShellMaxOverlap=-1, indexShellMaxOverlapLast=-1, shellIndexMinCoverage=-1;
   375     for ( 
unsigned int n = numberOfShells; n < totalNumberOfSamples; ++n ) 
   379       int indexMaxOverlap=-1;
   380       int sumMaxOverlap=-1;
   381       int numberOfCandidates=0, numberSearch=0;
   383       if (needCoverageInshells)
   386         for ( 
int s = 0; s < numberOfShells; ++s ) 
   388           if (chosenIndices[s].size() >= this->m_NumbersInShell[s])
   389             coverageInShells[s] = numberOfSamples;
   392         shellIndexMinCoverage = 
utl::argmin(coverageInShells.begin(), coverageInShells.end());
   395       for ( 
int s = 0; s < numberOfShells; ++s ) 
   398         if (needCoverageInshells && shellIndexMinCoverage!=s)
   404         if (chosenIndices[s].size() < this->m_NumbersInShell[s])
   407           for ( 
typename std::set<int>::iterator iter = nextCandidateIndices[s].begin(); iter!=nextCandidateIndices[s].end(); ++iter ) 
   410             if (hasChosen[jj][s]==-1 && hasChosen[jj][numberOfShells]==-1)
   412               queryCandidate = (*m_FineScheme)[jj];
   413               bool overlapBall = 
true;
   414               if (n>numberOfShells)
   416                 double innerProduct = 0;
   417                 for ( 
int kk = 0; kk < 3; ++kk ) 
   418                   innerProduct+= queryPointLast[kk]*queryCandidate[kk];
   421                 if ( std::fabs(innerProduct) < overlapBallsInnerProduct[s] )
   426               if (sumOverlapVec[s][jj]>=0 && !overlapBall)
   427                 sumOverlap = sumOverlapVec[s][jj];
   431                 indexDistPair=jj + s*numberOfSamples;
   432                 NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
   433                 if (mapIter==neighborMap.end())
   435                   m_KDTree->Search( queryCandidate, euclideanDistances[s], neighbors_jj );
   436                   neighborMap[indexDistPair] = neighbors_jj;
   439                   neighbors_jj = mapIter->second;
   441                 for ( 
int k = 0; k < neighbors_jj.size(); ++k ) 
   443                   if (hasChosen[neighbors_jj[k]/2][s]>=0 || hasChosen[neighbors_jj[k]/2][numberOfShells]>=0)
   446                 sumOverlapVec[s][jj]=sumOverlap;
   450               if (sumMaxOverlap<sumOverlap)
   452                 indexShellMaxOverlap = s;
   453                 indexMaxOverlap = jj;
   454                 sumMaxOverlap = sumOverlap;
   456               numberOfCandidates++;
   463       if (numberOfCandidates==0)
   466       currentIndex = indexMaxOverlap;
   467       indexShellMaxOverlapLast = indexMaxOverlap;
   469       hasChosen[currentIndex][indexShellMaxOverlap]=0;
   470       hasChosen[currentIndex][numberOfShells]=indexShellMaxOverlap;
   471       chosenIndices[indexShellMaxOverlap].push_back(currentIndex);
   472       queryPoint = (*m_FineScheme)[currentIndex];
   473       queryPointLast = queryPoint;
   475       indexDistPair=currentIndex+indexShellMaxOverlap*numberOfSamples;
   476       NeighborMapIterator mapIter = neighborMap.find(indexDistPair);
   477       if (mapIter==neighborMap.end())
   479         m_KDTree->Search( queryPoint, euclideanDistances[indexShellMaxOverlap], neighbors );
   480         neighborMap[indexDistPair] = neighbors;
   483         neighbors = mapIter->second;
   484       for ( 
int i = 0; i < neighbors.size(); ++i ) 
   487         if (needCoverageInshells)
   489           if (hasChosen[neighbors[i]/2][indexShellMaxOverlap]==-1)
   490             coverageInShells[indexShellMaxOverlap]++;
   492         hasChosen[neighbors[i]/2][indexShellMaxOverlap] = 0;
   495       indexDistPair=currentIndex+numberOfShells*numberOfSamples;
   496       mapIter = neighborMap.find(indexDistPair);
   497       if (mapIter==neighborMap.end())
   499         m_KDTree->Search( queryPoint, euclideanDistances.back(), neighbors_1 );
   500         neighborMap[indexDistPair] = neighbors_1;
   503         neighbors_1 = mapIter->second;
   504       for ( 
int i = 0; i < neighbors_1.size(); ++i ) 
   505         hasChosen[neighbors_1[i]/2][numberOfShells] = indexShellMaxOverlap;
   507       m_KDTree->Search( queryPoint, euclideanDistances[indexShellMaxOverlap]+1*m_MinDistanceInFineScheme, candidates );
   508       utlException(candidates.size()<=neighbors.size(), 
"the size of candidates should be larger than the size of neighbors.");
   510       m_KDTree->Search( queryPoint, euclideanDistances.back()+1*m_MinDistanceInFineScheme, candidates_1 );
   511       utlException(candidates_1.size()<=neighbors_1.size(), 
"the size of candidates should be larger than the size of neighbors.");
   513       for ( 
int i = 0; i < candidates.size(); ++i ) 
   515         int jj = candidates[i]/2;
   516         if ( hasChosen[jj][indexShellMaxOverlap]==-1 && hasChosen[jj][numberOfShells]==-1)
   517           nextCandidateIndices[indexShellMaxOverlap].insert(jj);
   520       for ( 
int i = 0; i < candidates_1.size(); ++i ) 
   522         int jj = candidates_1[i]/2;
   523         if ( hasChosen[jj][numberOfShells]==-1)
   525           for ( 
int sss = 0; sss < numberOfShells; ++sss ) 
   527             if (sss!=indexShellMaxOverlap && hasChosen[jj][sss]==-1)
   528               nextCandidateIndices[sss].insert(jj);
   530           nextCandidateIndices[numberOfShells].insert(jj);
   538     for ( 
int i = 0; i < chosenIndices.size(); ++i ) 
   540       if (chosenIndices[i].size()!=this->m_NumbersInShell[i])
   543     *indices = chosenIndices;
   551 template< 
class TSamplingType >
   556   utlGlobalException(this->m_CriteriaType!=Self::DISTANCE, 
"m_CriteriaType should be DISTANCE");
   562   int numberOfShells = this->m_NumbersInShell.size();
   563   int totalNumberOfSamples = std::accumulate(this->m_NumbersInShell.begin(), this->m_NumbersInShell.end(), 0);
   564   int angleSize = numberOfShells==1?1:(numberOfShells+1);
   565   std::vector<double> angles(angleSize,-1.0), anglesUpperBound(angleSize,-1.0), anglesLowerBound(angleSize,0.0);
   566   std::vector<std::vector<double> > anglesTest(angleSize);
   568   for ( 
int i = 0; i < numberOfShells; ++i ) 
   569     anglesUpperBound[i] = SamplingType::CalculateMinDistanceUpperBound(2*this->m_NumbersInShell[i]);
   570   if (numberOfShells>1)
   571     anglesUpperBound[numberOfShells] = SamplingType::CalculateMinDistanceUpperBound(2*totalNumberOfSamples); 
   573   if (numberOfShells==1)
   575     double angle_0=0, angle_1=anglesUpperBound[0];
   576     while (angle_0<angle_1)
   578       angles[0]= (angle_0+angle_1)*0.5;
   579       bool successAngles = IsSatisfiedSeparationAngles(angles);
   585         anglesTest[0].push_back(angles[0]);
   589       if (anglesTest[0].size()>=2 && std::fabs(anglesTest[0].back()-anglesTest[0][anglesTest[0].size()-2])/anglesTest[0][anglesTest[0].size()-2]<m_AngleMinChange )
   591         this->m_OutputOrientations = m_FineScheme;
   600     std::vector<double> angle_0(anglesLowerBound), angle_1(anglesUpperBound);
   603       for ( 
int i = 0; i < angleSize; ++i ) 
   604         angles[i] = (angle_0[i]+angle_1[i])*0.5;
   605       bool successAngles = IsSatisfiedSeparationAngles(angles);
   611         for ( 
int i = 0; i < angleSize; ++i ) 
   613           angle_0[i] = angles[i];
   614           anglesTest[i].push_back(angles[i]);
   619         for ( 
int i = 0; i < angleSize; ++i ) 
   620           angle_1[i] = angles[i];
   623       bool minAngleStop = 
true;
   624       for ( 
int i = 0; i < angleSize; ++i ) 
   626         if (anglesTest[i].size()<2 || std::fabs(anglesTest[i].back()-anglesTest[i][anglesTest[i].size()-2])/anglesTest[i][anglesTest[i].size()-2]>=m_AngleMinChange )
   628           minAngleStop = 
false;
   634         this->m_OutputOrientations = m_FineScheme;
 unsigned int argmin(Iterator i1, Iterator i2)
 
helper functions specifically used in dmritool 
 
itk::Point< double, 3 > MeasurementVectorType
 
SamplingSchemeQSpaceIMOCEstimationFilter()
 
#define utlException(cond, expout)
 
void Initialization() ITK_OVERRIDE
 
bool IsSatisfiedSeparationAngles(const std::vector< double > &angles)
 
#define utlGlobalException(cond, expout)                                                                                                                                                                                                                              
 
void GenerateData() ITK_OVERRIDE
 
SamplingType::Index2DVectorType Index2DVectorType
 
LightProcessObject Superclass
 
SamplingType::IndexVectorType IndexVectorType
 
SamplingType::Index2DVectorPointer Index2DVectorPointer
 
SamplingType::MatrixType MatrixType