Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Related Pages

NagFitStrategy.cpp

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

Generated on Thu Jul 15 09:50:48 2004 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5