NagFitStrategy.cpp

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     // use the range of fit to find the number of fit points
00020     // and the first active bin.
00021     int firstpoint=1;
00022     const int npoints = getNumberFitPoints(theHist, fit, firstpoint);
00023 
00024     // update the cache;
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     // use the range of fit to find the number of fit points
00034     // and the first active bin.
00035     vector<bool> active;
00036     getFitPoints(theGraph, fit, active);  // can use TGraph version.
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     // use the range of fit to find the number of fit points
00046     // and the first active bin.
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     // use the range of fit to find the number of fit points
00058     // and the first active bin.
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;  // don't throw -- just return.
00070     
00072     static NagError fail, fail2; 
00073     Nag_Comm comm;
00074     Nag_E04_Opt nagOptions;
00075 
00076     //initialize options structure.
00077     e04xxc(&nagOptions);
00078     
00079     if (quiet){
00080         nagOptions.list=false;
00081         fail.print = FALSE;
00082         nagOptions.print_level=Nag_NoPrint;
00083         //strcpy(nagOptions.outfile,"Nag.out");
00084     }
00085     double chiSq=0.;
00086     double fjac[npoints][cache->nVarPars];
00087     double fvec[npoints];
00088 
00089     comm.p = (Pointer) cache;
00090 
00091     // Call the optimisation routine:
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     // check for problems:
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         //cout << "Set Par " << i << " to  " << cache->pars[i] << endl;
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()){ // no 'R' so don't take range from TF1
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()){ // no 'R' so don't take range from TF1
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.); // set error to 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         //cout << "Fixing par: " << i << " to " << lowLim << endl;
00254         } else {
00255         map[nVarPars] = i;
00256         inPars[nVarPars] = fit.GetParameter(i);
00257         //cout << "Par " << i << " variable. Initial val: " << inPars[nVarPars] << endl;        
00258         ++nVarPars;
00259         }
00260     }
00261     //cout << "NVarPar: " << nVarPars << endl;
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 }  // end of namespace SctFitter;
00288 

Generated on Mon Feb 6 14:01:23 2006 for SCT DAQ/DCS Software - C++ by  doxygen 1.4.6