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/Analysis.hh"
00004 #include "Rivet/AnalysisHandler.hh"
00005 #include "Rivet/AnalysisInfo.hh"
00006 #include "Rivet/BeamConstraint.hh"
00007 #include "Rivet/Tools/RivetYODA.hh"
00008 #include "Rivet/Tools/Logging.hh"
00009 
00010 namespace Rivet {
00011 
00012 
00013   Analysis::Analysis(const string& name)
00014     : _crossSection(-1.0),
00015       _gotCrossSection(false),
00016       _analysishandler(NULL)
00017   {
00018     ProjectionApplier::_allowProjReg = false;
00019     _defaultname = name;
00020 
00021     AnalysisInfo* ai = AnalysisInfo::make(name);
00022     assert(ai != 0);
00023     _info.reset(ai);
00024     assert(_info.get() != 0);
00025   }
00026 
00027   double Analysis::sqrtS() const {
00028     return handler().sqrtS();
00029   }
00030 
00031   const ParticlePair& Analysis::beams() const {
00032     return handler().beams();
00033   }
00034 
00035   const PdgIdPair Analysis::beamIds() const {
00036     return handler().beamIds();
00037   }
00038 
00039 
00040   const string Analysis::histoDir() const {
00041     /// @todo Cache in a member variable
00042     string _histoDir;
00043     if (_histoDir.empty()) {
00044       _histoDir = "/" + name();
00045       if (handler().runName().length() > 0) {
00046         _histoDir = "/" + handler().runName() + _histoDir;
00047       }
00048       while (find_first(_histoDir, "//")) {
00049         replace_all(_histoDir, "//", "/");
00050       }
00051     }
00052     return _histoDir;
00053   }
00054 
00055 
00056   const string Analysis::histoPath(const string& hname) const {
00057     const string path = histoDir() + "/" + hname;
00058     return path;
00059   }
00060 
00061 
00062   const string Analysis::histoPath(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId) const {
00063     return histoDir() + "/" + makeAxisCode(datasetId, xAxisId, yAxisId);
00064   }
00065 
00066 
00067   const string Analysis::makeAxisCode(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId) const {
00068     stringstream axisCode;
00069     axisCode << "d";
00070     if (datasetId < 10) axisCode << 0;
00071     axisCode << datasetId;
00072     axisCode << "-x";
00073     if (xAxisId < 10) axisCode << 0;
00074     axisCode << xAxisId;
00075     axisCode << "-y";
00076     if (yAxisId < 10) axisCode << 0;
00077     axisCode << yAxisId;
00078     return axisCode.str();
00079   }
00080 
00081 
00082   Log& Analysis::getLog() const {
00083     string logname = "Rivet.Analysis." + name();
00084     return Log::getLog(logname);
00085   }
00086 
00087 
00088   size_t Analysis::numEvents() const {
00089     return handler().numEvents();
00090   }
00091 
00092 
00093   double Analysis::sumOfWeights() const {
00094     return handler().sumOfWeights();
00095   }
00096 
00097 
00098   ///////////////////////////////////////////
00099 
00100 
00101   bool Analysis::isCompatible(const ParticlePair& beams) const {
00102     return isCompatible(beams.first.pdgId(),  beams.second.pdgId(),
00103                         beams.first.energy(), beams.second.energy());
00104   }
00105 
00106 
00107   bool Analysis::isCompatible(PdgId beam1, PdgId beam2, double e1, double e2) const {
00108     PdgIdPair beams(beam1, beam2);
00109     pair<double,double> energies(e1, e2);
00110     return isCompatible(beams, energies);
00111   }
00112 
00113 
00114   bool Analysis::isCompatible(const PdgIdPair& beams, const pair<double,double>& energies) const {
00115     // First check the beam IDs
00116     bool beamIdsOk = false;
00117     foreach (const PdgIdPair& bp, requiredBeams()) {
00118       if (compatible(beams, bp)) {
00119         beamIdsOk =  true;
00120         break;
00121       }
00122     }
00123     if (!beamIdsOk) return false;
00124 
00125     // Next check that the energies are compatible (within 1% or 1 GeV, whichever is larger, for a bit of UI forgiveness)
00126 
00127     /// @todo Use some sort of standard ordering to improve comparisons, esp. when the two beams are different particles
00128     bool beamEnergiesOk = requiredEnergies().size() > 0 ? false : true;
00129     typedef pair<double,double> DoublePair;
00130     foreach (const DoublePair& ep, requiredEnergies()) {
00131       if ((fuzzyEquals(ep.first, energies.first, 0.01) && fuzzyEquals(ep.second, energies.second, 0.01)) ||
00132           (fuzzyEquals(ep.first, energies.second, 0.01) && fuzzyEquals(ep.second, energies.first, 0.01)) ||
00133           (abs(ep.first - energies.first) < 1*GeV && abs(ep.second - energies.second) < 1*GeV) ||
00134           (abs(ep.first - energies.second) < 1*GeV && abs(ep.second - energies.first) < 1*GeV)) {
00135         beamEnergiesOk =  true;
00136         break;
00137       }
00138     }
00139     return beamEnergiesOk;
00140 
00141     /// @todo Need to also check internal consistency of the analysis'
00142     /// beam requirements with those of the projections it uses.
00143   }
00144 
00145 
00146   ///////////////////////////////////////////
00147 
00148 
00149   Analysis& Analysis::setCrossSection(double xs) {
00150     _crossSection = xs;
00151     _gotCrossSection = true;
00152     return *this;
00153   }
00154 
00155   double Analysis::crossSection() const {
00156     if (!_gotCrossSection || std::isnan(_crossSection)) {
00157       string errMsg = "You did not set the cross section for the analysis " + name();
00158       throw Error(errMsg);
00159     }
00160     return _crossSection;
00161   }
00162 
00163   double Analysis::crossSectionPerEvent() const {
00164     const double sumW = sumOfWeights();
00165     assert(sumW != 0.0);
00166     return _crossSection / sumW;
00167   }
00168 
00169 
00170 
00171   ////////////////////////////////////////////////////////////
00172   // Histogramming
00173 
00174 
00175   void Analysis::_cacheRefData() const {
00176     if (_refdata.empty()) {
00177       MSG_TRACE("Getting refdata cache for paper " << name());
00178       _refdata = getRefData(name());
00179     }
00180   }
00181 
00182 
00183   const Scatter2D& Analysis::refData(const string& hname) const {
00184     _cacheRefData();
00185     MSG_TRACE("Using histo bin edges for " << name() << ":" << hname);
00186     if (!_refdata[hname]) {
00187       MSG_ERROR("Can't find reference histogram " << hname);
00188     }
00189     return *_refdata[hname];
00190   }
00191 
00192 
00193   const Scatter2D& Analysis::refData(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId) const {
00194     const string hname = makeAxisCode(datasetId, xAxisId, yAxisId);
00195     return refData(hname);
00196   }
00197 
00198 
00199   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00200                                    size_t nbins, double lower, double upper,
00201                                    const string& title,
00202                                    const string& xtitle,
00203                                    const string& ytitle) {
00204     const string path = histoPath(hname);
00205     Histo1DPtr hist( new Histo1D(nbins, lower, upper, path, title) );
00206     addAnalysisObject(hist);
00207     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00208     hist->setAnnotation("XLabel", xtitle);
00209     hist->setAnnotation("YLabel", ytitle);
00210     return hist;
00211   }
00212 
00213 
00214   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00215                                    const vector<double>& binedges,
00216                                    const string& title,
00217                                    const string& xtitle,
00218                                    const string& ytitle) {
00219     const string path = histoPath(hname);
00220     Histo1DPtr hist( new Histo1D(binedges, path, title) );
00221     addAnalysisObject(hist);
00222     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00223     hist->setAnnotation("XLabel", xtitle);
00224     hist->setAnnotation("YLabel", ytitle);
00225     return hist;
00226   }
00227 
00228 
00229   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00230                                    const Scatter2D& refscatter,
00231                                    const string& title,
00232                                    const string& xtitle,
00233                                    const string& ytitle) {
00234     const string path = histoPath(hname);
00235     Histo1DPtr hist( new Histo1D(refscatter, path) );
00236     addAnalysisObject(hist);
00237     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00238     hist->setTitle(title);
00239     hist->setAnnotation("XLabel", xtitle);
00240     hist->setAnnotation("YLabel", ytitle);
00241     return hist;
00242   }
00243 
00244 
00245   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00246                                    const string& title,
00247                                    const string& xtitle,
00248                                    const string& ytitle) {
00249     const Scatter2D& refdata = refData(hname);
00250     return bookHisto1D(hname, refdata, title, xtitle, ytitle);
00251   }
00252 
00253 
00254   Histo1DPtr Analysis::bookHisto1D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00255                                    const string& title,
00256                                    const string& xtitle,
00257                                    const string& ytitle) {
00258     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00259     return bookHisto1D(axisCode, title, xtitle, ytitle);
00260   }
00261 
00262 
00263   /// @todo Add booking methods which take a path, titles and *a reference Scatter from which to book*
00264 
00265 
00266   /////////////////
00267 
00268 
00269   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00270   //                                  size_t nxbins, double xlower, double xupper,
00271   //                                  size_t nybins, double ylower, double yupper,
00272   //                                  const string& title,
00273   //                                  const string& xtitle,
00274   //                                  const string& ytitle,
00275   //                                  const string& ztitle)
00276   // {
00277   //   const string path = histoPath(hname);
00278   //   Histo2DPtr hist( new Histo2D(path, nxbins, xlower, xupper, nybins, ylower, yupper) );
00279   //   addAnalysisObject(hist);
00280   //   MSG_TRACE("Made histogram " << hname <<  " for " << name());
00281   //   hist->setTitle(title);
00282   //   hist->setAnnotation("XLabel", xtitle);
00283   //   hist->setAnnotation("YLabel", ytitle);
00284   //   hist->setAnnotation("ZLabel", ztitle);
00285   //   return hist;
00286   // }
00287 
00288 
00289   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00290   //                                  const vector<double>& xbinedges,
00291   //                                  const vector<double>& ybinedges,
00292   //                                  const string& title,
00293   //                                  const string& xtitle,
00294   //                                  const string& ytitle,
00295   //                                  const string& ztitle)
00296   // {
00297   //   const string path = histoPath(hname);
00298   //   Histo2DPtr hist( new Histo2D(path, xbinedges, ybinedges) );
00299   //   addAnalysisObject(hist);
00300   //   MSG_TRACE("Made histogram " << hname <<  " for " << name());
00301   //   hist->setTitle(title);
00302   //   hist->setAnnotation("XLabel", xtitle);
00303   //   hist->setAnnotation("YLabel", ytitle);
00304   //   hist->setAnnotation("ZLabel", ztitle);
00305   //   return hist;
00306   // }
00307 
00308 
00309   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00310   //                                  const Scatter3D& refscatter,
00311   //                                  const string& title="",
00312   //                                  const string& xtitle="",
00313   //                                  const string& ytitle="",
00314   //                                  const string& ztitle="") {
00315   //   const string path = histoPath(hname);
00316   //   Histo2DPtr hist( new Histo2D(refscatter, path) );
00317   //   addAnalysisObject(hist);
00318   //   MSG_TRACE("Made histogram " << hname <<  " for " << name());
00319   //   hist->setTitle(title);
00320   //   hist->setAnnotation("XLabel", xtitle);
00321   //   hist->setAnnotation("YLabel", ytitle);
00322   //   hist->setAnnotation("ZLabel", ztitle);
00323   //   return hist;
00324   // }
00325 
00326 
00327   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00328   //                                  const string& title,
00329   //                                  const string& xtitle,
00330   //                                  const string& ytitle,
00331   //                                  const string& ztitle) {
00332   //   const Scatter3D& refdata = refData(hname);
00333   //   return bookHisto2D(hname, refdata, title, xtitle, ytitle, ztitle);
00334   // }
00335 
00336 
00337   // Histo2DPtr Analysis::bookHisto2D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00338   //                                  const string& title,
00339   //                                  const string& xtitle,
00340   //                                  const string& ytitle,
00341   //                                  const string& ztitle) {
00342   //   const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00343   //   return bookHisto2D(axisCode, title, xtitle, ytitle, ztitle);
00344   // }
00345 
00346 
00347   /////////////////
00348 
00349 
00350   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00351                                        size_t nbins, double lower, double upper,
00352                                        const string& title,
00353                                        const string& xtitle,
00354                                        const string& ytitle) {
00355     const string path = histoPath(hname);
00356     Profile1DPtr prof( new Profile1D(nbins, lower, upper, path, title) );
00357     addAnalysisObject(prof);
00358     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00359     prof->setAnnotation("XLabel", xtitle);
00360     prof->setAnnotation("YLabel", ytitle);
00361     return prof;
00362   }
00363 
00364 
00365   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00366                                        const vector<double>& binedges,
00367                                        const string& title,
00368                                        const string& xtitle,
00369                                        const string& ytitle) {
00370     const string path = histoPath(hname);
00371     Profile1DPtr prof( new Profile1D(binedges, path, title) );
00372     addAnalysisObject(prof);
00373     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00374     prof->setAnnotation("XLabel", xtitle);
00375     prof->setAnnotation("YLabel", ytitle);
00376     return prof;
00377   }
00378 
00379 
00380   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00381                                        const Scatter2D& refscatter,
00382                                        const string& title,
00383                                        const string& xtitle,
00384                                        const string& ytitle) {
00385     const string path = histoPath(hname);
00386     Profile1DPtr prof( new Profile1D(refscatter, path) );
00387     addAnalysisObject(prof);
00388     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00389     prof->setTitle(title);
00390     prof->setAnnotation("XLabel", xtitle);
00391     prof->setAnnotation("YLabel", ytitle);
00392     return prof;
00393   }
00394 
00395 
00396   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00397                                        const string& title,
00398                                        const string& xtitle,
00399                                        const string& ytitle) {
00400     const Scatter2D& refdata = refData(hname);
00401     return bookProfile1D(hname, refdata, title, xtitle, ytitle);
00402   }
00403 
00404 
00405   Profile1DPtr Analysis::bookProfile1D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00406                                        const string& title,
00407                                        const string& xtitle,
00408                                        const string& ytitle) {
00409     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00410     return bookProfile1D(axisCode, title, xtitle, ytitle);
00411   }
00412 
00413 
00414   ///////////////////
00415 
00416 
00417   Scatter2DPtr Analysis::bookScatter2D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00418                                        bool copy_pts,
00419                                        const string& title,
00420                                        const string& xtitle,
00421                                        const string& ytitle) {
00422     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00423     return bookScatter2D(axisCode, copy_pts, title, xtitle, ytitle);
00424   }
00425 
00426 
00427   Scatter2DPtr Analysis::bookScatter2D(const string& hname,
00428                                        bool copy_pts,
00429                                        const string& title,
00430                                        const string& xtitle,
00431                                        const string& ytitle) {
00432     Scatter2DPtr s;
00433     const string path = histoPath(hname);
00434     if (copy_pts) {
00435       const Scatter2D& refdata = refData(hname);
00436       s.reset( new Scatter2D(refdata, path) );
00437       foreach (Point2D& p, s->points()) p.setY(0, 0);
00438     } else {
00439       s.reset( new Scatter2D(path) );
00440     }
00441     addAnalysisObject(s);
00442     MSG_TRACE("Made scatter " << hname <<  " for " << name());
00443     s->setTitle(title);
00444     s->setAnnotation("XLabel", xtitle);
00445     s->setAnnotation("YLabel", ytitle);
00446     return s;
00447   }
00448 
00449 
00450   Scatter2DPtr Analysis::bookScatter2D(const string& hname,
00451                                        size_t npts, double lower, double upper,
00452                                        const string& title,
00453                                        const string& xtitle,
00454                                        const string& ytitle) {
00455     const string path = histoPath(hname);
00456     Scatter2DPtr s( new Scatter2D(path) );
00457     const double binwidth = (upper-lower)/npts;
00458     for (size_t pt = 0; pt < npts; ++pt) {
00459       const double bincentre = lower + (pt + 0.5) * binwidth;
00460       s->addPoint(bincentre, 0, binwidth/2.0, 0);
00461     }
00462     addAnalysisObject(s);
00463     MSG_TRACE("Made scatter " << hname <<  " for " << name());
00464     s->setTitle(title);
00465     s->setAnnotation("XLabel", xtitle);
00466     s->setAnnotation("YLabel", ytitle);
00467     return s;
00468   }
00469 
00470 
00471   Scatter2DPtr Analysis::bookScatter2D(const string& hname,
00472                                        const vector<double>& binedges,
00473                                        const string& title,
00474                                        const string& xtitle,
00475                                        const string& ytitle) {
00476     const string path = histoPath(hname);
00477     Scatter2DPtr s( new Scatter2D(path) );
00478     for (size_t pt = 0; pt < binedges.size()-1; ++pt) {
00479       const double bincentre = (binedges[pt] + binedges[pt+1]) / 2.0;
00480       const double binwidth = binedges[pt+1] - binedges[pt];
00481       s->addPoint(bincentre, 0, binwidth/2.0, 0);
00482     }
00483     addAnalysisObject(s);
00484     MSG_TRACE("Made scatter " << hname <<  " for " << name());
00485     s->setTitle(title);
00486     s->setAnnotation("XLabel", xtitle);
00487     s->setAnnotation("YLabel", ytitle);
00488     return s;
00489   }
00490 
00491 
00492   /////////////////////
00493 
00494 
00495   void Analysis::divide(Histo1DPtr h1, Histo1DPtr h2, Scatter2DPtr s) const {
00496     // preserve the path info
00497     const string path = s->path();
00498     *s = *h1 / *h2;
00499     s->setPath(path);
00500   }
00501 
00502   void Analysis::divide(Profile1DPtr p1, Profile1DPtr p2, Scatter2DPtr s) const {
00503     // preserve the path info
00504     const string path = s->path();
00505     *s = *p1 / *p2;
00506     s->setPath(path);
00507   }
00508 
00509   void Analysis::divide(const Histo1D& h1, const Histo1D& h2, Scatter2DPtr s) const {
00510     // preserve the path info
00511     const string path = s->path();
00512     *s = h1 / h2;
00513     s->setPath(path);
00514   }
00515 
00516   void Analysis::divide(const Profile1D& p1, const Profile1D& p2, Scatter2DPtr s) const {
00517     // preserve the path info
00518     const string path = s->path();
00519     *s = p1 / p2;
00520     s->setPath(path);
00521   }
00522 
00523   void Analysis::normalize(Histo1DPtr histo, double norm, bool includeoverflows) {
00524     if (!histo) {
00525       MSG_ERROR("Failed to normalize histo=NULL in analysis " << name() << " (norm=" << norm << ")");
00526       return;
00527     }
00528     MSG_TRACE("Normalizing histo " << histo->path() << " to " << norm);
00529     try {
00530       histo->normalize(norm, includeoverflows);
00531     } catch (YODA::Exception& we) {
00532       MSG_WARNING("Could not normalize histo " << histo->path());
00533       return;
00534     }
00535   }
00536 
00537 
00538   void Analysis::scale(Histo1DPtr histo, double scale) {
00539     if (!histo) {
00540       MSG_ERROR("Failed to scale histo=NULL in analysis " << name() << " (scale=" << scale << ")");
00541       return;
00542     }
00543     if (std::isnan(scale) || std::isinf(scale)) {
00544       MSG_ERROR("Failed to scale histo=" << histo->path() << " in analysis: " << name() << " (invalid scale factor = " << scale << ")");
00545       scale = 0;
00546     }
00547     MSG_TRACE("Scaling histo " << histo->path() << " by factor " << scale);
00548     try {
00549       histo->scaleW(scale);
00550     } catch (YODA::Exception& we) {
00551       MSG_WARNING("Could not scale histo " << histo->path());
00552       return;
00553     }
00554     // // Transforming the histo into a scatter after scaling
00555     // vector<double> x, y, ex, ey;
00556     // for (size_t i = 0, N = histo->numBins(); i < N; ++i) {
00557     //   x.push_back( histo->bin(i).midpoint() );
00558     //   ex.push_back(histo->bin(i).width()*0.5);
00559     //   y.push_back(histo->bin(i).height()*scale);
00560     //   ey.push_back(histo->bin(i).heightErr()*scale);
00561     // }
00562     // string title = histo->title();
00563     // Scatter2DPtr dps( new Scatter2D(x, y, ex, ey, hpath, title) );
00564     // addAnalysisObject(dps);
00565   }
00566 
00567 
00568   /// @todo 2D versions of scale and normalize...
00569 
00570 
00571   void Analysis::integrate(Histo1DPtr h, Scatter2DPtr s) const {
00572     // preserve the path info
00573     const string path = s->path();
00574     *s = toIntegralHisto(*h);
00575     s->setPath(path);
00576   }
00577 
00578   void Analysis::integrate(const Histo1D& h, Scatter2DPtr s) const {
00579     // preserve the path info
00580     const string path = s->path();
00581     *s = toIntegralHisto(h);
00582     s->setPath(path);
00583   }
00584 
00585 
00586   /// @todo 2D versions of integrate... defined how, exactly?!?
00587 
00588 
00589   //////////////////////////////////
00590 
00591 
00592   void Analysis::addAnalysisObject(AnalysisObjectPtr ao) {
00593     _analysisobjects.push_back(ao);
00594   }
00595 
00596   void Analysis::removeAnalysisObject(const string& path) {
00597     for (vector<AnalysisObjectPtr>::iterator it = _analysisobjects.begin();  it != _analysisobjects.end(); ++it) {
00598       if ((*it)->path() == path) {
00599         _analysisobjects.erase(it);
00600         break;
00601       }
00602     }
00603   }
00604 
00605   void Analysis::removeAnalysisObject(AnalysisObjectPtr ao) {
00606     for (vector<AnalysisObjectPtr>::iterator it = _analysisobjects.begin();  it != _analysisobjects.end(); ++it) {
00607       if (*it == ao) {
00608         _analysisobjects.erase(it);
00609         break;
00610       }
00611     }
00612  }
00613 
00614 
00615 }