From 18e449fe2b8d5b3a2507664917675e07394b73e8 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Tue, 16 Dec 2014 10:42:02 +0100 Subject: [PATCH] Replace fit "Quality" by explicit outcome, chi2, R2. --- TODO | 2 ++ pub/lib/fit.cpp | 26 +++++++------------------- pub/lib/integrate.cpp | 14 +++++++------- pub/lib/node.cpp | 26 +++++++++++++++----------- pub/lib/var.cpp | 15 ++++++++++----- pub/lib/var.hpp | 5 +++-- pub/lib/xax_lex.lpp | 2 +- pub/lib/zentry.cpp | 12 +++++++----- pub/lib/zentry.hpp | 5 +++-- 9 files changed, 55 insertions(+), 52 deletions(-) diff --git a/TODO b/TODO index 9acf54b3..7dfa3ad1 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,8 @@ cq0/q0 etc -> more explicit names throughout (cp,oi,..); get rid of ci (geni 'integrate') automatic mfj after oi +update infoLine header + shibang mechanism to invoke Frida scripts cp should show quality of last fit latest action on pX should be part of history diff --git a/pub/lib/fit.cpp b/pub/lib/fit.cpp index fdffb062..f1d4e498 100644 --- a/pub/lib/fit.cpp +++ b/pub/lib/fit.cpp @@ -32,7 +32,6 @@ namespace NCurveFit { double Factor=100.; int nCall=200; int verbosity=0; - int mFitMetric=2; double maxtime = 3; } @@ -42,8 +41,8 @@ void NCurveFit::setFitTuningPars( string which ) { if ( which=="?" ) printf( "Fit setup:\n nCall=%d\n Verbosity=%d\n Factor=%g\n" - " Eps=%g\n Metric=%i\n", - nCall, verbosity, Factor, Epsilon, mFitMetric ); + " Eps=%g\n", + nCall, verbosity, Factor, Epsilon ); else if ( which=="v" ) verbosity = iask( "Verbosity", verbosity ); else if ( which=="c" ) @@ -52,17 +51,7 @@ void NCurveFit::setFitTuningPars( string which ) Factor = dask( "NTuneFit::Factor", Factor ); else if ( which=="e" ) Epsilon = dask( "NTuneFit::Epsilon", Epsilon ); - else if ( which=="m" ){ - // metric (0) is the integer indicator returned by lmmin; - // it cannot be chosen here - cout << "Fit metric:\n" - "(1) R^2 (coefficient of determination, for linear regression)\n" - "(2) chi^2 (mean deviation, with weights as in fit)\n"; - int ret = iask( "Option", mFitMetric ); - if( ret<1 || ret>CCurve::mQuality ) - throw "invalid option"; - mFitMetric = ret; - } else if ( which=="t" ) + else if ( which=="t" ) maxtime = dask( "Max duration of fits (in s)", maxtime ); } @@ -267,7 +256,7 @@ void NCurveFit::fit( bool _allow_slow_conv ) // Fit quality metrics Q: // Q: status code - C->Quality[0] = (double) status.outcome; + C->fitOutcome = (double) status.outcome; // Q: coefficient of determination R^2 (for linear regression) double ysum1 = 0, ysum2 = 0; @@ -276,12 +265,12 @@ void NCurveFit::fit( bool _allow_slow_conv ) ysum2 += SQR( D->y[i] ); } double ydev2 = ysum2 - SQR( ysum1 )/nd; // = nd * <(y-<y>)^2> - C->Quality[1] = ydev2!=0 ? 1 - SQR(status.fnorm) / ydev2 : -1; + C->fitR2 = ydev2!=0 ? 1 - SQR(status.fnorm) / ydev2 : -1; // Q: mean deviation (chi^2 if fvec is weighed with 1/dy) int nfreedom = nd - npfree - 1; if( nfreedom<1 ) nfreedom = 1; - C->Quality[2] = SQR(status.fnorm) / nfreedom; + C->fitChi2 = SQR(status.fnorm) / nfreedom; { // print results: @@ -291,7 +280,7 @@ void NCurveFit::fit( bool _allow_slow_conv ) for ( int i=0; i<npfree; i++ ) printf(" %12g", Par[i]); printf( " (%3d->%9.7g)", - status.nfev, C->Quality[mFitMetric] ); + status.nfev, C->fitChi2 ); printf( "%s\n", lm_shortmsg[ status.outcome ] ); } } catch (...) { @@ -301,4 +290,3 @@ void NCurveFit::fit( bool _allow_slow_conv ) } // j } // k } - diff --git a/pub/lib/integrate.cpp b/pub/lib/integrate.cpp index 2c874985..74945c86 100644 --- a/pub/lib/integrate.cpp +++ b/pub/lib/integrate.cpp @@ -92,7 +92,7 @@ void NCurveIntegral::integrate() if( NRead::stack_empty() ) cout << "Generate integral file:\n" " 0 | 1 | ... extract curve parameters\n" - " q0 | q1 | q2 extract fit metrics\n" + " res | chi2 | R2 extract fit metrics\n" " i numeric integral\n" " s integral as sum over data file grid\n" " <list> comma-separated list thereof\n" @@ -191,12 +191,12 @@ void NCurveIntegral::integrate() double val; if ( mode=="p" ) val = fin->VC(j)->P[ip]; - else if ( mode=="q0" ) - val = fin->VC(j)->Quality[0]; - else if ( mode=="q1" ) - val = fin->VC(j)->Quality[1]; - else if ( mode=="q2" ) - val = fin->VC(j)->Quality[2]; + else if ( mode=="res" ) + val = fin->VC(j)->fitOutcome; + else if ( mode=="chi2" ) + val = fin->VC(j)->fitChi2; + else if ( mode=="R2" ) + val = fin->VC(j)->fitR2; else if ( mode=="i" ) val = NumericIntegral( fin, fiter.k(), j, numint_bound_low, numint_bound_hig ); diff --git a/pub/lib/node.cpp b/pub/lib/node.cpp index 57315f89..fb461ec7 100644 --- a/pub/lib/node.cpp +++ b/pub/lib/node.cpp @@ -520,23 +520,22 @@ void CNodeIva::tree_val( CResult& ret, const CContext& ctx ) const // References for curve file: POlc fc = P2C( f ); if ( fc ) { + if ( ref->ti ) + throw string("unexpected i dependence of curve property"); int j = ref->get_j( ctx, f->nJ() ); PCurve cj = fc->VC(j); if ( var->typ == CVar::_CP ) { - if ( ref->ti ) - throw string("P does not require 3 indices"); if ( var->num>= fc->nP ) throw string("invalid p ref(") + var->var_info() + ") in curve file"; ret.set_r( cj->P[var->num] ); - } else if ( var->typ == CVar::_CQ ) { - if ( ref->ti ) - throw string("Q does not require 3 indices"); - if ( var->num >= CCurve::mQuality ) - throw string("invalid fm ref(") + var->var_info() + - ") in curve file"; - ret.set_r( cj->Quality[var->num] ); + } else if ( var->typ == CVar::_COUTCOME ) { + ret.set_r( cj->fitOutcome ); + } else if ( var->typ == CVar::_CCHI2 ) { + ret.set_r( cj->fitChi2 ); + } else if ( var->typ == CVar::_CR2 ) { + ret.set_r( cj->fitR2 ); } else throw string("invalid ref(") + var->var_info() + @@ -604,8 +603,13 @@ void CNodeIva::set_coord( CCoord& ret, int k_in ) const if( var->num>=fc->nP ) throw "invalid reference p" + S(var->num); ret = fc->PCo[var->num]; - } else if ( var->typ == CVar::_CQ ) - ret = CCoord("cq"+S(var->num), ""); // fit quality indicator + } + else if ( var->typ == CVar::_COUTCOME ) + ret = CCoord("fit_outcome", ""); + else if ( var->typ == CVar::_CCHI2 ) + ret = CCoord("chi2", ""); + else if ( var->typ == CVar::_CR2 ) + ret = CCoord("R2", ""); else if ( var->typ == CVar::_C ) ret = CCoord(fc->expr,""); else diff --git a/pub/lib/var.cpp b/pub/lib/var.cpp index e538f2cf..8e317d1c 100644 --- a/pub/lib/var.cpp +++ b/pub/lib/var.cpp @@ -39,10 +39,7 @@ CVar::CVar( string s ) if( s.size()<1 ) throw "Variable name missing"; - if ( s.substr(0,2)=="cq" ) { // curve quality - num = requestNum( s, 2 ); - typ = _CQ; - } else if ( s[0]=='p' ) { // curve parameter + if ( s[0]=='p' ) { // curve parameter num = requestNum( s, 1 ); typ = _CP; } else if ( s=="z+" ) { // new z value @@ -67,6 +64,12 @@ CVar::CVar( string s ) typ = _DY; } else if ( s=="c" ) { typ = _C; + } else if ( s=="outcome" ) { + typ = _COUTCOME; + } else if ( s=="chi2" ) { + typ = _CCHI2; + } else if ( s=="R2" ) { + typ = _CR2; } else if ( s=="k" ) { typ = _K; } else if ( s=="j" ) { @@ -106,7 +109,9 @@ string CVar::var_info() const case _Z: ret = "z"; break; case _R: ret = "r"; break; case _CP: ret = "p"; break; - case _CQ: ret = "cq"; break; + case _COUTCOME: ret = "fit_outcome"; break; + case _CCHI2: ret = "chi2"; break; + case _CR2: ret = "R2"; break; case _K: ret = "k"; break; case _J: ret = "j"; break; case _I: ret = "i"; break; diff --git a/pub/lib/var.hpp b/pub/lib/var.hpp index 44a54df1..b61e7d8b 100644 --- a/pub/lib/var.hpp +++ b/pub/lib/var.hpp @@ -16,7 +16,8 @@ class CVar { _NOREF=0, _X, _Y, _Z, _R, // data _DY, // associated error - _C, _CP, _CQ, // curve, curve parameters, curve quality + _C, _CP, // curve, curve parameters + _COUTCOME, _CCHI2, _CR2, // fit outcome _K, _J, _I, // indices for file, spectrum, point _NJ, _NI // number of spectra in file, points in spectrum }; @@ -31,7 +32,7 @@ class CVar { bool pointwise() const { return typ==_X || typ==_Y || typ==_DY || typ==_I; }; bool numbered() const { - return typ==_CP || typ==_CQ || typ==_Z; }; + return typ==_CP || typ==_Z; }; CVar errvar() const; diff --git a/pub/lib/xax_lex.lpp b/pub/lib/xax_lex.lpp index dbdd81b1..2085485e 100644 --- a/pub/lib/xax_lex.lpp +++ b/pub/lib/xax_lex.lpp @@ -58,7 +58,7 @@ EXP [eE]"-"?[0-9]+ xaxlval->v = PVar( new CVar(xaxtext) ); return IDX; } -[xy]|dy|n[ij]|([zpr]|cq){DIG}+ { +[xy]|dy|n[ij]|([zpr]{DIG}+)|outcome|chi2|R2 { xaxlval->v = PVar( new CVar(xaxtext) ); return REF; } diff --git a/pub/lib/zentry.cpp b/pub/lib/zentry.cpp index b3b437da..04c05885 100644 --- a/pub/lib/zentry.cpp +++ b/pub/lib/zentry.cpp @@ -275,9 +275,9 @@ void CCurve::clear(void) { P.clear(); z.clear(); - Quality[0] = -1; - Quality[1] = -1; - Quality[2] = -1; + fitOutcome = -1; + fitChi2 = 0; + fitR2 = 0; } //! Return line containing z and p values. @@ -299,9 +299,11 @@ string CCurve::infoLine() const if( ip<P.size()-1 ) out += " "; } - snprintf( wrd, LEN, "%-2li", lround(Quality[0]) ); + snprintf( wrd, LEN, "%-2i", fitOutcome ); out += wrd; - snprintf( wrd, LEN, "%-12.7g", Quality[2] ); + snprintf( wrd, LEN, "%-12.7g", fitChi2 ); + out += wrd; + snprintf( wrd, LEN, "%-12.7g", fitR2 ); out += wrd; return out; } diff --git a/pub/lib/zentry.hpp b/pub/lib/zentry.hpp index 5a343aaf..59260d53 100644 --- a/pub/lib/zentry.hpp +++ b/pub/lib/zentry.hpp @@ -26,10 +26,11 @@ class CZentry { class CCurve: public CZentry { public: - static const int mQuality = 3; vector<double> P; vector<bool> fixed; - double Quality[mQuality]; + int fitOutcome; + double fitChi2; + double fitR2; void clear( void ); string infoLine() const; -- GitLab