Tomato
OxCalculatorT1WithSignCheck.hxx
Go to the documentation of this file.
1 
7 #ifndef Tomato_OXCALCULATORT1WithSignCheck_HXX
8 #define Tomato_OXCALCULATORT1WithSignCheck_HXX
9 
10 namespace Ox {
11 
12  template< typename MeasureType >
13  int
16 
17  // if fitter does not have to iterate, do not calculate
18  if (this->getFitter()->getMaxFunctionEvals() == 0){
19  return 1; // EXIT_FAILURE
20  }
21 
22  // check if ndims has been set
23  if (this->_nDims != 2 && this->_nDims != 3){
24  throw std::runtime_error("CalculatorT1WithSignCheck::prepareToCalculate currently implemented only for _nDims of 2 or 3");
25  }
26 
27  if (!this->getInvTimes()){
28  throw std::runtime_error("CalculatorT1WithSignCheck::prepareToCalculate InvTimes have to be provided!");
29  }
30 
31  // verify invTimes are sorted
32  for (int i = 0; i < this->getNSamples()-1; i++){
33  if (this->getInvTimes()[i] > this->getInvTimes()[i+1]){
34  throw std::runtime_error("CalculatorT1WithSignCheck::prepareToCalculate InvTimes have to be sorted!");
35  }
36  }
37 
38  // calculate sign
39  if (this->getSignCalculator()) {
40 
41  this->getSignCalculator()->setNSamples(this->getNSamples());
42  this->getSignCalculator()->setInvTimes(this->getInvTimes());
43  this->getSignCalculator()->setSigMag(this->getSigMag());
44  this->getSignCalculator()->setSigPha(this->getSigPha());
45  this->getSignCalculator()->setSignal(this->_Signal);
46  this->getSignCalculator()->setSigns(this->_Signs);
47 
48  this->getSignCalculator()->calculateSign();
49 
50  } else {
51  for (int i = 0; i < this->_nSamples; ++i){
52  this->_Signal[i] = this->_SigMag[i];
53  this->_Signs[i] = 1; // no flip
54  }
55  }
56 
57  // calculate start point
58  if (this->getStartPointCalculator()) {
59  this->getStartPointCalculator()->setNDims(this->_nDims);
60  if (!this->getStartPointCalculator()->getInputStartPoint()) {
61  if (this->_nDims == 2) {
62  MeasureType const temp[] = {100, 1000};
63  this->getStartPointCalculator()->setInputStartPoint(temp);
64  } else if (this->_nDims == 3) {
65  MeasureType const temp[] = {100, 200, 1000};
66  this->getStartPointCalculator()->setInputStartPoint(temp);
67  }
68  }
69  this->getStartPointCalculator()->setNSamples(this->getNSamples());
70  this->getStartPointCalculator()->setInvTimes(this->getInvTimes());
71  this->getStartPointCalculator()->setSigMag(this->getSigMag());
72  this->getStartPointCalculator()->setSigns(this->getSigns());
73  this->getStartPointCalculator()->setCalculatedStartPoint(this->_StartPoint);
74 
75  this->getStartPointCalculator()->calculateStartPoint();
76  } else {
77  for (int i = 0; i < this->_nDims; ++i){
78  this->_StartPoint[i] = 500;
79  }
80  }
81 
82  return 0; // EXIT_SUCCESS
83  };
84 
85  template< typename MeasureType >
86  int
89 
90  this->_Results = std::map <std::string, MeasureType>();
91 
92  // calculate if higher than the cutoff
93  if (KWUtil::calcMeanArray(this->getNSamples(), this->getSigMag()) < this->getMeanCutOff()) {
94  return 0; // EXIT_SUCCESS
95  }
96 
97  // get ready, continue if prepareToCalculate EXIT_SUCCESS
98  if (this->prepareToCalculate() == 1) {
99  return 1; // EXIT_FAILURE
100  }
101 
102  this->_Results = calculateWithSignCheck( this->getNSamples(),
103  this->getInvTimes(),
104  this->getSignal(),
105  this->getSigns());
106 
107  return 0; // EXIT_SUCCESS
108  }
109 
110  template< typename MeasureType >
111  std::map <std::string, MeasureType>
113  ::calculateWithSignCheck(int nSamples, const MeasureType* invTimes, MeasureType* signal, MeasureType* signs){
114 
115  // some initialisation
116  std::map <std::string, MeasureType> results;
117 
118  MeasureType mse = 1e32;
119  MeasureType mseTemp = 1e32;
120  MeasureType *tempParameters = new MeasureType[this->_nDims];
121  MeasureType *calculatedParameters = new MeasureType[this->_nDims];
122  int timeFlip = 0;
123 
124  KWUtil::copyArrayToArray(this->_nDims, tempParameters, this->_StartPoint); // start from the starting point
125 
126  // configure Functions object and fitter object
127  this->getModel()->setNSamples(nSamples);
128  this->getModel()->setSignal(signal);
129  this->getModel()->setInvTimes(invTimes);
130 
131  // configure Fitter
132  this->getFitter()->setParameters(tempParameters);
133  this->getFitter()->setModel(this->getModel());
134 
135  // fit
136  this->getFitter()->performFitting();
137 
138  // save the tempResults at the best tempResults
139  KWUtil::copyArrayToArray(this->_nDims, calculatedParameters, this->getFitter()->getParameters());
140  mse = this->getFitter()->getMse();
141 
142  // look for better solutions than the above one
143  for (int iSwap = 0; iSwap < nSamples; iSwap++) {
144 
145  // continue if sign was already calculated before
146  if (signs[iSwap] != 0) continue;
147  signs[iSwap] = 1;
148 
149  // continue only if TI in reasonable range
150  if (invTimes[iSwap] > this->MaxTIForSignInvert) continue;
151 
152  // in each iteration change the sign of one of the signal elements
153  signal[iSwap] = -fabs(signal[iSwap]);
154 
155  // start from the starting point
156  this->getFitter()->copyToParameters(this->_StartPoint);
157 
158  // fit
159  this->getFitter()->performFitting();
160  mseTemp = this->getFitter()->getMse();
161 
162  // are these the best tempResults?
163  if (mseTemp < mse) {
164  // save the tempResults at the best tempResults
165  KWUtil::copyArrayToArray(this->_nDims, calculatedParameters, this->getFitter()->getParameters());
166  mse = mseTemp;
167  timeFlip = iSwap + 1;
168  }
169  }
170 
171  // sign and signal for the best fit
172  for (int i = 0; i < nSamples; i++) signs[i] = 1;
173  for (int i = 0; i < timeFlip; i++) signs[i] = -1;
174  for (int i = 0; i < nSamples; i++) signal[i] = signs[i] * fabs(signal[i]);
175 
176  // errors
177  int deltasCalculatedExit = 1;
178  MeasureType *fitDeltas = new MeasureType[this->_nDims];
179  MeasureType *jacobian = new MeasureType[nSamples*this->_nDims];
180  this->getModel()->calcLSJacobian(calculatedParameters, jacobian);
181  deltasCalculatedExit = KWUtil::calculateFitError(
182  nSamples,
183  this->_nDims,
184  jacobian,
185  sqrt(mse*nSamples),
186  fitDeltas);
187  delete [] jacobian;
188 
189  if (mse != 1e32 && calculatedParameters[0] != 0) {
190  KWUtil::copyArrayToArray(this->_nDims, this->_ParametersAfterFitting, calculatedParameters);
191  if (this->_nDims == 2) {
192  results["A"] = calculatedParameters[0];
193  results["T1star"] = calculatedParameters[1];
194  results["T1"] = calculatedParameters[1];
195  results["R2"] = calculateR2FromModel(nSamples, invTimes, signal, calculatedParameters);
196  results["R2Abs"] = calculateR2AbsFromModel(nSamples, invTimes, signal, calculatedParameters);
197  results["ChiSqrt"] = KWUtil::getChiSqrt(mse*nSamples, nSamples);
198  results["LastValue"] = mse*nSamples;
199  results["timeFlip"] = timeFlip;
200 
201  results["deltaA"] = -1;
202  results["deltaT1"] = -1;
203  results["deltaT1star"] = -1;
204  if (deltasCalculatedExit == 0) {
205  results["deltaA"] = fitDeltas[0];
206  results["deltaT1"] = fitDeltas[1];
207  results["deltaT1star"] = fitDeltas[1];
208  }
209  } else if (this->_nDims == 3) {
210  results["T1"] = calculatedParameters[2] * (calculatedParameters[1] / calculatedParameters[0] - 1.);
211  results["R2"] = calculateR2FromModel(nSamples, invTimes, signal, calculatedParameters);
212  results["R2Abs"] = calculateR2AbsFromModel(nSamples, invTimes, signal, calculatedParameters);
213  results["A"] = calculatedParameters[0];
214  results["B"] = calculatedParameters[1];
215  results["T1star"] = calculatedParameters[2];
216  results["ChiSqrt"] = KWUtil::getChiSqrt(mse*nSamples, nSamples);
217  results["SNR"] = (results["B"] - results["A"]) / (results["ChiSqrt"] + 0.001);
218  results["LastValue"] = mse*nSamples;
219  results["timeFlip"] = timeFlip;
220 
221  results["deltaA"] = -1;
222  results["deltaB"] = -1;
223  results["deltaT1star"] = -1;
224  results["deltaT1"] = -1;
225  if (deltasCalculatedExit == 0){
226  results["deltaA"] = fitDeltas[0];
227  results["deltaB"] = fitDeltas[1];
228  results["deltaT1star"] = fitDeltas[2];
229  results["deltaT1"] =
230  results["deltaT1star"] * (results["B"]/results["A"] - 1)
231  + results["T1star"] * ( results["deltaB"]/results["A"]
232  + results["B"]*results["deltaA"]/(results["A"] * results["A"]) );
233  }
234  }
235  }
236 
237  delete [] tempParameters;
238  delete [] calculatedParameters;
239  delete [] fitDeltas;
240  return results;
241  }
242 
243  template< typename MeasureType >
244  MeasureType
246  ::calculateR2FromModel(int nSamples, const MeasureType* times, const MeasureType* signal, const MeasureType* parameters) {
247 
248  MeasureType *fitted = new MeasureType[nSamples];
249 
250  for (int i = 0; i < nSamples; i++){
251  fitted[i] = this->_Model->calcModelValue(parameters, times[i]);
252  }
253 
254  double result = KWUtil::calcR2cor(nSamples, fitted, signal);
255 
256  delete [] fitted;
257  return result;
258  }
259 
260  template< typename MeasureType >
261  MeasureType
263  ::calculateR2AbsFromModel(int nSamples, const MeasureType* invTimes, const MeasureType* signal, const MeasureType* parameters) {
264 
265  MeasureType *absFitted = new MeasureType[nSamples];
266  MeasureType *absYsignal = new MeasureType[nSamples];
267 
268  MeasureType A = parameters[0];
269  MeasureType B = parameters[1];
270  MeasureType T1star = parameters[2];
271 
272  for (int i = 0; i < nSamples; i++){
273  MeasureType fitted;
274  fitted = this->_Model->calcModelValue(parameters, invTimes[i]);
275  absFitted[i] = fabs(fitted);
276  absYsignal[i] = fabs(signal[i]);
277  }
278 
279  double result = KWUtil::calcR2cor(nSamples, absFitted, absYsignal);
280 
281  delete[] absFitted;
282  delete[] absYsignal;
283  return result;
284  }
285 
286  template< typename MeasureType >
287  const MeasureType *
289  ::getInvTimes() const {
290  if (!this->_InvTimes) {
291  throw std::runtime_error("_InvTimes equals 0. Set _InvTimes");
292  };
293  return this->_InvTimes;
294  }
295 
296  template<typename MeasureType>
298  return _DoCalculateSDMap;
299  }
300 
301  template<typename MeasureType>
303  CalculatorT1WithSignCheck::_DoCalculateSDMap = doCalculateSDMap;
304  }
305 
306 
307 } //namespace Ox
308 
309 #endif //Tomato_OXCALCULATORT1WithSignCheck_HXX
virtual int calculate()
Definition: OxCalculatorT1WithSignCheck.hxx:88
virtual int prepareToCalculate()
Definition: OxCalculatorT1WithSignCheck.hxx:15
void setDoCalculateSDMap(bool _DoCalculateSDMap)
Definition: OxCalculatorT1WithSignCheck.hxx:302
virtual std::map< std::string, MeasureType > calculateWithSignCheck(int nSamples, const MeasureType *invTimes, MeasureType *signal, MeasureType *signs)
Definition: OxCalculatorT1WithSignCheck.hxx:113
MeasureType calculateR2AbsFromModel(int nSamples, const MeasureType *invTimes, const MeasureType *signal, const MeasureType *parameters)
Definition: OxCalculatorT1WithSignCheck.hxx:263
Definition: OxCalculator.h:19
MeasureType calculateR2FromModel(int nSamples, const MeasureType *invTimes, const MeasureType *signal, const MeasureType *parameters)
Definition: OxCalculatorT1WithSignCheck.hxx:246
bool getDoCalculateSDMap() const
Definition: OxCalculatorT1WithSignCheck.hxx:297
const MeasureType * getInvTimes() const
Definition: OxCalculatorT1WithSignCheck.hxx:289