ANIMA  4.0
animaGammaMixtureT2RelaxometryEstimationImageFilter.hxx
Go to the documentation of this file.
1 #pragma once
3 
4 #include <itkImageRegionIterator.h>
5 #include <itkImageRegionConstIterator.h>
6 
7 #include <animaNLOPTOptimizers.h>
9 
10 namespace anima
11 {
12 
13 template <class TPixelScalarType>
14 void
15 GammaMixtureT2RelaxometryEstimationImageFilter <TPixelScalarType>
16 ::BeforeThreadedGenerateData()
17 {
18  Superclass::BeforeThreadedGenerateData();
19 
20  this->GetOutput(2)->FillBuffer(1.0);
21 
22  m_WeightsImage = VectorOutputImageType::New();
23  m_WeightsImage->Initialize();
24  m_WeightsImage->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
25  m_WeightsImage->SetSpacing (this->GetInput(0)->GetSpacing());
26  m_WeightsImage->SetOrigin (this->GetInput(0)->GetOrigin());
27  m_WeightsImage->SetDirection (this->GetInput(0)->GetDirection());
28  m_WeightsImage->SetVectorLength(3);
29  m_WeightsImage->Allocate();
30 
31  OutputVectorType zero(3);
32  zero.Fill(0.0);
33  m_WeightsImage->FillBuffer(zero);
34 
35  m_MeanParamImage = VectorOutputImageType::New();
36  m_MeanParamImage->Initialize();
37  m_MeanParamImage->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
38  m_MeanParamImage->SetSpacing (this->GetInput(0)->GetSpacing());
39  m_MeanParamImage->SetOrigin (this->GetInput(0)->GetOrigin());
40  m_MeanParamImage->SetDirection (this->GetInput(0)->GetDirection());
41  m_MeanParamImage->SetVectorLength(3);
42  m_MeanParamImage->Allocate();
43 
44  m_MeanParamImage->FillBuffer(zero);
45 }
46 
47 template <class TPixelScalarType>
48 void
50 ::CheckComputationMask()
51 {
52  if (this->GetComputationMask())
53  return;
54 
55  typedef itk::ImageRegionConstIterator <InputImageType> IteratorType;
56  typedef itk::ImageRegionIterator <MaskImageType> MaskIteratorType;
57 
58  std::vector <IteratorType> inItrs(this->GetNumberOfIndexedInputs());
59  for (unsigned int i = 0;i < this->GetNumberOfIndexedInputs();++i)
60  inItrs[i] = IteratorType(this->GetInput(i),this->GetOutput(0)->GetLargestPossibleRegion());
61 
62  typename MaskImageType::Pointer maskImage = MaskImageType::New();
63  maskImage->Initialize();
64  maskImage->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
65  maskImage->SetSpacing (this->GetInput(0)->GetSpacing());
66  maskImage->SetOrigin (this->GetInput(0)->GetOrigin());
67  maskImage->SetDirection (this->GetInput(0)->GetDirection());
68  maskImage->Allocate();
69 
70  MaskIteratorType maskItr (maskImage,this->GetOutput(0)->GetLargestPossibleRegion());
71  while (!maskItr.IsAtEnd())
72  {
73  double averageVal = 0;
74  for (unsigned int i = 0;i < this->GetNumberOfIndexedInputs();++i)
75  averageVal += inItrs[i].Get();
76 
77  averageVal /= this->GetNumberOfIndexedInputs();
78 
79  bool maskPoint = (averageVal <= m_AverageSignalThreshold);
80 
81  if (maskPoint)
82  maskItr.Set(0);
83  else
84  maskItr.Set(1);
85 
86  for (unsigned int i = 0;i < this->GetNumberOfIndexedInputs();++i)
87  ++inItrs[i];
88 
89  ++maskItr;
90  }
91 
92  this->SetComputationMask(maskImage);
93 }
94 
95 template <class TPixelScalarType>
96 void
98 ::DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread)
99 {
100  typedef itk::ImageRegionConstIterator <InputImageType> ImageConstIteratorType;
101  typedef itk::ImageRegionIterator <InputImageType> ImageIteratorType;
102  typedef itk::ImageRegionIterator <VectorOutputImageType> VectorImageIteratorType;
103 
104  VectorImageIteratorType outWeightsIterator(this->GetWeightsImage(),outputRegionForThread);
105  VectorImageIteratorType outMeanParamsIterator(this->GetMeanParamImage(),outputRegionForThread);
106 
107  ImageIteratorType outM0Iterator(this->GetM0OutputImage(),outputRegionForThread);
108  ImageIteratorType outMWFIterator(this->GetMWFOutputImage(),outputRegionForThread);
109  ImageIteratorType outB1Iterator(this->GetB1OutputImage(),outputRegionForThread);
110  ImageIteratorType outSigmaSqIterator(this->GetSigmaSquareOutputImage(),outputRegionForThread);
111 
112  unsigned int numInputs = this->GetNumberOfIndexedInputs();
113  std::vector <ImageConstIteratorType> inIterators;
114  for (unsigned int i = 0;i < numInputs;++i)
115  inIterators.push_back(ImageConstIteratorType(this->GetInput(i),outputRegionForThread));
116 
117  typedef itk::ImageRegionIterator <MaskImageType> MaskIteratorType;
118  MaskIteratorType maskItr(this->GetComputationMask(),outputRegionForThread);
119 
120  ImageIteratorType t1MapItr;
121  if (m_T1Map)
122  t1MapItr = ImageIteratorType(m_T1Map,outputRegionForThread);
123 
124  std::vector <double> VarParamsFixed(3, m_ShortT2Var);
125  VarParamsFixed[1] = m_MediumT2Var;
126  VarParamsFixed[2] = m_HighT2Var;
127 
128  std::vector <double> MeanParamsInit(3, m_ShortT2Mean);
129  MeanParamsInit[1] = 110.0;
130  MeanParamsInit[2] = m_HighT2Mean;
131 
132  using OptimizerType = anima::NLOPTOptimizers;
133  using CostFunctionType = anima::B1GammaMixtureT2RelaxometryCostFunction;
134 
135  unsigned int n_compartments = 3;
136  OptimizerType::ParametersType signalValues(numInputs);
137  OptimizerType::ParametersType t2OptimizedWeights(n_compartments);
138 
139  OutputVectorType outputT2Weights(n_compartments);
140  OutputVectorType outputMeanParams(n_compartments);
141 
142  typename CostFunctionType::Pointer cost = CostFunctionType::New();
143  cost->SetEchoSpacing(m_EchoSpacing);
144  cost->SetExcitationFlipAngle(m_T2ExcitationFlipAngle);
145  cost->SetGammaMeans(MeanParamsInit);
146  cost->SetGammaVariances(VarParamsFixed);
147  cost->SetConstrainedParameters(m_ConstrainedParameters);
148  cost->SetGammaIntegralTolerance(m_GammaIntegralTolerance);
149 
150  unsigned int dimension = cost->GetNumberOfParameters();
151 
152  itk::Array<double> lowerBounds(dimension);
153  itk::Array<double> upperBounds(dimension);
154  OptimizerType::ParametersType p(dimension);
155  lowerBounds[0] = 1.0 * m_T2FlipAngles[0];
156  upperBounds[0] = 2.0 * m_T2FlipAngles[0];
157 
158  // Initializations for L & U bounds and initial guesses.
159  if (!m_ConstrainedParameters)
160  {
161  lowerBounds[1] = m_LowerShortT2;
162  lowerBounds[2] = m_LowerMediumT2;
163  lowerBounds[3] = m_LowerHighT2;
164 
165  upperBounds[1] = m_UpperShortT2;
166  upperBounds[2] = m_UpperMediumT2;
167  upperBounds[3] = m_UpperHighT2;
168  }
169  else
170  {
171  lowerBounds[1] = m_LowerMediumT2;
172  upperBounds[1] = m_UpperMediumT2;
173  }
174 
175  while (!maskItr.IsAtEnd())
176  {
177  outputT2Weights.Fill(0);
178  outputMeanParams.Fill(0);
179 
180  if (maskItr.Get() == 0)
181  {
182  outWeightsIterator.Set(outputT2Weights);
183  outMeanParamsIterator.Set(outputMeanParams);
184  outM0Iterator.Set(0);
185  outMWFIterator.Set(0.0);
186  outB1Iterator.Set(1.0);
187  outSigmaSqIterator.Set(0.0);
188 
189  ++maskItr;
190  ++outWeightsIterator;
191  ++outMeanParamsIterator;
192  ++outM0Iterator;
193  ++outMWFIterator;
194  ++outB1Iterator;
195  ++outSigmaSqIterator;
196 
197  for (unsigned int i = 0;i < numInputs;++i)
198  ++inIterators[i];
199 
200  if (m_T1Map)
201  ++t1MapItr;
202 
203  continue;
204  }
205 
206  double t1Value = 1000.0;
207  double m0Value = 0.0;
208 
209  for (unsigned int i = 0;i < numInputs;++i)
210  signalValues[i] = inIterators[i].Get();
211 
212  if (m_T1Map)
213  {
214  t1Value = t1MapItr.Get();
215  if (t1Value <= 0.0)
216  t1Value = 1000.0;
217  }
218 
219  cost->SetT1Value(t1Value);
220  cost->SetT2RelaxometrySignals(signalValues);
221 
222  OptimizerType::Pointer opt = OptimizerType::New();
223  opt->SetAlgorithm(NLOPT_LD_CCSAQ);
224  opt->SetXTolRel(1.0e-5);
225  opt->SetFTolRel(1.0e-7);
226  opt->SetMaxEval(500);
227  opt->SetVectorStorageSize(2000);
228 
229  opt->SetLowerBoundParameters(lowerBounds);
230  opt->SetUpperBoundParameters(upperBounds);
231 
232  p[0] = 1.2 * m_T2FlipAngles[0];
233  if (!m_ConstrainedParameters)
234  {
235  // Set Initial guesses
236  p[1] = 20;
237  p[2] = 110;
238  p[3] = 2000;
239  }
240  else
241  p[1] = 110;
242 
243  opt->SetInitialPosition(p);
244  opt->SetMaximize(false);
245  opt->SetCostFunction(cost);
246 
247  opt->StartOptimization();
248  p = opt->GetCurrentPosition();
249 
250  t2OptimizedWeights = cost->GetOptimalT2Weights();
251 
252  // Get M0
253  m0Value = 0;
254  for (unsigned int i = 0;i < n_compartments;++i)
255  m0Value += t2OptimizedWeights[i];
256 
257  for (unsigned int i = 0;i < n_compartments;++i)
258  {
259  if (m0Value > 0.0)
260  outputT2Weights[i] = t2OptimizedWeights[i] / m0Value;
261  else
262  outputT2Weights[i] = 0.0;
263  }
264 
265  outM0Iterator.Set(m0Value);
266  outWeightsIterator.Set(outputT2Weights);
267 
268  if (!m_ConstrainedParameters)
269  {
270  for (unsigned int i = 0;i < 3;++i)
271  outputMeanParams[i] = p[i + 1];
272  }
273  else
274  {
275  outputMeanParams[0] = m_ShortT2Mean;
276  outputMeanParams[1] = p[1];
277  outputMeanParams[2] = m_HighT2Mean;
278  }
279 
280  outMeanParamsIterator.Set(outputMeanParams);
281 
282  double mwfValue = outputT2Weights[0];
283 
284  outMWFIterator.Set(mwfValue);
285 
286  double b1Value = p[0] / m_T2FlipAngles[0];
287  outB1Iterator.Set(b1Value);
288 
289  outSigmaSqIterator.Set(cost->GetSigmaSquare());
290 
291  this->IncrementNumberOfProcessedPoints();
292  ++maskItr;
293  ++outWeightsIterator;
294  ++outMeanParamsIterator;
295  ++outM0Iterator;
296  ++outMWFIterator;
297  ++outB1Iterator;
298  ++outSigmaSqIterator;
299 
300  for (unsigned int i = 0;i < numInputs;++i)
301  ++inIterators[i];
302 
303  if (m_T1Map)
304  ++t1MapItr;
305  }
306 }
307 
308 } // end namespace anima
Implements an ITK wrapper for the NLOPT library.