rivet is hosted by Hepforge, IPPP Durham
Analysis.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Rivet.hh"
00003 #include "Rivet/RivetYODA.hh"
00004 #include "Rivet/AnalysisHandler.hh"
00005 #include "Rivet/AnalysisInfo.hh"
00006 #include "Rivet/Analysis.hh"
00007 #include "Rivet/Tools/Logging.hh"
00008 
00009 namespace Rivet {
00010   Analysis::Analysis(const string& name)
00011     : _crossSection(-1.0),
00012       _gotCrossSection(false),
00013       _analysishandler(NULL)
00014   {
00015     ProjectionApplier::_allowProjReg = false;
00016     _defaultname = name;
00017 
00018     AnalysisInfo* ai = AnalysisInfo::make(name);
00019     assert(ai != 0);
00020     _info.reset(ai);
00021     assert(_info.get() != 0);
00022   }
00023 
00024   double Analysis::sqrtS() const {
00025     return handler().sqrtS();
00026   }
00027 
00028   const ParticlePair& Analysis::beams() const {
00029     return handler().beams();
00030   }
00031 
00032   const PdgIdPair Analysis::beamIds() const {
00033     return handler().beamIds();
00034   }
00035 
00036 
00037   const string Analysis::histoDir() const {
00038     /// @todo This doesn't change: calc and cache at first use!
00039     string path = "/" + name();
00040     if (handler().runName().length() > 0) {
00041       path = "/" + handler().runName() + path;
00042     }
00043     while (find_first(path, "//")) {
00044       replace_all(path, "//", "/");
00045     }
00046     return path;
00047   }
00048 
00049 
00050   const string Analysis::histoPath(const string& hname) const {
00051     const string path = histoDir() + "/" + hname;
00052     return path;
00053   }
00054 
00055 
00056   const string Analysis::histoPath(size_t datasetId, size_t xAxisId, size_t yAxisId) const {
00057     return histoDir() + "/" + makeAxisCode(datasetId, xAxisId, yAxisId);
00058   }
00059 
00060 
00061   const string Analysis::makeAxisCode(size_t datasetId, size_t xAxisId, size_t yAxisId) const {
00062     stringstream axisCode;
00063     axisCode << "d";
00064     if (datasetId < 10) axisCode << 0;
00065     axisCode << datasetId;
00066     axisCode << "-x";
00067     if (xAxisId < 10) axisCode << 0;
00068     axisCode << xAxisId;
00069     axisCode << "-y";
00070     if (yAxisId < 10) axisCode << 0;
00071     axisCode << yAxisId;
00072     return axisCode.str();
00073   }
00074 
00075 
00076   Log& Analysis::getLog() const {
00077     string logname = "Rivet.Analysis." + name();
00078     return Log::getLog(logname);
00079   }
00080 
00081 
00082   size_t Analysis::numEvents() const {
00083     return handler().numEvents();
00084   }
00085 
00086 
00087   double Analysis::sumOfWeights() const {
00088     return handler().sumOfWeights();
00089   }
00090 
00091 
00092   ///////////////////////////////////////////
00093 
00094 
00095   bool Analysis::isCompatible(const ParticlePair& beams) const {
00096     return isCompatible(beams.first.pdgId(),  beams.second.pdgId(),
00097                         beams.first.energy(), beams.second.energy());
00098   }
00099 
00100 
00101   bool Analysis::isCompatible(PdgId beam1, PdgId beam2, double e1, double e2) const {
00102     PdgIdPair beams(beam1, beam2);
00103     pair<double,double> energies(e1, e2);
00104     return isCompatible(beams, energies);
00105   }
00106 
00107 
00108   bool Analysis::isCompatible(const PdgIdPair& beams, const pair<double,double>& energies) const {
00109     // First check the beam IDs
00110     bool beamIdsOk = false;
00111     foreach (const PdgIdPair& bp, requiredBeams()) {
00112       if (compatible(beams, bp)) {
00113         beamIdsOk =  true;
00114         break;
00115       }
00116     }
00117     if (!beamIdsOk) return false;
00118 
00119     // Next check that the energies are compatible (within 1%, to give a bit of UI forgiveness)
00120     bool beamEnergiesOk = requiredEnergies().size()>0 ? false : true;
00121     typedef pair<double,double> DoublePair;
00122     foreach (const DoublePair& ep, requiredEnergies()) {
00123       if ((fuzzyEquals(ep.first, energies.first, 0.01) && fuzzyEquals(ep.second, energies.second, 0.01)) ||
00124           (fuzzyEquals(ep.first, energies.second, 0.01) && fuzzyEquals(ep.second, energies.first, 0.01))) {
00125         beamEnergiesOk =  true;
00126         break;
00127       }
00128     }
00129     return beamEnergiesOk;
00130 
00131     /// @todo Need to also check internal consistency of the analysis'
00132     /// beam requirements with those of the projections it uses.
00133   }
00134 
00135 
00136   ///////////////////////////////////////////
00137 
00138 
00139   Analysis& Analysis::setCrossSection(double xs) {
00140     _crossSection = xs;
00141     _gotCrossSection = true;
00142     return *this;
00143   }
00144 
00145   double Analysis::crossSection() const {
00146     if (!_gotCrossSection || std::isnan(_crossSection)) {
00147       string errMsg = "You did not set the cross section for the analysis " + name();
00148       throw Error(errMsg);
00149     }
00150     return _crossSection;
00151   }
00152 
00153   double Analysis::crossSectionPerEvent() const {
00154     const double sumW = sumOfWeights();
00155     assert(sumW != 0.0);
00156     return _crossSection / sumW;
00157   }
00158 
00159 
00160 
00161   ////////////////////////////////////////////////////////////
00162   // Histogramming
00163 
00164 
00165   void Analysis::_cacheRefData() const {
00166     if (_refdata.empty()) {
00167       MSG_TRACE("Getting refdata cache for paper " << name());
00168       _refdata = getRefData(name());
00169     }
00170   }
00171 
00172 
00173   const Scatter2D & Analysis::referenceData(const string& hname) const {
00174     _cacheRefData();
00175     MSG_TRACE("Using histo bin edges for " << name() << ":" << hname);
00176     if (!_refdata[hname]) {
00177       MSG_ERROR("Can't find reference histogram " << hname);
00178     }
00179     return *_refdata[hname];
00180   }
00181 
00182 
00183   const Scatter2D & Analysis::referenceData(size_t datasetId, size_t xAxisId, size_t yAxisId) const {
00184     const string hname = makeAxisCode(datasetId, xAxisId, yAxisId);
00185     return referenceData(hname);
00186   }
00187 
00188 
00189   Histo1DPtr Analysis::bookHisto1D(size_t datasetId, size_t xAxisId,
00190                                    size_t yAxisId, const string& title,
00191                                    const string& xtitle, const string& ytitle)
00192   {
00193     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00194     return bookHisto1D(axisCode, title, xtitle, ytitle);
00195   }
00196 
00197 
00198   Histo1DPtr Analysis::bookHisto1D(const string& hname, const string& title,
00199                                    const string& xtitle, const string& ytitle)
00200   {
00201     const Scatter2D & refdata = referenceData(hname);
00202     const string path = histoPath(hname);
00203     Histo1DPtr hist( new Histo1D(refdata, path) );
00204     addPlot(hist);
00205     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00206     hist->setTitle(title);
00207     hist->setAnnotation("XLabel", xtitle);
00208     hist->setAnnotation("YLabel", ytitle);
00209     return hist;
00210   }
00211 
00212 
00213   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00214                                    size_t nbins, double lower, double upper,
00215                                    const string& title,
00216                                    const string& xtitle, const string& ytitle) {
00217     const string path = histoPath(hname);
00218     Histo1DPtr hist( new Histo1D(nbins, lower, upper, path, title) );
00219     addPlot(hist);
00220     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00221     hist->setAnnotation("XLabel", xtitle);
00222     hist->setAnnotation("YLabel", ytitle);
00223     return hist;
00224   }
00225 
00226 
00227   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00228                                    const vector<double>& binedges,
00229                                    const string& title,
00230                                    const string& xtitle,
00231                                    const string& ytitle) {
00232     const string path = histoPath(hname);
00233     Histo1DPtr hist( new Histo1D(binedges, path, title) );
00234     addPlot(hist);
00235     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00236     hist->setAnnotation("XLabel", xtitle);
00237     hist->setAnnotation("YLabel", ytitle);
00238     return hist;
00239   }
00240 
00241   // IHistogram2D*
00242   // Analysis::bookHistogram2D(const string& hname,
00243   //                size_t nxbins, double xlower, double xupper,
00244   //                size_t nybins, double ylower, double yupper,
00245   //                const string& title, const string& xtitle,
00246   //                const string& ytitle, const string& ztitle) {
00247   //   _makeHistoDir();
00248   //   const string path = histoPath(hname);
00249   //   IHistogram2D* hist =
00250   //     histogramFactory().createHistogram2D(path, title, nxbins, xlower, xupper,
00251   //                       nybins, ylower, yupper);
00252   //   MSG_TRACE("Made 2D histogram " << hname <<  " for " << name());
00253   //   hist->setXTitle(xtitle);
00254   //   hist->setYTitle(ytitle);
00255   //   hist->setZTitle(ztitle);
00256   //   return hist;
00257   // }
00258 
00259 
00260   // IHistogram2D*
00261   // Analysis::bookHistogram2D(const string& hname,
00262   //                const vector<double>& xbinedges,
00263   //                const vector<double>& ybinedges,
00264   //                const string& title, const string& xtitle,
00265   //                const string& ytitle, const string& ztitle) {
00266   //   _makeHistoDir();
00267   //   const string path = histoPath(hname);
00268   //   IHistogram2D* hist =
00269   //     histogramFactory().createHistogram2D(path, title, xbinedges, ybinedges);
00270   //   MSG_TRACE("Made 2D histogram " << hname <<  " for " << name());
00271   //   hist->setXTitle(xtitle);
00272   //   hist->setYTitle(ytitle);
00273   //   hist->setZTitle(ztitle);
00274   //   return hist;
00275   // }
00276 
00277 
00278   /////////////////
00279 
00280 
00281   Profile1DPtr Analysis::bookProfile1D(size_t datasetId, size_t xAxisId,
00282                                        size_t yAxisId, const string& title,
00283                                        const string& xtitle, const string& ytitle) {
00284     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00285     return bookProfile1D(axisCode, title, xtitle, ytitle);
00286   }
00287 
00288 
00289   Profile1DPtr Analysis::bookProfile1D(const string& hname, const string& title,
00290                                        const string& xtitle, const string& ytitle)
00291   {
00292     const Scatter2D & refdata = referenceData(hname);
00293     const string path = histoPath(hname);
00294     Profile1DPtr prof( new Profile1D(refdata, path) );
00295     addPlot(prof);
00296     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00297     prof->setTitle(title);
00298     prof->setAnnotation("XLabel", xtitle);
00299     prof->setAnnotation("YLabel", ytitle);
00300     return prof;
00301   }
00302 
00303 
00304   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00305                                        size_t nbins, double lower, double upper,
00306                                        const string& title,
00307                                        const string& xtitle, const string& ytitle) {
00308     const string path = histoPath(hname);
00309     Profile1DPtr prof( new Profile1D(nbins, lower, upper, path, title) );
00310     addPlot(prof);
00311     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00312     prof->setAnnotation("XLabel", xtitle);
00313     prof->setAnnotation("YLabel", ytitle);
00314     return prof;
00315   }
00316 
00317 
00318   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00319                                        const vector<double>& binedges,
00320                                        const string& title,
00321                                        const string& xtitle, const string& ytitle) {
00322     const string path = histoPath(hname);
00323     Profile1DPtr prof( new Profile1D(binedges, path, title) );
00324     addPlot(prof);
00325     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00326     prof->setAnnotation("XLabel", xtitle);
00327     prof->setAnnotation("YLabel", ytitle);
00328     return prof;
00329   }
00330 
00331 
00332   ///////////////////
00333 
00334 
00335   Scatter2DPtr Analysis::bookScatter2D(size_t datasetId, size_t xAxisId,
00336                                        size_t yAxisId, const string& title,
00337                                        const string& xtitle, const string& ytitle) {
00338     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00339     return bookScatter2D(axisCode, title, xtitle, ytitle);
00340   }
00341 
00342 
00343   Scatter2DPtr Analysis::bookScatter2D(const string& hname, const string& title,
00344                                        const string& xtitle, const string& ytitle) {
00345     const string path = histoPath(hname);
00346     Scatter2DPtr dps( new Scatter2D(path, title) );
00347     addPlot(dps);
00348     MSG_TRACE("Made data point set " << hname <<  " for " << name());
00349     dps->setAnnotation("XLabel", xtitle);
00350     dps->setAnnotation("YLabel", ytitle);
00351     return dps;
00352   }
00353 
00354 
00355   Scatter2DPtr Analysis::bookScatter2D(const string& hname,
00356                                        size_t npts, double lower, double upper,
00357                                        const string& title,
00358                                        const string& xtitle, const string& ytitle) {
00359     Scatter2DPtr dps = bookScatter2D(hname, title, xtitle, ytitle);
00360     const double binwidth = (upper-lower)/npts;
00361     for (size_t pt = 0; pt < npts; ++pt) {
00362       const double bincentre = lower + (pt + 0.5) * binwidth;
00363       // @todo YODA check
00364       dps->addPoint(bincentre, 0, binwidth/2.0, 0);
00365       // IMeasurement* meas = dps->point(pt)->coordinate(0);
00366       // meas->setValue(bincentre);
00367       // meas->setErrorPlus(binwidth/2.0);
00368       // meas->setErrorMinus(binwidth/2.0);
00369     }
00370     return dps;
00371   }
00372 
00373   // @todo YODA
00374   // Scatter2DPtr Analysis::bookScatter2D(size_t datasetId, size_t xAxisId,
00375   //                       size_t yAxisId, const string& title,
00376   //                       const string& xtitle, const string& ytitle) {
00377   //   // Get the bin edges (only read the AIDA file once)
00378   //   _cacheXAxisData();
00379   //   // Build the axis code
00380   //   const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00381   //   //const map<string, vector<DPSXPoint> > xpoints = getDPSXValsErrs(papername);
00382   //   MSG_TRACE("Using DPS x-positions for " << name() << ":" << axisCode);
00383   //   Scatter2DPtr dps = bookScatter2D(axisCode, title, xtitle, ytitle);
00384   //   const vector<Point2D> xpts = _dpsData.find(axisCode)->second;
00385   //   foreach ( const Point2D & pt, xpts ) {
00386   //     // \todo YODA check
00387   //     dps->addPoint(pt.x(), pt.xErrMinus(), pt.xErrPlus(), 0, 0, 0);
00388   //     // dps->addPoint(xpts[pt].val, xpts[pt].errminus, xpts[pt].errplus, 0, 0, 0);
00389   //     // IMeasurement* meas = dps->point(pt)->coordinate(0);
00390   //     // meas->setValue(xpts[pt].val);
00391   //     // meas->setErrorPlus(xpts[pt].errplus);
00392   //     // meas->setErrorMinus(xpts[pt].errminus);
00393   //   }
00394   //   MSG_TRACE("Made DPS " << axisCode <<  " for " << name());
00395   //   return dps;
00396   // }
00397 
00398 
00399   void Analysis::divide(Histo1DPtr h1, Histo1DPtr h2, Scatter2DPtr s) const {
00400     // preserve the path info
00401     std::string path = s->path();
00402     *s = *h1 / *h2;
00403     s->setPath( path );
00404   }
00405 
00406   void Analysis::divide(Profile1DPtr p1, Profile1DPtr p2, Scatter2DPtr s) const {
00407     // preserve the path info
00408     std::string path = s->path();
00409     *s = *p1 / *p2;
00410     s->setPath( path );
00411   }
00412 
00413   void Analysis::divide(const Histo1D & h1,
00414                         const Histo1D & h2,
00415                         Scatter2DPtr s) const {
00416     // preserve the path info
00417     std::string path = s->path();
00418     *s = h1 / h2;
00419     s->setPath( path );
00420   }
00421 
00422   void Analysis::divide(const Profile1D & p1,
00423                         const Profile1D & p2,
00424                         Scatter2DPtr s) const {
00425     // preserve the path info
00426     std::string path = s->path();
00427     *s = p1 / p2;
00428     s->setPath( path );
00429   }
00430 
00431   void Analysis::normalize(Histo1DPtr histo, double norm, bool includeoverflows) {
00432     if (!histo) {
00433       MSG_ERROR("Failed to normalize histo=NULL in analysis " << name() << " (norm=" << norm << ")");
00434       return;
00435     }
00436     MSG_TRACE("Normalizing histo " << histo->path() << " to " << norm);
00437     try {
00438       histo->normalize(norm, includeoverflows);
00439     } catch (YODA::WeightError& we) {
00440       MSG_WARNING("Could not normalize histo " << histo->path());
00441       return;
00442     }
00443   }
00444 
00445 
00446   void Analysis::scale(Histo1DPtr histo, double scale) {
00447     if (!histo) {
00448       MSG_ERROR("Failed to scale histo=NULL in analysis " << name() << " (scale=" << scale << ")");
00449       return;
00450     }
00451     MSG_TRACE("Scaling histo " << histo->path() << "by factor " << scale);
00452     try {
00453       histo->scaleW(scale);
00454     } catch (YODA::WeightError& we) {
00455       MSG_WARNING("Could not normalize histo " << histo->path());
00456       return;
00457     }
00458     // // Transforming the histo into a scatter after scaling
00459     // vector<double> x, y, ex, ey;
00460     // for (size_t i = 0, N = histo->numBins(); i < N; ++i) {
00461     //   x.push_back( histo->bin(i).midpoint() );
00462     //   ex.push_back(histo->bin(i).width()*0.5);
00463     //   y.push_back(histo->bin(i).height()*scale);
00464     //   ey.push_back(histo->bin(i).heightErr()*scale);
00465     // }
00466     // string title = histo->title();
00467     // Scatter2DPtr dps( new Scatter2D(x, y, ex, ey, hpath, title) );
00468     // addPlot(dps);
00469   }
00470 
00471 
00472   /// @todo 2D versions of scale and normalize... or ditch these completely?
00473 
00474 
00475   void Analysis::addPlot(AnalysisObjectPtr ao) {
00476     _plotobjects.push_back(ao);
00477   }
00478 
00479 }