Isis 3 Programmer Reference
ZeroBufferFit.cpp
Go to the documentation of this file.
1 
24 #include <cmath>
25 #include <string>
26 #include <vector>
27 #include <numeric>
28 #include <iostream>
29 #include <sstream>
30 
31 #include "ZeroBufferFit.h"
32 #include "IString.h"
33 #include "HiCalTypes.h"
34 #include "HiCalUtil.h"
35 #include "HiCalConf.h"
36 #include "LeastSquares.h"
37 #include "LowPassFilter.h"
38 #include "MultivariateStatistics.h"
39 #include "IException.h"
40 
41 using namespace std;
42 
43 namespace Isis {
44 
53  ZeroBufferFit::ZeroBufferFit(const HiCalConf &conf) :
54  NonLinearLSQ(), Module("ZeroBufferFit") {
55  DbProfile prof = conf.getMatrixProfile();
56  _history.add("Profile["+ prof.Name()+"]");
57  _timet.setBin(ToInteger(prof("Summing")));
58  _timet.setLineTime(ToDouble(prof("ScanExposureDuration")));
59 
60  _skipFit = IsEqual(ConfKey(prof, "ZeroBufferFitSkipFit", QString("TRUE")), "TRUE");
61  _useLinFit = IsTrueValue(prof, "ZeroBufferFitOnFailUseLinear");
62 
63 
64  _absErr = toDouble(ConfKey(prof, "AbsoluteError", QString("1.0E-4")));
65  _relErr = toDouble(ConfKey(prof, "RelativeError", QString("1.0E-4")));
66 
67  _sWidth = toInt(ConfKey(prof, "GuessFilterWidth", QString("17")));
68  _sIters = toInt(ConfKey(prof, "GuessFilterIterations", QString("1")));
69 
70  if ( prof.exists("MaximumIterations") ) {
71  setMaxIters(ToInteger(prof("MaximumIterations")));
72  }
73 
74  _maxLog = toDouble(ConfKey(prof, "MaximumLog", QString("709.0")));
75  _badLines = ToInteger(prof("TrimLines"))/ToInteger(prof("Summing"));
76  _minLines = toInt(ConfKey(prof,"ZeroBufferFitMinimumLines", QString("100")));
77 
78 
79  QString histstr = "ZeroBufferFit(AbsErr[" + ToString(_absErr) +
80  "],RelErr[" + ToString(_relErr) +
81  "],MaxIter[" + ToString(maxIters()) + "])";
82  _history.add(histstr);
83 
84  }
85 
107  ostringstream hist;
108  _data = d;
109  if ( _skipFit || (!gotGoodLines(d))) {
110  _b2 = _data;
111  _coefs = HiVector(4, 0.0);
112  _uncert = _coefs;
113  _cc = HiVector(2, 0.0);
114  _chisq = 0.0;
115  if ( !gotGoodLines(d) ) {
116  hist << "NotEnoughLines(GoodLines[" << goodLines(d)
117  << "],MinimumLines[" << _minLines << "]);";
118  }
119 
120  hist << "SkipFit(TRUE: Not using LMFit)";
121  _history.add(hist.str().c_str());
122  }
123  else {
124  hist << "Fit(";
125  _b2 = HiVector(goodLines(_data));
126  if ( success(curvefit()) ) {
127  _coefs = coefs();
128  _uncert = uncert();
129  hist << "Solved,#Iters[" << nIterations() << "],ChiSq[" << Chisq()
130  << "],DoF[" << DoF() << "])";
131  _history.add(hist.str().c_str());
132  _history.add("a0("+ToString(_coefs[0])+"+-"+ToString(_uncert[0])+")");
133  _history.add("a1("+ToString(_coefs[1])+"+-"+ToString(_uncert[1])+")");
134  _history.add("a2("+ToString(_coefs[2])+"+-"+ToString(_uncert[2])+")");
135  _history.add("a3("+ToString(_coefs[3])+"+-"+ToString(_uncert[3])+")");
136  }
137  else {
138  // Punt, fit a straight line to the data
139  _cc = poly_fit(d);
140  HiVector a(4);
141  a[0] = _cc[0];
142  a[1] = _cc[1];
143  a[2] = 0.0;
144  a[3] = 0.0;
145  _coefs = a;
146 
147  hist << "Failed::Reason("<< statusstr() << "),#Iters["
148  << nIterations() << "])";
149  _history.add(hist.str().c_str());
150  _history.add("a0("+ToString(_coefs[0])+")");
151  _history.add("a1("+ToString(_coefs[1])+")");
152  _history.add("a2("+ToString(_coefs[2])+")");
153  _history.add("a3("+ToString(_coefs[3])+")");
154  if ( _useLinFit ) {
155  _history.add("OnFailureUse(LinearFit(Zf))");
156  }
157  else {
158  _skipFit = true;
159  _history.add("OnFailureUse(ZfBuffer)");
160  }
161  }
162  }
163  return (Yfit());
164  }
165 
177  NonLinearLSQ::NLVector ZeroBufferFit::guess() {
178  int n = _data.dim();
179  int nb = n - _badLines;
180 
181  HiVector b1 = _data.subarray(0, nb-1);
182  LowPassFilter gfilter(b1, _history, _sWidth, _sIters);
183 
184  int nb2 = nb/2;
185  _b2 = gfilter.ref();
186  HiVector cc = poly_fit(_b2.subarray(nb2,_b2.dim()-1), nb2-1);
187 
188  // Compute the 3rd term guess by getting the average of the residual
189  // at both ends of the data set.
190  Statistics s;
191 
192  // Get the head of the data set
193  int n0 = MIN(nb, 20);
194  for ( int k = 0 ; k < n0 ; k++ ) {
195  double d = _b2[k] - (cc[0] + cc[1] * _timet(k));
196  s.AddData(&d, 1);
197  }
198  double head = s.Average();
199 
200  // Get the tail of the data set
201  s.Reset();
202  n0 = (int) (0.9 * nb);
203  for ( int l = n0 ; l < nb ; l++ ) {
204  double d = _b2[l] - (cc[0] + cc[1] * _timet(l));
205  s.AddData(&d, 1);
206  }
207  double tail = s.Average();
208 
209  // Populate the guess with the results
210  NLVector g(4, 0.0);
211  g[0] = cc[0];
212  g[1] = cc[1];
213  g[2] = head-tail;
214  g[3] = -5.0/_timet(nb-1);
215  _guess = g;
216  _history.add("Guess["+ToString(_guess[0])+ ","+
217  ToString(_guess[1])+ ","+
218  ToString(_guess[2])+ ","+
219  ToString(_guess[3])+ "]");
220  return (g);
221  }
222 
234  int ZeroBufferFit::checkIteration(const int Iter, const NLVector &fitcoefs,
235  const NLVector &uncerts, double cplxconj,
236  int Istatus) {
237  _chisq = pow(cplxconj, 2.0);
238  return (Istatus);
239  }
240 
242  NonLinearLSQ::NLVector ZeroBufferFit::f_x(const NLVector &a) {
243  double a0 = a[0];
244  double a1 = a[1];
245  double a2 = a[2];
246  double a3 = a[3];
247 
248  int n = _b2.dim();
249  NLVector f(n);
250  for (int i = 0 ; i < n ; i++) {
251  double lt = _timet(i);
252  double et = a3 * lt;
253  double Yi = a0 + (a1 * lt) + a2 * exp(MIN(et,_maxLog));
254  f[i] = (Yi - _b2[i]);
255  }
256  return (f);
257  }
258 
260  NonLinearLSQ::NLMatrix ZeroBufferFit::df_x(const NLVector &a) {
261  // double a0 = a[0];
262  // double a1 = a[1];
263  double a2 = a[2];
264  double a3 = a[3];
265 
266  int n = _b2.dim();
267  NLMatrix J(n, 4);
268  for (int i = 0; i < n; i++) {
269  double lt = _timet(i);
270  double et = a3 * lt;
271  double p0 = exp (MIN(et,_maxLog));
272  J[i][0] = 1.0;
273  J[i][1] = lt;
274  J[i][2] = p0;
275  J[i][3] = a2 * lt * p0;
276  }
277  return (J);
278  }
279 
282  if ( _skipFit || (!gotGoodLines(_data))) {
283  return (_data.copy());
284  }
285  else {
286  HiVector dcorr(_data.dim());
287  HiVector a = _coefs;
288  for ( int i = 0 ; i < dcorr.dim() ; i++ ) {
289  double lt = _timet(i);
290  dcorr[i] = a[0] + (a[1] * lt) + a[2] * exp(a[3] * lt);
291  }
292  return (dcorr);
293  }
294  }
295 
298 
299  HiVector vNorm(v.dim());
300  double v0 = v[0];
301  for ( int i = 0 ; i < v.dim() ; i++ ) {
302  vNorm[i] = v[i] - v0;
303  }
304  _history.add("Normalize[" + ToString(v0) + "]");
305  return (vNorm);
306  }
307 
320  HiVector ZeroBufferFit::poly_fit(const HiVector &d, const double line0) const {
321  // Needs a linear fit to latter half of data
323  int n = d.dim();
324  for ( int i = 0 ; i < n ; i++ ) {
325  double t = _timet(line0+i);
326  fit.AddData(&t, &d[i], 1);
327  }
328  NLVector cc(2);
329  fit.LinearRegression(cc[0], cc[1]);
330  return (cc);
331  }
332 
334  void ZeroBufferFit::printOn(std::ostream &o) const {
335  o << "# History = " << _history << endl;
336  // Write out the header
337  o << setw(_fmtWidth) << "Line"
338  << setw(_fmtWidth+1) << "Time"
339  << setw(_fmtWidth+1) << "Data"
340  << setw(_fmtWidth+1) << "Fit\n";
341 
342  HiVector fit = Yfit();
343  for (int i = 0 ; i < _data.dim() ; i++) {
344  o << formatDbl(i) << " "
345  << formatDbl(_timet(i)) << " "
346  << formatDbl(_data[i]) << " "
347  << formatDbl(fit[i]) << endl;
348  }
349  return;
350  }
351 
352 } // namespace Isis
353 
354 
const HiVector & ref() const
Return data via a const reference.
Definition: Module.h:126
HiVector Yfit() const
Computes the solution vector using current coefficents.
int _fmtWidth
Default field with of double.
Definition: Module.h:168
void LinearRegression(double &a, double &b) const
Fits a line through the data.
int maxIters() const
Maximum number iterations for valid solution.
Definition: NonLinearLSQ.h:85
int nIterations() const
Return number of iterations from last fit processing.
Definition: NonLinearLSQ.h:122
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:108
Namespace for the standard library.
HiVector poly_fit(const HiVector &d, const double line0=0.0) const
Compute a polyonomial fit using multivariate statistics.
bool exists(const QString &key) const
Checks for the existance of a keyword.
Definition: DbProfile.h:129
HiHistory _history
Hierarchial component history.
Definition: Module.h:167
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
int DoF() const
Returns the Degrees of Freedom.
NonLinearLSQ Computes a fit using a Levenberg-Marquardt algorithm.
Definition: NonLinearLSQ.h:57
A DbProfile is a container for access parameters to a database.
Definition: DbProfile.h:65
std::string statusstr() const
Return error message pertaining to last fit procesing.
Definition: NonLinearLSQ.h:102
HiVector Normalize(const HiVector &v)
Compute normalized solution vector from result.
NLVector uncert() const
Return uncertainties from last fit processing.
Definition: NonLinearLSQ.h:120
bool IsEqual(const QString &v1, const QString &v2="TRUE")
Shortened string equality test.
Definition: HiCalUtil.h:272
QString formatDbl(const double &value) const
Properly format values that could be special pixels.
Definition: Module.h:184
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:107
int checkIteration(const int Iter, const NLVector &fitcoefs, const NLVector &uncerts, double cplxconj, int Istatus)
Computes the interation check for convergence.
int ToInteger(const T &value)
Helper function to convert values to Integers.
Definition: HiCalUtil.h:236
virtual void printOn(std::ostream &o) const
Provides virtualized dump of data from this module.
bool IsTrueValue(const DbProfile &prof, const QString &key, const QString &value="TRUE")
Determines if the keyword value is the expected value.
Definition: HiCalUtil.h:290
Container of multivariate statistics.
void Reset()
Reset all accumulators and counters to zero.
Definition: Statistics.cpp:126
Compute a low pass filter from a Module class content.
Definition: LowPassFilter.h:45
Module manages HiRISE calibration vectors from various sources.
Definition: Module.h:54
double Chisq() const
Returns the Chi-Square value of the fit solution.
bool gotGoodLines(const HiVector &d) const
Determines if the vector contains any valid lines.
double ToDouble(const T &value)
Helper function to convert values to doubles.
Definition: HiCalUtil.h:248
NLMatrix df_x(const NLVector &a)
Computes the first derivative of the function at the current iteration.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
void AddData(const double *x, const double *y, const unsigned int count)
Add two arrays of doubles to the accumulators and counters.
T ConfKey(const DbProfile &conf, const QString &keyname, const T &defval, int index=0)
Find a keyword in a profile using default for non-existant keywords.
Definition: HiCalUtil.h:219
QString Name() const
Returns the name of this property.
Definition: DbProfile.h:118
bool success() const
Determine success from last fit processing.
Definition: NonLinearLSQ.h:98
int goodLines(const HiVector &d) const
Returns the number of good lines in the image.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:154
NLVector f_x(const NLVector &a)
Computes the function value at the current iteration.
NLVector guess()
Compute the initial guess of the fit.
QString ToString(const T &value)
Helper function to convert values to strings.
Definition: HiCalUtil.h:260
double Average() const
Computes and returns the average.
Definition: Statistics.cpp:313
NLVector coefs() const
Return coefficients from last fit processing.
Definition: NonLinearLSQ.h:118
HiVector Solve(const HiVector &d)
Compute non-linear fit to (typically) ZeroBufferSmooth module.
T MIN(const T &A, const T &B)
Implement templatized MIN fumnction.
TNT::Array1D< double > HiVector
1-D Buffer
Definition: HiCalTypes.h:40
void setMaxIters(int m)
Sets the maximum number of iterations.
Definition: NonLinearLSQ.h:77