00001 #include "NagFitStrategy.h"
00002 #include <TF1.h>
00003 #include <TH1.h>
00004 #include <TGraphErrors.h>
00005 #include <TGraphAsymmErrors.h>
00006
00007 using namespace Sct;
00008 namespace SctFitter{
00009 NagFitStrategy::NagFitStrategy(string opt) throw()
00010 : FitStrategy(opt), name("NagFitStrategy") {}
00011
00012 NagFitStrategy::~NagFitStrategy() throw() {}
00013
00015
00016 void NagFitStrategy::fitTH1(const TH1& hist, TF1& fit) const throw(LogicError, MathsError) {
00018 TH1& theHist = const_cast<TH1&> (hist);
00019
00020
00021 int firstpoint=1;
00022 const int npoints = getNumberFitPoints(theHist, fit, firstpoint);
00023
00024
00025 Cache* cache = new Cache(hist, npoints, firstpoint, fit);
00026 nagFit(cache, fit, quiet());
00027 delete cache;
00028 }
00029
00030
00031 void NagFitStrategy::fitTGraph(const TGraph& graph, TF1& fit) const throw (LogicError, MathsError) {
00032 TGraph& theGraph = const_cast<TGraph&> (graph);
00033
00034
00035 vector<bool> active;
00036 getFitPoints(theGraph, fit, active);
00037
00038 Cache* cache = new Cache(theGraph, fit, active);
00039 nagFit(cache, fit, quiet());
00040 delete cache;
00041 }
00042
00043 void NagFitStrategy::fitTGraphErrors(const TGraphErrors& graph, TF1& fit) const throw (LogicError, MathsError) {
00044 TGraphErrors& theGraph = const_cast<TGraphErrors&> (graph);
00045
00046
00047 vector<bool> active;
00048 getFitPoints(theGraph, fit, active);
00049
00050 Cache* cache = new Cache(theGraph, fit, active);
00051 nagFit(cache, fit, quiet());
00052 delete cache;
00053 }
00054
00055 void NagFitStrategy::fitTGraphAsymmErrors(const TGraphAsymmErrors& graph, TF1& fit) const throw (LogicError, MathsError) {
00056 TGraphAsymmErrors& theGraph = const_cast<TGraphAsymmErrors&> (graph);
00057
00058
00059 vector<bool> active;
00060 getFitPoints(theGraph, fit, active);
00061
00062 Cache* cache = new Cache(theGraph, fit, active);
00063 nagFit(cache, fit, quiet());
00064 delete cache;
00065 }
00066
00067 void NagFitStrategy::nagFit(Cache* cache, TF1& fit, bool quiet) const throw(MathsError) {
00068 unsigned npoints=cache->m_x.size();
00069 if (npoints==0) return;
00070
00072 static NagError fail, fail2;
00073 Nag_Comm comm;
00074 Nag_E04_Opt nagOptions;
00075
00076
00077 e04xxc(&nagOptions);
00078
00079 if (quiet){
00080 nagOptions.list=false;
00081 fail.print = FALSE;
00082 nagOptions.print_level=Nag_NoPrint;
00083
00084 }
00085 double chiSq=0.;
00086 double fjac[npoints][cache->nVarPars];
00087 double fvec[npoints];
00088
00089 comm.p = (Pointer) cache;
00090
00091
00092 nag_opt_lsq_no_deriv(npoints, cache->nVarPars,
00093 &(this->chiSquaredFunctionForNag),
00094 cache->inPars, &chiSq, fvec,
00095 (double*)fjac, cache->nVarPars, &nagOptions, &comm, &fail);
00096
00097 e04xzc(&nagOptions, "all", &fail2);
00098
00099
00100 if (fail.code != NE_NOERROR && fail.code != NW_COND_MIN){
00101 if (!quiet){
00102 MathsError e("NagFitStrategy NAG ERROR", __FILE__, __LINE__);
00103 e.sendToMrs(MRS_DIAGNOSTIC);
00104 }
00105 } else {
00106 cache->convertPars(cache->inPars);
00107 for (int i=0; i<fit.GetNpar(); ++i){
00108 fit.SetParameter(i,cache->pars[i]);
00109
00110 }
00111 fit.SetChisquare(chiSq);
00112 fit.SetNDF(npoints-fit.GetNpar());
00113 }
00114 }
00115
00116 const string& NagFitStrategy::getName() const throw() {
00117 return name;
00118 }
00119
00120 bool NagFitStrategy::inMap=FitStrategyFactory::instance().addToMap("NagFitStrategy", *new NagFitStrategy("") );
00121
00122 const int NagFitStrategy::getNumberFitPoints(TH1& hist, const TF1& fit,
00123 int& firstpoint) const throw (LogicError) {
00124 if (!ranged()){
00125 firstpoint=1;
00126 return hist.GetNbinsX();
00127 }
00128
00129 int iLastBin;
00131 TF1& theFit = const_cast<TF1&> (fit);
00132 double xmin, xmax;
00133 theFit.GetRange(xmin, xmax);
00134 if (xmin>=xmax) throw InvalidArgumentError("NagFitStrategy TF1 fit min>=max", __FILE__, __LINE__);
00135 TAxis* axis=hist.GetXaxis();
00136
00137 firstpoint = axis->FindFixBin(xmin);
00138 iLastBin = axis->FindFixBin(xmax);
00139 if (firstpoint < 1) firstpoint = 1;
00140 if (iLastBin > axis->GetLast()) iLastBin = axis->GetLast();
00141 return iLastBin - firstpoint;
00142 }
00143
00144 void NagFitStrategy::getFitPoints(TGraph& graph, const TF1& fit, vector<bool>& active) const throw (LogicError) {
00145 active.resize(graph.GetN());
00146
00147 if (!ranged()){
00148 for (int ipoint=0; ipoint<graph.GetN(); ++ipoint){
00149 active[ipoint]=true;
00150 }
00151 return;
00152 }
00153
00155 TF1& theFit = const_cast<TF1&> (fit);
00156 double xmin, xmax, x, y;
00157 theFit.GetRange(xmin, xmax);
00158 if (xmin>=xmax) throw InvalidArgumentError("NagFitStrategy TF1 fit min>=max", __FILE__, __LINE__);
00159 for (int ipoint=0; ipoint<graph.GetN(); ++ipoint){
00160 graph.GetPoint(ipoint,x,y);
00161 active[ipoint] = (x>=xmin && x<=xmax);
00162 }
00163 }
00164
00165 NagFitStrategy::Cache::Cache(const TGraph& graph, TF1& fit, const vector<bool>& active) throw(LogicError, MathsError) {
00166 TGraph& theGraph = const_cast<TGraph&> (graph);
00167 function=&fit;
00168 setupPars(fit);
00169 for ( int ipoint=0; ipoint<graph.GetN(); ++ipoint){
00170 if (active[ipoint]){
00171 double x, y;
00172 theGraph.GetPoint(ipoint,x,y);
00173 m_x.push_back(x);
00174 m_y.push_back(y);
00175 m_ey.push_back(1.);
00176 }
00177 }
00178 }
00179
00180 NagFitStrategy::Cache::Cache(const TGraphErrors& graph, TF1& fit, const vector<bool>& active) throw(LogicError, MathsError) {
00181 TGraphErrors& theGraph=const_cast<TGraphErrors&> (graph);
00182 function=&fit;
00183 setupPars(fit);
00184 for ( int ipoint=0; ipoint<graph.GetN(); ++ipoint){
00185 if (active[ipoint]){
00186 double x, y, err;
00187 theGraph.GetPoint(ipoint,x,y);
00188 err=theGraph.GetErrorY(ipoint);
00189 if (err==0.) throw MathsError("NagFitStrategy::Cache(graph) Error=0", __FILE__, __LINE__);
00190 m_x.push_back(x);
00191 m_y.push_back(y);
00192 m_ey.push_back(err);
00193 }
00194 }
00195 }
00196
00197 NagFitStrategy::Cache::Cache(const TGraphAsymmErrors& graph, TF1& fit, const vector<bool>& active) throw(LogicError, MathsError) {
00198 TGraphAsymmErrors& theGraph=const_cast<TGraphAsymmErrors&> (graph);
00199 function=&fit;
00200 setupPars(fit);
00201 for ( int ipoint=0; ipoint<graph.GetN(); ++ipoint){
00202 if (active[ipoint]){
00203 double x, y, err;
00204 theGraph.GetPoint(ipoint,x,y);
00205 err=theGraph.GetErrorY(ipoint);
00206 if (err==0.) throw MathsError("NagFitStrategy::Cache(graph) Error=0", __FILE__, __LINE__);
00207 m_x.push_back(x);
00208 m_y.push_back(y);
00209 m_ey.push_back(err);
00210 }
00211 }
00212 }
00213
00214
00215 NagFitStrategy::Cache::Cache(const TH1& hist, const unsigned npoints,
00216 const unsigned firstpoint, TF1& fit) throw(LogicError, MathsError) {
00217 function=&fit;
00218 setupPars(fit);
00219 for (unsigned i=0; i<npoints; ++i){
00220 double err = hist.GetBinError(i + firstpoint);
00221 if (err==0.) throw MathsError("NagFitStrategy::Cache(TH1) Error=0", __FILE__, __LINE__);
00222 double y=hist.GetBinContent(i + firstpoint);
00223 if (2*err>y) continue;
00224 m_ey.push_back(err);
00225 m_y.push_back(y);
00226 m_x.push_back(hist.GetBinCenter(i + firstpoint));
00227 }
00228 }
00229
00230 NagFitStrategy::Cache::~Cache() throw(){
00231 delete [] pars;
00232 delete [] map;
00233 delete [] inPars;
00234 }
00235
00236 void NagFitStrategy::Cache::convertPars(double inPars[]) {
00237 for (unsigned int i=0; i<nVarPars; ++i) {
00238 pars[map[i]] = inPars[i];
00239 }
00240 }
00241
00242 void NagFitStrategy::Cache::setupPars(TF1& fit) {
00243 map = new int[fit.GetNpar()];
00244 pars = new double[fit.GetNpar()];
00245 inPars = new double[fit.GetNpar()];
00246 nVarPars = 0;
00247 double lowLim, highLim;
00248
00249 for (unsigned int i=0; i<fit.GetNpar(); ++i) {
00250 fit.GetParLimits(i, lowLim, highLim);
00251 if (lowLim == highLim && lowLim != 0) {
00252 pars[i] = lowLim;
00253
00254 } else {
00255 map[nVarPars] = i;
00256 inPars[nVarPars] = fit.GetParameter(i);
00257
00258 ++nVarPars;
00259 }
00260 }
00261
00262 }
00263
00264
00266 void NagFitStrategy::chiSquaredFunctionForNag(Integer nresid, Integer nvar, double x_pars[],
00267 double fvec[], Nag_Comm *comm) throw() {
00268 Cache* cache = (Cache*) comm->p;
00269 cache->convertPars(x_pars);
00270 for (int i=0; i < nresid; ++i){
00271 double resid = cache->function->EvalPar( &(cache->m_x[i]) , cache->pars)
00272 - cache->m_y[i];
00273 fvec[i] = (resid) / (cache->m_ey[i]);
00274 }
00275 }
00276
00277 bool NagFitStrategy::quiet() const throw() {
00278 return ( getOptions().find('Q')!=string::npos ||
00279 getOptions().find('q')!=string::npos );
00280 }
00281
00282 bool NagFitStrategy::ranged() const throw() {
00283 return ( getOptions().find('R')!=string::npos ||
00284 getOptions().find('r')!=string::npos );
00285 }
00286
00287 }
00288