Tomato
OxCalculatorT1Shmolli.hxx
Go to the documentation of this file.
1 
7 #ifndef TOMATO_OXCALCULATORT1SHMOLLI_HXX
8 #define TOMATO_OXCALCULATORT1SHMOLLI_HXX
9 
10 namespace Ox {
11 
12  template< typename MeasureType >
13  int
16 
17  // Shmolli 51111 needs exactly 7 samples
18  if (this->getNSamples() != 7){
19  throw std::runtime_error("T1_SHMOLLI reconstruction available only for 7 samples.");
20  }
21 
22 // // base class prepareToCalculate()
23 // if(Calculator<MeasureType>::prepareToCalculate() == 1) {
24 // return 1; // EXIT_FAILURE
25 // }
26 
27  // if fitter does not have to iterate, do not calculate
28  if (this->getFitter()->getMaxFunctionEvals() == 0){
29  return 1; // EXIT_FAILURE
30  }
31 
32  // verify invTimes are sorted
33  for (int i = 0; i < this->getNSamples()-1; i++){
34  if (this->getInvTimes()[i] > this->getInvTimes()[i+1]){
35  throw std::runtime_error("InvTimes have to be sorted!");
36  }
37  }
38 
39  // calculate sign
40  this->getSignCalculator()->setNSamples(this->getNSamples());
41  this->getSignCalculator()->setInvTimes(this->getInvTimes());
42  this->getSignCalculator()->setSigMag(this->getSigMag());
43  this->getSignCalculator()->setSigPha(this->getSigPha());
44  this->getSignCalculator()->setSignal(this->_Signal);
45  this->getSignCalculator()->setSigns(this->_Signs);
46 
47  this->getSignCalculator()->calculateSign();
48 
49  // calculate start point
50  this->getStartPointCalculator()->setNDims(this->_nDims);
51  if (!this->getStartPointCalculator()->getInputStartPoint()){
52  if (this->_nDims == 3){
53  MeasureType const temp[] = {100, 200, 1000};
54  this->getStartPointCalculator()->setInputStartPoint(temp);
55  } else {
56  throw std::runtime_error("Calculator: Set InputStartPoint in StartPointCalculator");
57  }
58  }
59  this->getStartPointCalculator()->setNSamples(this->getNSamples());
60  this->getStartPointCalculator()->setInvTimes(this->getInvTimes());
61  this->getStartPointCalculator()->setSigMag(this->getSigMag());
62  this->getStartPointCalculator()->setSigns(this->getSigns());
63  this->getStartPointCalculator()->setCalculatedStartPoint(this->_StartPoint);
64 
65  this->getStartPointCalculator()->calculateStartPoint();
66 
67  // calculate TRR
68  calculateTRRaverageHB();
69 
70  return 0; // EXIT_SUCCESS
71  };
72 
73  template< typename MeasureType >
74  int
76  ::getStartPointSKPShmolli(const MeasureType * invTimes5, const MeasureType * invTimes6, const MeasureType * invTimes7,
77  const MeasureType * sigMag5, const MeasureType * sigMag6, const MeasureType * sigMag7,
78  const MeasureType * signs5, const MeasureType * signs6, const MeasureType * signs7){
79 
80  int nStartFitPoints = 0;
81 
82  StartPointCalculator<MeasureType> *startPointCalculator = this->getStartPointCalculator();
83  startPointCalculator->setCalculatedStartPoint(this->_StartPoint);
84 
85  if (this->getSigPha()){
86  startPointCalculator->setNSamples(5);
87  startPointCalculator->setInvTimes(invTimes5);
88  startPointCalculator->setSigMag(sigMag5);
89  startPointCalculator->setSigns(signs5);
90  nStartFitPoints = startPointCalculator->calculateStartPoint();
91 
92  if( nStartFitPoints < 3 ) {
93  startPointCalculator->setNSamples(6);
94  startPointCalculator->setInvTimes(invTimes6);
95  startPointCalculator->setSigMag(sigMag6);
96  startPointCalculator->setSigns(signs6);
97  nStartFitPoints = startPointCalculator->calculateStartPoint();
98  }
99  if( nStartFitPoints < 3 ) {
100  startPointCalculator->setNSamples(7);
101  startPointCalculator->setInvTimes(invTimes7);
102  startPointCalculator->setSigMag(sigMag7);
103  startPointCalculator->setSigns(signs7);
104  startPointCalculator->calculateStartPoint();
105  }
106  } else {
107  if( nStartFitPoints < 3 ) {
108  startPointCalculator->setNSamples(7);
109  startPointCalculator->setInvTimes(invTimes7);
110  startPointCalculator->setSigMag(sigMag7);
111  startPointCalculator->setSigns(signs7);
112  startPointCalculator->calculateStartPoint();
113  }
114  }
115 
116  return 0; // EXIT_SUCCESS
117  }
118 
119  template< typename MeasureType >
120  int
123 
124  // if shmolli (7 samples)
125  const MeasureType *invTimes = this->getInvTimes();
126  MeasureType invTimesDifferences[4];
127  if (this->_nSamples == 7) {
128  invTimesDifferences[0] = invTimes[3] - invTimes[0];
129  invTimesDifferences[1] = invTimes[4] - invTimes[3];
130  invTimesDifferences[2] = invTimes[5] - invTimes[4];
131  invTimesDifferences[3] = invTimes[6] - invTimes[5];
132  }
133 
134  _TRRaverageHB = KWUtil::calcMeanArray(4, invTimesDifferences);
135  // m_TRRaverageHB = KWUtil::calcMedianArray(4, invTimesDifferences);
136 
137  return 0; // EXIT_SUCCESS
138  }
139 
140  template< typename MeasureType >
141  int
144 
145  this->_Results = std::map <std::string, MeasureType>();
146 
147  // calculate if higher than the cutoff
148  if (KWUtil::calcMeanArray(this->getNSamples(), this->getSigMag()) < this->getMeanCutOff()) {
149  return 0; // EXIT_SUCCESS
150  }
151 
152  // continue only if prepareToCalculate was successful
153  if(this->prepareToCalculate() == 1){ //EXIT_FAILURE
154  return 1; // EXIT_FAILURE
155  }
156 
157  // some initialisation
158  const double MaxTIForSignInvert = (this->MAX_T1_TRESHOLD * 0.67);
159  MeasureType lastValue = 1e32;
160  MeasureType lastValueTemp = lastValue;
161 
162  // nShmolliSamplesUsed = 5 // =(T1s567[0] < TRRaverageHB) && (T1s567[0] > 1);
163  // nShmolliSamplesUsed = 6 // =(chi567[1]*T1s567[1] < (chi567[0]*TRRaverageHB )) && (T1s567[1] > 1);
164  // nShmolliSamplesUsed = 7 // =((chi567[2]*T1s567[2]) < (chi567[1]* TRRaverageHB*0.4 )) && (T1s567[2] > 1);
165 
166  // temporary defs here
167  double T1temp = 0;
168  double chiTemp = 1e32; // legacy reasons
169  unsigned int nShmolliSamplesUsed = 0;
170  MeasureType TRRaverageHB = this->_TRRaverageHB;
171 
172  std::map <std::string, MeasureType> results0, results5, results6, results7;
173  MeasureType signal5[5], signal6[6], signal7[7];
174  MeasureType invTimes5[5], invTimes6[6], invTimes7[7];
175  MeasureType signs5[5], signs6[6], signs7[7];
176 
177  getShmolliSamples(this->_InvTimes, invTimes5, invTimes6, invTimes7);
178  getShmolliSamples(this->_Signal, signal5, signal6, signal7);
179  getShmolliSamples(this->_Signs, signs5, signs6, signs7);
180 
181  this->getStartPointSKPShmolli(
182  invTimes5, invTimes6, invTimes7,
183  signal5, signal6, signal7,
184  signs5, signs6, signs7);
185 
186  signs5[0] = -1; // KW: Why only in the 5 samples case and not in the 6 or 7 samples case? small amount of pixels (94) influenced by it
187  signal5[0] = -fabs(signal5[0]);
188 
189  // 5els fitting
190  results5 = this->calculateWithSignCheck(5, invTimes5, signal5, signs5);
191 
192  if (results5["A"] > 1){ // converged
193  nShmolliSamplesUsed = 5;
194  T1temp = results5["T1"];
195  chiTemp = results5["ChiSqrt"]; // legacy
196  } else {
197  chiTemp = results5["LastValue"]; // legacy, very small amount of pixels (3) influenced by it
198  }
199 
200  // 6els fitting
201  results6 = this->calculateWithSignCheck(6, invTimes6, signal6, signs6);
202 
203  if ((T1temp <= TRRaverageHB) // KW: has to be T1temp in these cases that do not converge
204  || (results6["A"] <= 1) // not converged
205  || (results6["T1"] <= 0.4 * TRRaverageHB) // prevent from errors in v.short range. KW: very small amount of pixels (14) influenced by it
206  )
207  {
208 
209  if ((results6["A"] > 1) // converged
210  && (results6["ChiSqrt"] * results6["T1"] < chiTemp * TRRaverageHB))
211  {
212  nShmolliSamplesUsed = 6;
213  T1temp = results6["T1"];
214  }
215 
216  // 7els fitting
217  results7 = this->calculateWithSignCheck(7, invTimes7, signal7, signs7);
218 
219  if ((results7["A"] > 1) // converged
220  && (results7["ChiSqrt"] * results7["T1"] < results6["ChiSqrt"] * TRRaverageHB * 0.4) // KW: in the article results5 instead of 6. 1422 pixels influenced by change
221  && (T1temp < TRRaverageHB) // KW: not a single pixel influenced by it
222  )
223  {
224  nShmolliSamplesUsed = 7; // use all 3 IR only if SD improvement compensates for a limit of 5*MAxT1<2*T_HB
225  }
226  }
227 
228  // assign output values
229  if (nShmolliSamplesUsed == 5) {
230  this->_Results = results5;
231  }
232  else if (nShmolliSamplesUsed == 6) {
233  this->_Results = results6;
234  }
235  else if (nShmolliSamplesUsed == 7) {
236  this->_Results = results7;
237  } else {
238  this->_Results = results0;
239  //std::cout << "ShMOLLI calculation error" << std::endl;
240  }
241  this->_Results["NShmolliSamplesUsed"] = nShmolliSamplesUsed;
242  this->_Results["hasBeenCalculated"] = 1;
243  this->_ParametersAfterFitting[0] = this->_Results["A"];
244  this->_ParametersAfterFitting[1] = this->_Results["B"];
245  this->_ParametersAfterFitting[2] = this->_Results["T1star"];
246 
247  return 0; // EXIT_SUCCESS
248  }
249 
250  template< typename MeasureType >
251  int
253  ::getShmolliSamples(const MeasureType* inArray, MeasureType* outArray5, MeasureType* outArray6, MeasureType* outArray7){
254  int indexes7[] = {0,1,2,3,4,5,6};
255  int indexes6[] = {0,1,3,4,5,6};
256  int indexes5[] = {0,3,4,5,6};
257  for (int i = 0; i < 7; i++) outArray7[i] = inArray[indexes7[i]];
258  for (int i = 0; i < 6; i++) outArray6[i] = inArray[indexes6[i]];
259  for (int i = 0; i < 5; i++) outArray5[i] = inArray[indexes5[i]];
260  return 0; // EXIT_SUCCESS
261  }
262 
263 } //namespace Ox
264 
265 #endif //TOMATO_OXCALCULATORT1SHMOLLI_HXX
int calculateTRRaverageHB()
Definition: OxCalculatorT1Shmolli.hxx:122
virtual int calculate()
Definition: OxCalculatorT1Shmolli.hxx:143
virtual int prepareToCalculate()
Definition: OxCalculatorT1Shmolli.hxx:15
Definition: OxCalculatorT1Shmolli.h:22
Definition: OxStartPointCalculator.h:21
Definition: OxCalculator.h:19
virtual int calculateStartPoint()=0