36 namespace algorithms {
41 if(!(fin >> (*
_coeffs)(0,0)))
throw std::runtime_error(
"reading constant");
46 int oldPrec = fout.precision(6);
47 std::ios_base::fmtflags oldf =
48 fout.setf(std::ios_base::scientific,std::ios_base::floatfield);
49 fout <<
"C " << (*_coeffs)(0,0) << std::endl;
50 if (!fout)
throw std::runtime_error(
"writing (constant) function");
51 fout.precision(oldPrec);
59 (*_coeffs)(0,0) += (*crhs->
_coeffs)(0,0);
72 int maxOrder = std::max(xo,yo);
73 for(
int m=0;
m<=maxOrder;++
m) {
74 int i0 = std::min(xo,
m);
75 int len = std::min(yo,i0)+1;
78 tmv::ConstVectorView<double> subf = fVect.subVector(k,k+len);
81 for(
int i=0;i<len;++i)
82 (*
_coeffs)(i0-i,
m-i0+i) = fVect(k+i);
87 Assert(k==(
int)fVect.size());
102 if (!(fin >> xo >> yo >>
_scale))
103 throw std::runtime_error(
"reading xorder,yorder,scale");
108 int maxOrder = std::max(xo,yo);
109 for(
int m=0;
m<=maxOrder;++
m) {
110 int i0 = std::min(xo,
m);
111 int len = std::min(yo,i0)+1;
114 for(
int i=0;i<len;++i) fin >> coeffDiag(i);
116 for(
int i=0;i<len;++i) fin >> (*_coeffs)(i0-i,
m-i0+i);
119 if (!fin)
throw std::runtime_error(
"reading (polynomial)");
124 int oldPrec = fout.precision(6);
125 std::ios_base::fmtflags oldf =
126 fout.setf(std::ios_base::scientific,std::ios_base::floatfield);
129 fout <<
"C " << (*_coeffs)(0,0) << std::endl;
132 for(
int m=0;
m<=maxOrder;++
m) {
134 int len = std::min(
_yOrder,i0)+1;
137 for(
int i=0;i<len;++i) fout << coeffDiag(i) <<
' ';
139 for(
int i=0;i<len;++i) fout << (*
_coeffs)(i0-i,
m-i0+i);
144 if (!fout)
throw std::runtime_error(
"writing (polynomial) function");
146 fout.precision(oldPrec);
151 (*_coeffs)(0,0) += a;
152 (*_coeffs)(1,0) += b*
_scale;
153 (*_coeffs)(0,1) += c*
_scale;
157 double a,
double b,
double c,
double d,
double e,
double f)
165 std::vector<double> scaleToThe(maxOrder+1);
166 scaleToThe[0] = 1.0; scaleToThe[1] =
_scale;
167 for(
int i=2;i<=maxOrder;++i) scaleToThe[i] = scaleToThe[i-1]*
_scale;
168 std::vector<double> aToThe(maxOrder+1);
169 std::vector<double> bToThe(maxOrder+1);
170 std::vector<double> cToThe(maxOrder+1);
171 std::vector<double> dToThe(maxOrder+1);
172 std::vector<double> eToThe(maxOrder+1);
173 std::vector<double> fToThe(maxOrder+1);
174 aToThe[0] = 1.; aToThe[1] = a;
175 bToThe[0] = 1.; bToThe[1] =
b;
176 cToThe[0] = 1.; cToThe[1] = c;
177 dToThe[0] = 1.; dToThe[1] = d;
178 eToThe[0] = 1.; eToThe[1] = e;
179 fToThe[0] = 1.; fToThe[1] = f;
180 for(
int i=2;i<=maxOrder;++i) aToThe[i] = aToThe[i-1]*a;
181 for(
int i=2;i<=maxOrder;++i) bToThe[i] = bToThe[i-1]*b;
182 for(
int i=2;i<=maxOrder;++i) cToThe[i] = cToThe[i-1]*c;
183 for(
int i=2;i<=maxOrder;++i) dToThe[i] = dToThe[i-1]*d;
184 for(
int i=2;i<=maxOrder;++i) eToThe[i] = eToThe[i-1]*e;
185 for(
int i=2;i<=maxOrder;++i) fToThe[i] = fToThe[i-1]*f;
190 for(
int n=1;n<=maxOrder;++n) {
193 for(
int m=1;
m<n;++
m) {
198 std::auto_ptr<DMatrix> oldCoeffs =
_coeffs;
201 for(
int i=0;i<=
_xOrder;++i)
for(
int j=0;j<=
_yOrder&&i+j<=maxOrder;++j) {
202 for(
int k=0;k<=i;++k)
for(
int l=0;l<=k;++l) {
203 for(
int m=0;
m<=j;++
m)
for(
int n=0;n<=
m;++n) {
204 (*_coeffs)(k-l+
m-n,l+n) +=
206 aToThe[i-k]*bToThe[k-l]*cToThe[l]*
207 dToThe[j-
m]*eToThe[
m-n]*fToThe[n]*
208 (*oldCoeffs)(i,j)/scaleToThe[i+j-k-
m];
224 std::auto_ptr<DMatrix > newCoeffs(
225 new DMatrix(newXOrder+1,newYOrder+1));
226 newCoeffs->setZero();
263 return std::auto_ptr<Function2D>(
new Constant2D());
266 return std::auto_ptr<Function2D>(
273 std::auto_ptr<Polynomial2D> temp(
276 int maxOrder = std::max(newXOrder,newYOrder);
277 for(
int i=newXOrder;i>=0;--i) {
278 for(
int j=std::min(maxOrder-i,newYOrder);j>=0;--j) {
282 (*temp->_coeffs)(i,j) = (*_coeffs)(i+1,j)*(i+1.)/
_scale;
285 return std::auto_ptr<Function2D>(temp);
291 return std::auto_ptr<Function2D>(
new Constant2D());
294 return std::auto_ptr<Function2D>(
301 std::auto_ptr<Polynomial2D> temp(
304 int maxOrder = std::max(newXOrder,newYOrder);
305 for(
int i=newXOrder;i>=0;--i)
306 for(
int j=std::min(maxOrder-i,newYOrder);j>=0;--j) {
310 (*temp->_coeffs)(i,j) = (*_coeffs)(i,j+1)*(j+1.)/
_scale;
312 return std::auto_ptr<Function2D>(temp);
317 std::auto_ptr<Function2D> temp =
copy();
335 if (tc !=
'D' && tc !=
'C') fin.putback(tc);
336 std::auto_ptr<Function2D> ret;
347 case 'X' : ret.reset(
new Cheby2D(fin));
350 default:
throw std::runtime_error(
"invalid type");
356 double a,
double b,
double c,
359 if(dynamic_cast<Constant2D*>(
this)) {
360 Assert(dynamic_cast<const Constant2D*>(&f));
361 Assert(dynamic_cast<const Constant2D*>(&g));
363 if(dynamic_cast<Polynomial2D*>(
this)) {
364 Assert(dynamic_cast<const Polynomial2D*>(&f));
365 Assert(dynamic_cast<const Polynomial2D*>(&g));
368 if(dynamic_cast<Legendre2D*>(
this)) {
369 Assert(dynamic_cast<const Legendre2D*>(&f));
370 Assert(dynamic_cast<const Legendre2D*>(&g));
371 Assert(dynamic_cast<const Legendre2D*>(&f)->getBounds() ==
372 dynamic_cast<const Legendre2D*>(&g)->getBounds());
376 if(dynamic_cast<Cheby2D*>(
this)) {
377 Assert(dynamic_cast<const Cheby2D*>(&f));
378 Assert(dynamic_cast<const Cheby2D*>(&g));
379 Assert(dynamic_cast<const Cheby2D*>(&f)->getBounds() ==
380 dynamic_cast<const Cheby2D*>(&g)->getBounds());
397 inline int fitSize(
const int xOrder,
const int yOrder)
399 int lowOrder = std::min(xOrder,yOrder);
400 int highOrder = std::max(xOrder,yOrder);
401 return (lowOrder+1)*(lowOrder+2)/2 + (lowOrder+1)*(highOrder-lowOrder);
405 int xOrder,
int yOrder,
406 const std::vector<Position>& pos,
const std::vector<double>& vals,
407 const std::vector<bool>& shouldUse,
DVector *f,
408 const std::vector<double>* sigList,
430 Assert(pos.size() == vals.size());
431 Assert(shouldUse.size() == vals.size());
432 Assert((sigList==0) || (sigList->size() == vals.size()));
433 xdbg<<
"Start SimpleFit: size = "<<pos.size()<<std::endl;
434 xdbg<<
"order = "<<xOrder<<
','<<yOrder<<std::endl;
436 int highOrder = std::max(xOrder,yOrder);
437 int size =
fitSize(xOrder,yOrder);
438 xdbg<<
"size = "<<size<<std::endl;
440 const int nVals = vals.size();
442 Assert(
int(f->size()) == size);
443 Assert(!diff ||
int(diff->size()) == nVals);
445 (
int(cov->TMV_colsize()) == size &&
int(cov->TMV_rowsize()) == size));
447 int nUse = std::count(shouldUse.begin(),shouldUse.end(),
true);
448 xdbg<<
"nuse = "<<nUse<<std::endl;
455 for(
int i=0;i<nVals;++i)
if (shouldUse[i]) {
457 Assert((*sigList)[i] > 0.);
458 V(ii) = vals[i]/(*sigList)[i];
466 for(
int pplusq=0;pplusq<=highOrder;++pplusq) {
467 for(
int p=std::min(pplusq,xOrder),q=pplusq-p;
468 q<=std::min(pplusq,yOrder);--p,++q,++pq) {
471 Assert(pq<
int(P.TMV_rowsize()));
472 P(ii,pq) = px[p]*py[q];
475 Assert(pq ==
int(P.TMV_rowsize()));
476 if (sigList) P.row(ii) /= (*sigList)[i];
481 xdbg<<
"Done make V,P\n";
492 for(
int i=0;i<nVals;++i) {
503 *dof = P.TMV_colsize() - P.TMV_rowsize();
504 if (*dof < 0) *dof = 0;
510 xdbg<<
"Done simple fit\n";
514 int order,
const std::vector<Position>& pos,
515 const std::vector<double>& vals,
const std::vector<bool>& shouldUse,
516 const std::vector<double>* sig,
517 double *chisqOut,
int *dofOut,
DMatrix* cov)
522 doSimpleFit(order,order,pos,vals,shouldUse,&fVect,sig,dofOut,&diff,cov);
523 *chisqOut = diff.TMV_normSq();
525 doSimpleFit(order,order,pos,vals,shouldUse,&fVect,sig);
530 inline double absSq(
const double&
x) {
return x*
x; }
535 int order,
double nSig,
536 const std::vector<Position>& pos,
const std::vector<double>& vals,
537 std::vector<bool> *shouldUse,
538 const std::vector<double>* sig,
double *chisqOut,
int *dofOut,
541 xdbg<<
"start outlier fit\n";
542 const int nVals = vals.size();
547 double nSigSq = nSig*nSig;
550 xdbg<<
"before dosimple\n";
551 doSimpleFit(order,order,pos,vals,*shouldUse,&fVect,sig,&dof,&diff,cov);
552 xdbg<<
"after dosimple\n";
555 chisq = diff.TMV_normSq();
563 double thresh=nSigSq*chisq/dof;
564 xdbg<<
"chisq = "<<chisq<<
", thresh = "<<thresh<<std::endl;
565 for(
int i=0;i<nVals;++i)
if( (*shouldUse)[i]) {
566 xdbg<<
"pos ="<<pos[i]<<
", v = "<<vals[i]<<
567 " diff = "<<diff[i]<<std::endl;
568 if (
absSq(diff[i]) > thresh) {
570 (*shouldUse)[i] =
false;
574 if (!isDone)
xdbg<<
" are outliers\n";
577 if (chisqOut) *chisqOut =
chisq;
578 if (dofOut) *dofOut = dof;
579 xdbg<<
"done outlier fit\n";
582 inline double betai(
double a,
double b,
double x);
584 inline bool Equivalent(
double chisq1,
double chisq2,
int n1,
int n2,
587 if (chisq2 <= chisq1)
return true;
589 if (chisq1 <= 0.)
return (chisq2 <= 0.);
592 if (n1 <= 0)
return (n2 <= 0);
593 double f = (chisq2-chisq1)/(n2-n1) / (chisq1/n1);
595 double prob =
betai(0.5*n2,0.5*n1,n2/(n2+n1*f));
599 return (prob > 1.-equivProb);
603 int maxOrder,
double equivProb,
604 const std::vector<Position>& pos,
const std::vector<double>& vals,
605 const std::vector<bool>& shouldUse,
const std::vector<double>* sig,
606 double *chisqOut,
int *dofOut,
DMatrix* cov)
608 xdbg<<
"Start OrderFit\n";
613 &fVectMax,sig,&dofmax,&diff,cov);
614 double chisqmax = diff.TMV_normSq();
615 xdbg<<
"chisq,dof(n="<<maxOrder<<
") = "<<chisqmax<<
','<<dofmax<<std::endl;
619 std::auto_ptr<DVector > fVect(0);
620 for(tryOrder=0;tryOrder<maxOrder;++tryOrder) {
623 fVect.get(),sig,&dof,&diff,cov);
624 chisq = diff.TMV_normSq();
625 xdbg<<
"chisq,dof(n="<<tryOrder<<
") = "<<chisq<<
','<<dof<<
".... ";
626 if (
Equivalent(chisqmax,chisq,dofmax,dof,equivProb)) {
632 if (tryOrder == maxOrder) {
634 if(chisqOut) *chisqOut = chisqmax;
635 if(dofOut) *dofOut = dofmax;
639 if(chisqOut) *chisqOut =
chisq;
640 if(dofOut) *dofOut = dof;
648 #define FPMIN 1.0e-30
656 double d = 1.0 - qab*x/qap;
663 double aa = m*(b-
m)*x/((qam+m2)*(a+m2));
670 aa = -(a+
m)*(qab+m)*x/((a+m2)*(qap+m2));
678 if (std::abs(del-1.0) <
EPS)
break;
681 throw std::runtime_error(
682 "a or b too big in betacf, or MAXIT too small");
693 const double cof[6]={76.18009172947146,-86.50532032941677,
694 24.01409824083091,-1.231739572450155,0.1208650973866179e-2,
695 -0.5395239384953e-5};
697 temp -= (x+0.5)*
log(temp);
698 double ser = 1.000000000190015;
700 for(
int j=0;j<6;++j) ser += cof[j]/(y+=1.0);
701 return -temp+
log(2.5066282746310005*ser/x);
704 inline double betai(
double a,
double b,
double x)
706 if (x<0.0 || x>1.0)
throw std::runtime_error(
"Bad x in betai");
707 if (x==0.0)
return 0.;
708 if (x==1.0)
return 1.;
710 if (x < (a+1.0)/(a+b+2.0))
return bt*
betacf(a,b,x)/a;
711 else return 1.0-bt*
betacf(b,a,1.0-x)/
b;
Eigen::Block< DVector, Eigen::Dynamic, 1 > DVectorView
virtual DVector definePY(int order, double y) const =0
virtual DVector definePX(int order, double x) const =0
#define TMV_conjugateSelf(m)
virtual std::auto_ptr< Function2D > conj() const
#define TMV_QR_Solve(m, x, b)
std::auto_ptr< DMatrix > _coeffs
#define EIGEN_ToScalar(m)
virtual void setFunction(int _xOrder, int _yOrder, const DVector &fVect)=0
double betacf(double a, double b, double x)
const DMatrix & getCoeffs() const
virtual void outlierFit(int order, double nsig, const std::vector< Position > &pos, const std::vector< double > &v, std::vector< bool > *shouldUse, const std::vector< double > *sigList=0, double *chisqout=0, int *dofout=0, DMatrix *cov=0)
virtual void write(std::ostream &fout) const
virtual void linearPreTransform(double a, double b, double c, double d, double e, double f)
int fitSize(const int xOrder, const int yOrder)
virtual std::auto_ptr< Function2D > dFdY() const
double betai(double a, double b, double x)
virtual void operator+=(const Function2D &rhs)
virtual void write(std::ostream &fout) const
virtual std::auto_ptr< Function2D > dFdX() const
virtual void addLinear(double a, double b, double c)
#define TMV_QR_InverseATA(m, cov)
void makeProductOf(const Polynomial2D &f, const Polynomial2D &g)
virtual void linearTransform(double a, double b, double c, const Function2D &f, const Function2D &g)
double binom(int i, int j)
virtual double operator()(double x, double y) const
afw::table::Key< double > b
virtual void simpleFit(int order, const std::vector< Position > &pos, const std::vector< double > &v, const std::vector< bool > &shouldUse, const std::vector< double > *sigList=0, double *chisqOut=0, int *dofOut=0, DMatrix *cov=0)
virtual void setFunction(int xOrder, int yOrder, const DVector &fVect)
void doSimpleFit(int xOrder, int yOrder, const std::vector< Position > &pos, const std::vector< double > &v, const std::vector< bool > &shouldUse, DVector *f, const std::vector< double > *sigList=0, int *dof=0, DVector *diff=0, DMatrix *cov=0)
Polynomial2D(double scale=1.)
virtual std::auto_ptr< Function2D > copy() const =0
double absSq(const double &x)
virtual void operator+=(const Function2D &rhs)
#define EIGEN_Transpose(m)
static std::auto_ptr< Function2D > read(std::istream &fin)
virtual void orderFit(int maxOrder, double equivProb, const std::vector< Position > &pos, const std::vector< double > &v, const std::vector< bool > &shouldUse, const std::vector< double > *sigList=0, double *chisqout=0, int *dofout=0, DMatrix *cov=0)
bool Equivalent(double chisq1, double chisq2, int n1, int n2, double equivProb)