6 #include <itkImageRegionConstIterator.h> 7 #include <itkImageRegionIterator.h> 8 #include <boost/math/special_functions/legendre.hpp> 16 template <
typename TInputPixelType,
typename TOutputPixelType>
23 m_B0Indexes.push_back(i);
27 m_GradientIndexes.push_back(i);
29 std::vector <double> sphericalCoords;
31 m_GradientDirections.push_back(sphericalCoords);
34 template <
typename TInputPixelType,
typename TOutputPixelType>
42 this->Superclass::GenerateOutputInformation();
44 unsigned int vectorLength = (m_LOrder + 1)*(m_LOrder + 2)/2;
46 output->SetVectorLength(vectorLength);
49 template <
typename TInputPixelType,
typename TOutputPixelType>
54 unsigned int vectorLength = (m_LOrder + 1)*(m_LOrder + 2)/2;
55 unsigned int numGrads = m_GradientDirections.size();
57 if ((m_GradientIndexes.size() + m_B0Indexes.size()) != this->GetNumberOfIndexedInputs())
58 throw itk::ExceptionObject(__FILE__, __LINE__,
"Number of gradient directions different from number of inputs",ITK_LOCATION);
60 if (m_UseAganjEstimation)
66 if (m_BValueShellSelected < 0)
67 m_BValueShellSelected = m_BValuesList[m_GradientIndexes[0]];
69 std::vector <unsigned int> bvalKeptIndexes;
70 std::vector < std::vector <double> > keptGradients;
72 for (
unsigned int i = 0;i < numGrads;++i)
74 if ((m_BValuesList[m_GradientIndexes[i]] >= m_BValueShellSelected - m_BValueShellTolerance) &&
75 (m_BValuesList[m_GradientIndexes[i]] <= m_BValueShellSelected + m_BValueShellTolerance))
77 bvalKeptIndexes.push_back(m_GradientIndexes[i]);
78 keptGradients.push_back(m_GradientDirections[i]);
82 m_GradientIndexes = bvalKeptIndexes;
83 m_GradientDirections = keptGradients;
84 numGrads = m_GradientIndexes.size();
86 std::cout <<
"Running ODF estimation using " << m_B0Indexes.size() <<
" B0 images and " << numGrads <<
" gradient images with b-value at " << m_BValueShellSelected <<
"s.mm^-2" << std::endl;
90 unsigned int posValue = 0;
91 vnl_matrix <double> BMatrix(numGrads,vectorLength);
95 for (
unsigned int i = 0;i < numGrads;++i)
98 for (
int k = 0;k <= (int)m_LOrder;k += 2)
99 for (
int m = -k;m <= k;++m)
101 BMatrix(i,posValue) = tmpBasis.
getNthSHValueAtPosition(k,m,m_GradientDirections[i][0],m_GradientDirections[i][1]);
106 std::vector <double> LVector(vectorLength,0);
107 m_PVector.resize(vectorLength);
110 for (
unsigned int k = 0;k <= m_LOrder;k += 2)
112 double ljVal = k*k*(k + 1)*(k + 1);
113 double pjValNum = 1, pjValDenom = 1, pjVal;
115 for (
unsigned int l = 2;l <= k; l += 2)
121 pjVal = pjValNum/pjValDenom;
125 for (
int m = -k;m <= (int)k;++m)
127 LVector[posValue] = ljVal;
129 if (!m_UseAganjEstimation)
130 m_PVector[posValue] = 2*M_PI*pjVal;
132 m_PVector[posValue] = k*(k+1.0)*pjVal/(-8.0*M_PI);
138 vnl_matrix <double> tmpMat = BMatrix.transpose() * BMatrix;
139 for (
unsigned int i = 0;i < vectorLength;++i)
140 tmpMat(i,i) += m_Lambda*LVector[i];
142 vnl_matrix_inverse <double> tmpInv(tmpMat);
144 m_TMatrix = tmpInv.inverse() * BMatrix.transpose();
148 m_DeconvolutionVector.clear();
150 for (
unsigned int k = 0;k <= m_LOrder;k += 2)
154 double delta = 0.001;
156 for (
double t = -1;t <= 1;t += delta)
158 double tmpVal = sqrt(1.0/((m_SharpnessRatio - 1)*t*t + 1));
159 if ((t == -1) || (t == 1))
161 lambdaL += tmpVal*boost::math::legendre_p(k,t);
166 lambdaL += 2*tmpVal*boost::math::legendre_p(k,t);
171 for (
int m = -k;m <= (int)k;++m)
172 m_DeconvolutionVector.push_back(lambdaL*2*M_PI/Zfactor);
175 for (
unsigned int i = 0;i < vectorLength;++i)
176 for (
unsigned int j = 0;j < numGrads;++j)
177 m_TMatrix(i,j) *= m_PVector[i]/m_DeconvolutionVector[i];
181 for (
unsigned int i = 0;i < vectorLength;++i)
182 for (
unsigned int j = 0;j < numGrads;++j)
183 m_TMatrix(i,j) *= m_PVector[i];
186 if ((m_Normalize)&&(m_FileNameSphereTesselation !=
""))
188 std::ifstream sphereIn(m_FileNameSphereTesselation.c_str());
190 m_SphereSHSampling.clear();
192 std::vector <double> dirTmp(3,0);
193 std::vector <double> sphericalCoords;
194 std::vector <double> shData;
196 while (!sphereIn.eof())
199 sphereIn.getline(tmpStr,2048);
201 if (strcmp(tmpStr,
"") == 0)
204 std::stringstream tmpStrStream(tmpStr);
205 tmpStrStream >> dirTmp[0] >> dirTmp[1] >> dirTmp[2];
210 for (
int k = 0;k <= (int)m_LOrder;k += 2)
211 for (
int m = -k;m <= k;++m)
214 m_SphereSHSampling.push_back(shData);
222 template <
typename TInputPixelType,
typename TOutputPixelType>
227 typedef itk::ImageRegionConstIterator <TInputImage> InputIteratorType;
228 typedef itk::ImageRegionIterator <TOutputImage> OutputIteratorType;
230 unsigned int vectorLength = (m_LOrder + 1)*(m_LOrder + 2)/2;
231 unsigned int numGrads = m_GradientIndexes.size();
232 unsigned int numB0 = m_B0Indexes.size();
234 OutputIteratorType resIt(this->GetOutput(),outputRegionForThread);
236 std::vector<InputIteratorType> diffusionIts(numGrads);
237 std::vector<InputIteratorType> b0Its(numGrads);
238 for (
unsigned int i = 0;i < numGrads;++i)
239 diffusionIts[i] = InputIteratorType(this->GetInput(m_GradientIndexes[i]),outputRegionForThread);
240 for (
unsigned int i = 0;i < numB0;++i)
241 b0Its[i] = InputIteratorType(this->GetInput(m_B0Indexes[i]),outputRegionForThread);
243 InputIteratorType refB0Itr;
244 if (m_ReferenceB0Image.IsNotNull())
245 refB0Itr = InputIteratorType(m_ReferenceB0Image, outputRegionForThread);
247 itk::VariableLengthVector <TOutputPixelType> outputData(vectorLength);
248 std::vector <double> tmpData(numGrads,0);
249 while (!diffusionIts[0].IsAtEnd())
252 if (m_ReferenceB0Image.IsNotNull())
254 b0Value = refB0Itr.Get();
259 for (
unsigned int i = 0;i < numB0;++i)
261 b0Value += b0Its[i].Get();
268 for (
unsigned int i = 0;i < numGrads;++i)
270 tmpData[i] = diffusionIts[i].Get();
274 for (
unsigned int i = 0;i < vectorLength;++i)
277 if ((isZero(tmpData))||(b0Value <= 0))
279 resIt.Set(outputData);
284 if (m_UseAganjEstimation)
286 for (
unsigned int i = 0;i < numGrads;++i)
288 double e = tmpData[i] / b0Value;
291 tmpData[i] = m_DeltaAganjRegularization / 2.0;
292 else if (e < m_DeltaAganjRegularization)
293 tmpData[i] = m_DeltaAganjRegularization / 2.0 + e * e / (2.0 * m_DeltaAganjRegularization);
294 else if (e < 1.0 - m_DeltaAganjRegularization)
297 tmpData[i] = 1.0 - m_DeltaAganjRegularization / 2.0 - (1.0 - e) * (1.0 - e) / (2.0 * m_DeltaAganjRegularization);
299 tmpData[i] = 1.0 - m_DeltaAganjRegularization / 2.0;
301 tmpData[i] = std::log(-std::log(tmpData[i]));
307 for (
unsigned int i = 0;i < vectorLength;++i)
308 for (
unsigned int j = 0;j < numGrads;++j)
309 outputData[i] += m_TMatrix(i,j)*tmpData[j];
311 if (!m_UseAganjEstimation)
313 for (
unsigned int i = 0;i < vectorLength;++i)
314 outputData[i] /= b0Value;
317 outputData[0] = 1/(2*sqrt(M_PI));
322 long double integralODF = 0;
323 for (
unsigned int i = 0;i < m_SphereSHSampling.size();++i)
324 for (
unsigned int j = 0;j < vectorLength;++j)
325 integralODF += m_SphereSHSampling[i][j]*outputData[j];
327 for (
unsigned int i = 0;i < vectorLength;++i)
328 outputData[i] /= integralODF;
331 resIt.Set(outputData);
itk::VectorImage< TOutputPixelType, 3 > TOutputImage
void BeforeThreadedGenerateData() ITK_OVERRIDE
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) ITK_OVERRIDE
Superclass::OutputImageRegionType OutputImageRegionType
double getNthSHValueAtPosition(int k, int m, double theta, double phi)
void AddGradientDirection(unsigned int i, std::vector< double > &grad)
void GenerateOutputInformation() ITK_OVERRIDE
void TransformCartesianToSphericalCoordinates(const VectorType &v, VectorType &resVec)