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     /// @todo Use some sort of standard ordering to improve comparisons, esp. when the two beams are different particles
00127     bool beamEnergiesOk = requiredEnergies().size() > 0 ? false : true;
00128     typedef pair<double,double> DoublePair;
00129     foreach (const DoublePair& ep, requiredEnergies()) {
00130       if ((fuzzyEquals(ep.first, energies.first, 0.01) && fuzzyEquals(ep.second, energies.second, 0.01)) ||
00131           (fuzzyEquals(ep.first, energies.second, 0.01) && fuzzyEquals(ep.second, energies.first, 0.01)) ||
00132           ((ep.first - energies.first) < 1*GeV && (ep.second - energies.second) < 1*GeV) ||
00133           ((ep.first - energies.second) < 1*GeV && (ep.second - energies.first) < 1*GeV)) {
00134         beamEnergiesOk =  true;
00135         break;
00136       }
00137     }
00138     return beamEnergiesOk;
00139 
00140     /// @todo Need to also check internal consistency of the analysis'
00141     /// beam requirements with those of the projections it uses.
00142   }
00143 
00144 
00145   ///////////////////////////////////////////
00146 
00147 
00148   Analysis& Analysis::setCrossSection(double xs) {
00149     _crossSection = xs;
00150     _gotCrossSection = true;
00151     return *this;
00152   }
00153 
00154   double Analysis::crossSection() const {
00155     if (!_gotCrossSection || std::isnan(_crossSection)) {
00156       string errMsg = "You did not set the cross section for the analysis " + name();
00157       throw Error(errMsg);
00158     }
00159     return _crossSection;
00160   }
00161 
00162   double Analysis::crossSectionPerEvent() const {
00163     const double sumW = sumOfWeights();
00164     assert(sumW != 0.0);
00165     return _crossSection / sumW;
00166   }
00167 
00168 
00169 
00170   ////////////////////////////////////////////////////////////
00171   // Histogramming
00172 
00173 
00174   void Analysis::_cacheRefData() const {
00175     if (_refdata.empty()) {
00176       MSG_TRACE("Getting refdata cache for paper " << name());
00177       _refdata = getRefData(name());
00178     }
00179   }
00180 
00181 
00182   const Scatter2D& Analysis::refData(const string& hname) const {
00183     _cacheRefData();
00184     MSG_TRACE("Using histo bin edges for " << name() << ":" << hname);
00185     if (!_refdata[hname]) {
00186       MSG_ERROR("Can't find reference histogram " << hname);
00187     }
00188     return *_refdata[hname];
00189   }
00190 
00191 
00192   const Scatter2D& Analysis::refData(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId) const {
00193     const string hname = makeAxisCode(datasetId, xAxisId, yAxisId);
00194     return refData(hname);
00195   }
00196 
00197 
00198   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00199                                    size_t nbins, double lower, double upper,
00200                                    const string& title,
00201                                    const string& xtitle,
00202                                    const string& ytitle) {
00203     const string path = histoPath(hname);
00204     Histo1DPtr hist( new Histo1D(nbins, lower, upper, path, title) );
00205     addAnalysisObject(hist);
00206     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00207     hist->setAnnotation("XLabel", xtitle);
00208     hist->setAnnotation("YLabel", ytitle);
00209     return hist;
00210   }
00211 
00212 
00213   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00214                                    const vector<double>& binedges,
00215                                    const string& title,
00216                                    const string& xtitle,
00217                                    const string& ytitle) {
00218     const string path = histoPath(hname);
00219     Histo1DPtr hist( new Histo1D(binedges, path, title) );
00220     addAnalysisObject(hist);
00221     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00222     hist->setAnnotation("XLabel", xtitle);
00223     hist->setAnnotation("YLabel", ytitle);
00224     return hist;
00225   }
00226 
00227 
00228   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00229                                    const Scatter2D& refscatter,
00230                                    const string& title,
00231                                    const string& xtitle,
00232                                    const string& ytitle) {
00233     const string path = histoPath(hname);
00234     Histo1DPtr hist( new Histo1D(refscatter, path) );
00235     addAnalysisObject(hist);
00236     MSG_TRACE("Made histogram " << hname <<  " for " << name());
00237     hist->setTitle(title);
00238     hist->setAnnotation("XLabel", xtitle);
00239     hist->setAnnotation("YLabel", ytitle);
00240     return hist;
00241   }
00242 
00243 
00244   Histo1DPtr Analysis::bookHisto1D(const string& hname,
00245                                    const string& title,
00246                                    const string& xtitle,
00247                                    const string& ytitle) {
00248     const Scatter2D& refdata = refData(hname);
00249     return bookHisto1D(hname, refdata, title, xtitle, ytitle);
00250   }
00251 
00252 
00253   Histo1DPtr Analysis::bookHisto1D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00254                                    const string& title,
00255                                    const string& xtitle,
00256                                    const string& ytitle) {
00257     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00258     return bookHisto1D(axisCode, title, xtitle, ytitle);
00259   }
00260 
00261 
00262   /// @todo Add booking methods which take a path, titles and *a reference Scatter from which to book*
00263 
00264 
00265   /////////////////
00266 
00267 
00268   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00269   //                                  size_t nxbins, double xlower, double xupper,
00270   //                                  size_t nybins, double ylower, double yupper,
00271   //                                  const string& title,
00272   //                                  const string& xtitle,
00273   //                                  const string& ytitle,
00274   //                                  const string& ztitle)
00275   // {
00276   //   const string path = histoPath(hname);
00277   //   Histo2DPtr hist( new Histo2D(path, nxbins, xlower, xupper, nybins, ylower, yupper) );
00278   //   addAnalysisObject(hist);
00279   //   MSG_TRACE("Made histogram " << hname <<  " for " << name());
00280   //   hist->setTitle(title);
00281   //   hist->setAnnotation("XLabel", xtitle);
00282   //   hist->setAnnotation("YLabel", ytitle);
00283   //   hist->setAnnotation("ZLabel", ztitle);
00284   //   return hist;
00285   // }
00286 
00287 
00288   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00289   //                                  const vector<double>& xbinedges,
00290   //                                  const vector<double>& ybinedges,
00291   //                                  const string& title,
00292   //                                  const string& xtitle,
00293   //                                  const string& ytitle,
00294   //                                  const string& ztitle)
00295   // {
00296   //   const string path = histoPath(hname);
00297   //   Histo2DPtr hist( new Histo2D(path, xbinedges, ybinedges) );
00298   //   addAnalysisObject(hist);
00299   //   MSG_TRACE("Made histogram " << hname <<  " for " << name());
00300   //   hist->setTitle(title);
00301   //   hist->setAnnotation("XLabel", xtitle);
00302   //   hist->setAnnotation("YLabel", ytitle);
00303   //   hist->setAnnotation("ZLabel", ztitle);
00304   //   return hist;
00305   // }
00306 
00307 
00308   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00309   //                                  const Scatter3D& refscatter,
00310   //                                  const string& title="",
00311   //                                  const string& xtitle="",
00312   //                                  const string& ytitle="",
00313   //                                  const string& ztitle="") {
00314   //   const string path = histoPath(hname);
00315   //   Histo2DPtr hist( new Histo2D(refscatter, path) );
00316   //   addAnalysisObject(hist);
00317   //   MSG_TRACE("Made histogram " << hname <<  " for " << name());
00318   //   hist->setTitle(title);
00319   //   hist->setAnnotation("XLabel", xtitle);
00320   //   hist->setAnnotation("YLabel", ytitle);
00321   //   hist->setAnnotation("ZLabel", ztitle);
00322   //   return hist;
00323   // }
00324 
00325 
00326   // Histo2DPtr Analysis::bookHisto2D(const string& hname,
00327   //                                  const string& title,
00328   //                                  const string& xtitle,
00329   //                                  const string& ytitle,
00330   //                                  const string& ztitle) {
00331   //   const Scatter3D& refdata = refData(hname);
00332   //   return bookHisto2D(hname, refdata, title, xtitle, ytitle, ztitle);
00333   // }
00334 
00335 
00336   // Histo2DPtr Analysis::bookHisto2D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00337   //                                  const string& title,
00338   //                                  const string& xtitle,
00339   //                                  const string& ytitle,
00340   //                                  const string& ztitle) {
00341   //   const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00342   //   return bookHisto2D(axisCode, title, xtitle, ytitle, ztitle);
00343   // }
00344 
00345 
00346   /////////////////
00347 
00348 
00349   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00350                                        size_t nbins, double lower, double upper,
00351                                        const string& title,
00352                                        const string& xtitle,
00353                                        const string& ytitle) {
00354     const string path = histoPath(hname);
00355     Profile1DPtr prof( new Profile1D(nbins, lower, upper, path, title) );
00356     addAnalysisObject(prof);
00357     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00358     prof->setAnnotation("XLabel", xtitle);
00359     prof->setAnnotation("YLabel", ytitle);
00360     return prof;
00361   }
00362 
00363 
00364   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00365                                        const vector<double>& binedges,
00366                                        const string& title,
00367                                        const string& xtitle,
00368                                        const string& ytitle) {
00369     const string path = histoPath(hname);
00370     Profile1DPtr prof( new Profile1D(binedges, path, title) );
00371     addAnalysisObject(prof);
00372     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00373     prof->setAnnotation("XLabel", xtitle);
00374     prof->setAnnotation("YLabel", ytitle);
00375     return prof;
00376   }
00377 
00378 
00379   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00380                                        const Scatter2D& refscatter,
00381                                        const string& title,
00382                                        const string& xtitle,
00383                                        const string& ytitle) {
00384     const string path = histoPath(hname);
00385     Profile1DPtr prof( new Profile1D(refscatter, path) );
00386     addAnalysisObject(prof);
00387     MSG_TRACE("Made profile histogram " << hname <<  " for " << name());
00388     prof->setTitle(title);
00389     prof->setAnnotation("XLabel", xtitle);
00390     prof->setAnnotation("YLabel", ytitle);
00391     return prof;
00392   }
00393 
00394 
00395   Profile1DPtr Analysis::bookProfile1D(const string& hname,
00396                                        const string& title,
00397                                        const string& xtitle,
00398                                        const string& ytitle) {
00399     const Scatter2D& refdata = refData(hname);
00400     return bookProfile1D(hname, refdata, title, xtitle, ytitle);
00401   }
00402 
00403 
00404   Profile1DPtr Analysis::bookProfile1D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00405                                        const string& title,
00406                                        const string& xtitle,
00407                                        const string& ytitle) {
00408     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00409     return bookProfile1D(axisCode, title, xtitle, ytitle);
00410   }
00411 
00412 
00413   ///////////////////
00414 
00415 
00416   Scatter2DPtr Analysis::bookScatter2D(unsigned int datasetId, unsigned int xAxisId, unsigned int yAxisId,
00417                                        bool copy_pts,
00418                                        const string& title,
00419                                        const string& xtitle,
00420                                        const string& ytitle) {
00421     const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00422     return bookScatter2D(axisCode, copy_pts, title, xtitle, ytitle);
00423   }
00424 
00425 
00426   Scatter2DPtr Analysis::bookScatter2D(const string& hname,
00427                                        bool copy_pts,
00428                                        const string& title,
00429                                        const string& xtitle,
00430                                        const string& ytitle) {
00431     Scatter2DPtr s;
00432     const string path = histoPath(hname);
00433     if (copy_pts) {
00434       const Scatter2D& refdata = refData(hname);
00435       s.reset( new Scatter2D(refdata, path) );
00436       foreach (Point2D& p, s->points()) p.setY(0, 0);
00437     } else {
00438       s.reset( new Scatter2D(path) );
00439     }
00440     addAnalysisObject(s);
00441     MSG_TRACE("Made scatter " << hname <<  " for " << name());
00442     s->setTitle(title);
00443     s->setAnnotation("XLabel", xtitle);
00444     s->setAnnotation("YLabel", ytitle);
00445     return s;
00446   }
00447 
00448 
00449   Scatter2DPtr Analysis::bookScatter2D(const string& hname,
00450                                        size_t npts, double lower, double upper,
00451                                        const string& title,
00452                                        const string& xtitle,
00453                                        const string& ytitle) {
00454     const string path = histoPath(hname);
00455     Scatter2DPtr s( new Scatter2D(path) );
00456     const double binwidth = (upper-lower)/npts;
00457     for (size_t pt = 0; pt < npts; ++pt) {
00458       const double bincentre = lower + (pt + 0.5) * binwidth;
00459       s->addPoint(bincentre, 0, binwidth/2.0, 0);
00460     }
00461     addAnalysisObject(s);
00462     MSG_TRACE("Made scatter " << hname <<  " for " << name());
00463     s->setTitle(title);
00464     s->setAnnotation("XLabel", xtitle);
00465     s->setAnnotation("YLabel", ytitle);
00466     return s;
00467   }
00468 
00469 
00470   Scatter2DPtr Analysis::bookScatter2D(const string& hname,
00471                                        const vector<double>& binedges,
00472                                        const string& title,
00473                                        const string& xtitle,
00474                                        const string& ytitle) {
00475     const string path = histoPath(hname);
00476     Scatter2DPtr s( new Scatter2D(path) );
00477     for (size_t pt = 0; pt < binedges.size()-1; ++pt) {
00478       const double bincentre = (binedges[pt] + binedges[pt+1]) / 2.0;
00479       const double binwidth = binedges[pt+1] - binedges[pt];
00480       s->addPoint(bincentre, 0, binwidth/2.0, 0);
00481     }
00482     addAnalysisObject(s);
00483     MSG_TRACE("Made scatter " << hname <<  " for " << name());
00484     s->setTitle(title);
00485     s->setAnnotation("XLabel", xtitle);
00486     s->setAnnotation("YLabel", ytitle);
00487     return s;
00488   }
00489 
00490 
00491   /////////////////////
00492 
00493 
00494   void Analysis::divide(Histo1DPtr h1, Histo1DPtr h2, Scatter2DPtr s) const {
00495     // preserve the path info
00496     const string path = s->path();
00497     *s = *h1 / *h2;
00498     s->setPath(path);
00499   }
00500 
00501   void Analysis::divide(Profile1DPtr p1, Profile1DPtr p2, Scatter2DPtr s) const {
00502     // preserve the path info
00503     const string path = s->path();
00504     *s = *p1 / *p2;
00505     s->setPath(path);
00506   }
00507 
00508   void Analysis::divide(const Histo1D& h1, const Histo1D& h2, Scatter2DPtr s) const {
00509     // preserve the path info
00510     const string path = s->path();
00511     *s = h1 / h2;
00512     s->setPath(path);
00513   }
00514 
00515   void Analysis::divide(const Profile1D& p1, const Profile1D& p2, Scatter2DPtr s) const {
00516     // preserve the path info
00517     const string path = s->path();
00518     *s = p1 / p2;
00519     s->setPath(path);
00520   }
00521 
00522   void Analysis::normalize(Histo1DPtr histo, double norm, bool includeoverflows) {
00523     if (!histo) {
00524       MSG_ERROR("Failed to normalize histo=NULL in analysis " << name() << " (norm=" << norm << ")");
00525       return;
00526     }
00527     MSG_TRACE("Normalizing histo " << histo->path() << " to " << norm);
00528     try {
00529       histo->normalize(norm, includeoverflows);
00530     } catch (YODA::Exception& we) {
00531       MSG_WARNING("Could not normalize histo " << histo->path());
00532       return;
00533     }
00534   }
00535 
00536 
00537   void Analysis::scale(Histo1DPtr histo, double scale) {
00538     if (!histo) {
00539       MSG_ERROR("Failed to scale histo=NULL in analysis " << name() << " (scale=" << scale << ")");
00540       return;
00541     }
00542     if (std::isnan(scale) || std::isinf(scale)) {
00543       MSG_ERROR("Failed to scale histo=" << histo->path() << " in analysis: " << name() << " (invalid scale factor = " << scale << ")");
00544       scale = 0;
00545     }
00546     MSG_TRACE("Scaling histo " << histo->path() << " by factor " << scale);
00547     try {
00548       histo->scaleW(scale);
00549     } catch (YODA::Exception& we) {
00550       MSG_WARNING("Could not scale histo " << histo->path());
00551       return;
00552     }
00553     // // Transforming the histo into a scatter after scaling
00554     // vector<double> x, y, ex, ey;
00555     // for (size_t i = 0, N = histo->numBins(); i < N; ++i) {
00556     //   x.push_back( histo->bin(i).midpoint() );
00557     //   ex.push_back(histo->bin(i).width()*0.5);
00558     //   y.push_back(histo->bin(i).height()*scale);
00559     //   ey.push_back(histo->bin(i).heightErr()*scale);
00560     // }
00561     // string title = histo->title();
00562     // Scatter2DPtr dps( new Scatter2D(x, y, ex, ey, hpath, title) );
00563     // addAnalysisObject(dps);
00564   }
00565 
00566 
00567   /// @todo 2D versions of scale and normalize...
00568 
00569 
00570   void Analysis::integrate(Histo1DPtr h, Scatter2DPtr s) const {
00571     // preserve the path info
00572     const string path = s->path();
00573     *s = toIntegralHisto(*h);
00574     s->setPath(path);
00575   }
00576 
00577   void Analysis::integrate(const Histo1D& h, Scatter2DPtr s) const {
00578     // preserve the path info
00579     const string path = s->path();
00580     *s = toIntegralHisto(h);
00581     s->setPath(path);
00582   }
00583 
00584 
00585   /// @todo 2D versions of integrate... defined how, exactly?!?
00586 
00587 
00588   //////////////////////////////////
00589 
00590 
00591   void Analysis::addAnalysisObject(AnalysisObjectPtr ao) {
00592     _analysisobjects.push_back(ao);
00593   }
00594 
00595   void Analysis::removeAnalysisObject(const string& path) {
00596     for (vector<AnalysisObjectPtr>::iterator it = _analysisobjects.begin();  it != _analysisobjects.end(); ++it) {
00597       if ((*it)->path() == path) {
00598         _analysisobjects.erase(it);
00599         break;
00600       }
00601     }
00602   }
00603 
00604   void Analysis::removeAnalysisObject(AnalysisObjectPtr ao) {
00605     for (vector<AnalysisObjectPtr>::iterator it = _analysisobjects.begin();  it != _analysisobjects.end(); ++it) {
00606       if (*it == ao) {
00607         _analysisobjects.erase(it);
00608         break;
00609       }
00610     }
00611  }
00612 
00613 
00614 }