ANIMA  4.0
animaT1RelaxometryEstimationImageFilter.hxx
Go to the documentation of this file.
1 #pragma once
3 
4 #include <itkImageRegionIterator.h>
5 #include <itkImageRegionConstIterator.h>
6 
7 namespace anima
8 {
9 template <typename TInputImage, typename TOutputImage>
10 void
11 T1RelaxometryEstimationImageFilter <TInputImage,TOutputImage>
12 ::BeforeThreadedGenerateData()
13 {
14  if (this->GetNumberOfIndexedInputs() != m_FlipAngles.size())
15  itkExceptionMacro("There should be the same number of inputs and flip angles");
16 
17  if (this->GetNumberOfIndexedInputs() != 2)
18  itkExceptionMacro("There should be only two inputs for DESPOT1");
19 
20  Superclass::BeforeThreadedGenerateData();
21 }
22 
23 template <typename TInputImage, typename TOutputImage>
24 void
26 ::CheckComputationMask()
27 {
28  if (this->GetComputationMask())
29  return;
30 
31  typedef itk::ImageRegionConstIterator <InputImageType> IteratorType;
32  typedef itk::ImageRegionIterator <MaskImageType> MaskIteratorType;
33 
34  std::vector <IteratorType> inItrs(this->GetNumberOfIndexedInputs());
35  for (unsigned int i = 0;i < this->GetNumberOfIndexedInputs();++i)
36  inItrs[i] = IteratorType(this->GetInput(i),this->GetOutput()->GetLargestPossibleRegion());
37 
38  typename MaskImageType::Pointer maskImage = MaskImageType::New();
39  maskImage->Initialize();
40  maskImage->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
41  maskImage->SetSpacing (this->GetInput(0)->GetSpacing());
42  maskImage->SetOrigin (this->GetInput(0)->GetOrigin());
43  maskImage->SetDirection (this->GetInput(0)->GetDirection());
44  maskImage->Allocate();
45 
46  MaskIteratorType maskItr (maskImage,this->GetOutput()->GetLargestPossibleRegion());
47  while (!maskItr.IsAtEnd())
48  {
49  double averageVal = 0;
50  for (unsigned int i = 0;i < this->GetNumberOfIndexedInputs();++i)
51  averageVal += inItrs[i].Get();
52 
53  averageVal /= this->GetNumberOfIndexedInputs();
54 
55  bool maskPoint = (averageVal <= m_AverageSignalThreshold);
56 
57  if (maskPoint)
58  maskItr.Set(0);
59  else
60  maskItr.Set(1);
61 
62  for (unsigned int i = 0;i < this->GetNumberOfIndexedInputs();++i)
63  ++inItrs[i];
64 
65  ++maskItr;
66  }
67 
68  this->SetComputationMask(maskImage);
69 }
70 
71 template <typename TInputImage, typename TOutputImage>
72 void
74 ::DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread)
75 {
76  typedef itk::ImageRegionConstIterator <InputImageType> ImageIteratorType;
77  typedef itk::ImageRegionIterator <OutputImageType> OutImageIteratorType;
78 
79  OutImageIteratorType outT1Iterator(this->GetOutput(0),outputRegionForThread);
80  OutImageIteratorType outM0Iterator(this->GetOutput(1),outputRegionForThread);
81 
82  ImageIteratorType firstInputIterator(this->GetInput(0),outputRegionForThread);
83  ImageIteratorType secondInputIterator(this->GetInput(1),outputRegionForThread);
84 
85  OutImageIteratorType b1MapItr;
86  if (m_B1Map)
87  b1MapItr = OutImageIteratorType (m_B1Map,outputRegionForThread);
88 
89  typedef itk::ImageRegionIterator <MaskImageType> MaskIteratorType;
90  MaskIteratorType maskItr(this->GetComputationMask(),outputRegionForThread);
91 
92  while (!maskItr.IsAtEnd())
93  {
94  double b1Value = 1;
95  if (m_B1Map)
96  b1Value = b1MapItr.Get();
97 
98  if ((maskItr.Get() == 0)||(b1Value == 0))
99  {
100  outT1Iterator.Set(0);
101  outM0Iterator.Set(0);
102 
103  ++maskItr;
104  ++outT1Iterator;
105  ++outM0Iterator;
106 
107  ++firstInputIterator;
108  ++secondInputIterator;
109 
110  if (m_B1Map)
111  ++b1MapItr;
112 
113  continue;
114  }
115 
116  double basicT1Value = m_TRValue;
117 
118  double lnValue = secondInputIterator.Get() * std::sin(m_FlipAngles[0] * b1Value) * std::cos(m_FlipAngles[1] * b1Value) - firstInputIterator.Get() * std::cos(m_FlipAngles[0] * b1Value) * std::sin(m_FlipAngles[1] * b1Value);
119  lnValue /= secondInputIterator.Get() * std::sin(m_FlipAngles[0] * b1Value) - firstInputIterator.Get() * std::sin(m_FlipAngles[1] * b1Value);
120 
121  if (lnValue != lnValue) // test NaN
122  {
123  outT1Iterator.Set(1e-4);
124  outM0Iterator.Set(0);
125 
126  ++maskItr;
127  ++outT1Iterator;
128  ++outM0Iterator;
129 
130  ++firstInputIterator;
131  ++secondInputIterator;
132 
133  if (m_B1Map)
134  ++b1MapItr;
135 
136  continue;
137  }
138  else
139  lnValue = std::log(std::abs(lnValue));
140 
141  basicT1Value /= lnValue;
142 
143  if ((basicT1Value < 0)||(basicT1Value > m_T1UpperBoundValue))
144  basicT1Value = m_T1UpperBoundValue;
145 
146  outT1Iterator.Set(basicT1Value);
147 
148  // M0
149  double sumSignalData = 0;
150  double sumSquaredData = 0;
151 
152  double dataValue = (1.0 - std::exp(- m_TRValue / basicT1Value)) * std::sin(m_FlipAngles[0] * b1Value) / (1.0 - std::exp(-m_TRValue / basicT1Value) * std::cos(m_FlipAngles[0] * b1Value));
153 
154  sumSignalData += firstInputIterator.Get() * dataValue;
155  sumSquaredData += dataValue * dataValue;
156 
157  dataValue = (1.0 - std::exp(- m_TRValue / basicT1Value)) * std::sin(m_FlipAngles[1] * b1Value) / (1.0 - std::exp(- m_TRValue / basicT1Value) * std::cos(m_FlipAngles[1] * b1Value));
158 
159  sumSignalData += secondInputIterator.Get() * dataValue;
160  sumSquaredData += dataValue * dataValue;
161 
162  double m0Value = sumSignalData / sumSquaredData;
163 
164  if (m0Value <= 1.0e-4)
165  m0Value = 1.0e-4;
166  else if (m0Value > m_M0UpperBoundValue)
167  m0Value = m_M0UpperBoundValue;
168 
169  outM0Iterator.Set(m0Value);
170 
171  ++maskItr;
172  ++outT1Iterator;
173  ++outM0Iterator;
174 
175  ++firstInputIterator;
176  ++secondInputIterator;
177 
178  if (m_B1Map)
179  ++b1MapItr;
180  }
181 }
182 
183 } // end namespace anima
Superclass::OutputImageRegionType OutputImageRegionType