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 } Generated on Thu Feb 6 2014 17:38:41 for The Rivet MC analysis system by ![]() |