00001
00002 #include "Rivet/Rivet.hh"
00003 #include "Rivet/RivetAIDA.hh"
00004 #include "Rivet/AnalysisHandler.hh"
00005 #include "Rivet/AnalysisInfo.hh"
00006 #include "Rivet/Analysis.hh"
00007 #include "Rivet/Tools/Logging.hh"
00008 #include "LWH/AIManagedObject.h"
00009 using namespace AIDA;
00010
00011 namespace Rivet {
00012
00013
00014 namespace {
00015 string makeAxisCode(const size_t datasetId, const size_t xAxisId, const size_t yAxisId) {
00016 stringstream axisCode;
00017 axisCode << "d";
00018 if (datasetId < 10) axisCode << 0;
00019 axisCode << datasetId;
00020 axisCode << "-x";
00021 if (xAxisId < 10) axisCode << 0;
00022 axisCode << xAxisId;
00023 axisCode << "-y";
00024 if (yAxisId < 10) axisCode << 0;
00025 axisCode << yAxisId;
00026 return axisCode.str();
00027 }
00028 }
00029
00030
00031
00032
00033
00034 Analysis::Analysis(const string& name)
00035 : _crossSection(-1.0),
00036 _gotCrossSection(false),
00037 _analysishandler(NULL),
00038 _madeHistoDir(false)
00039 {
00040 ProjectionApplier::_allowProjReg = false;
00041 _defaultname = name;
00042
00043 AnalysisInfo* ai = AnalysisInfo::make(name);
00044 assert(ai != 0);
00045 _info.reset(ai);
00046 assert(_info.get() != 0);
00047 }
00048
00049
00050 IAnalysisFactory& Analysis::analysisFactory() {
00051 return handler().analysisFactory();
00052 }
00053
00054
00055 ITree& Analysis::tree() {
00056 return handler().tree();
00057 }
00058
00059
00060 IHistogramFactory& Analysis::histogramFactory() {
00061 return handler().histogramFactory();
00062 }
00063
00064
00065 IDataPointSetFactory& Analysis::datapointsetFactory() {
00066 return handler().datapointsetFactory();
00067 }
00068
00069
00070 double Analysis::sqrtS() const {
00071 return handler().sqrtS();
00072 }
00073
00074 const ParticlePair& Analysis::beams() const {
00075 return handler().beams();
00076 }
00077
00078 const PdgIdPair Analysis::beamIds() const {
00079 return handler().beamIds();
00080 }
00081
00082
00083 const string Analysis::histoDir() const {
00084
00085 string path = "/" + name();
00086 if (handler().runName().length() > 0) {
00087 path = "/" + handler().runName() + path;
00088 }
00089 while (find_first(path, "//")) {
00090 replace_all(path, "//", "/");
00091 }
00092 return path;
00093 }
00094
00095
00096 const string Analysis::histoPath(const string& hname) const {
00097 const string path = histoDir() + "/" + hname;
00098 return path;
00099 }
00100
00101
00102 Log& Analysis::getLog() const {
00103 string logname = "Rivet.Analysis." + name();
00104 return Log::getLog(logname);
00105 }
00106
00107
00108 size_t Analysis::numEvents() const {
00109 return handler().numEvents();
00110 }
00111
00112
00113 double Analysis::sumOfWeights() const {
00114 return handler().sumOfWeights();
00115 }
00116
00117
00118
00119
00120
00121 bool Analysis::isCompatible(const ParticlePair& beams) const {
00122 return isCompatible(beams.first.pdgId(), beams.second.pdgId(),
00123 beams.first.energy(), beams.second.energy());
00124 }
00125
00126
00127 bool Analysis::isCompatible(PdgId beam1, PdgId beam2, double e1, double e2) const {
00128 PdgIdPair beams(beam1, beam2);
00129 pair<double,double> energies(e1, e2);
00130 return isCompatible(beams, energies);
00131 }
00132
00133
00134 bool Analysis::isCompatible(const PdgIdPair& beams, const pair<double,double>& energies) const {
00135
00136 bool beamIdsOk = false;
00137 foreach (const PdgIdPair& bp, requiredBeams()) {
00138 if (compatible(beams, bp)) {
00139 beamIdsOk = true;
00140 break;
00141 }
00142 }
00143 if (!beamIdsOk) return false;
00144
00145
00146 bool beamEnergiesOk = requiredEnergies().size()>0 ? false : true;
00147 typedef pair<double,double> DoublePair;
00148 foreach (const DoublePair& ep, requiredEnergies()) {
00149 if ((fuzzyEquals(ep.first, energies.first, 0.01) && fuzzyEquals(ep.second, energies.second, 0.01)) ||
00150 (fuzzyEquals(ep.first, energies.second, 0.01) && fuzzyEquals(ep.second, energies.first, 0.01))) {
00151 beamEnergiesOk = true;
00152 break;
00153 }
00154 }
00155 return beamEnergiesOk;
00156
00157
00158
00159 }
00160
00161
00162
00163
00164
00165 Analysis& Analysis::setCrossSection(double xs) {
00166 _crossSection = xs;
00167 _gotCrossSection = true;
00168 return *this;
00169 }
00170
00171 double Analysis::crossSection() const {
00172 if (!_gotCrossSection || std::isnan(_crossSection)) {
00173 string errMsg = "You did not set the cross section for the analysis " + name();
00174 throw Error(errMsg);
00175 }
00176 return _crossSection;
00177 }
00178
00179 double Analysis::crossSectionPerEvent() const {
00180 const double sumW = sumOfWeights();
00181 assert(sumW > 0);
00182 return _crossSection / sumW;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 void Analysis::_cacheBinEdges() const {
00192 _cacheXAxisData();
00193 if (_histBinEdges.empty()) {
00194 MSG_TRACE("Getting histo bin edges from AIDA for paper " << name());
00195 _histBinEdges = getBinEdges(_dpsData);
00196 }
00197 }
00198
00199
00200 void Analysis::_cacheXAxisData() const {
00201 if (_dpsData.empty()) {
00202 MSG_TRACE("Getting DPS x-axis data from AIDA for paper " << name());
00203 _dpsData = getDPSXValsErrs(name());
00204 }
00205 }
00206
00207
00208 const BinEdges& Analysis::binEdges(const string& hname) const {
00209 _cacheBinEdges();
00210 MSG_TRACE("Using histo bin edges for " << name() << ":" << hname);
00211 const BinEdges& edges = _histBinEdges.find(hname)->second;
00212 if (getLog().isActive(Log::TRACE)) {
00213 stringstream edges_ss;
00214 foreach (const double be, edges) {
00215 edges_ss << " " << be;
00216 }
00217 MSG_TRACE("Edges:" << edges_ss.str());
00218 }
00219 return edges;
00220 }
00221
00222
00223 const BinEdges& Analysis::binEdges(size_t datasetId, size_t xAxisId, size_t yAxisId) const {
00224 const string hname = makeAxisCode(datasetId, xAxisId, yAxisId);
00225 return binEdges(hname);
00226 }
00227
00228
00229 BinEdges Analysis::logBinEdges(size_t nbins, double lower, double upper) {
00230 assert(lower>0.0);
00231 assert(upper>lower);
00232 double loglower=log10(lower);
00233 double logupper=log10(upper);
00234 vector<double> binedges;
00235 double stepwidth=(logupper-loglower)/double(nbins);
00236 for (size_t i=0; i<=nbins; ++i) {
00237 binedges.push_back(pow(10.0, loglower+double(i)*stepwidth));
00238 }
00239 return binedges;
00240 }
00241
00242 IHistogram1D* Analysis::bookHistogram1D(size_t datasetId, size_t xAxisId,
00243 size_t yAxisId, const string& title,
00244 const string& xtitle, const string& ytitle)
00245 {
00246 const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00247 return bookHistogram1D(axisCode, title, xtitle, ytitle);
00248 }
00249
00250
00251 IHistogram1D* Analysis::bookHistogram1D(const string& hname, const string& title,
00252 const string& xtitle, const string& ytitle)
00253 {
00254
00255 const BinEdges edges = binEdges(hname);
00256 _makeHistoDir();
00257 const string path = histoPath(hname);
00258 IHistogram1D* hist = histogramFactory().createHistogram1D(path, title, edges);
00259 MSG_TRACE("Made histogram " << hname << " for " << name());
00260 hist->setXTitle(xtitle);
00261 hist->setYTitle(ytitle);
00262 return hist;
00263 }
00264
00265
00266 IHistogram1D* Analysis::bookHistogram1D(const string& hname,
00267 size_t nbins, double lower, double upper,
00268 const string& title,
00269 const string& xtitle, const string& ytitle) {
00270 _makeHistoDir();
00271 const string path = histoPath(hname);
00272 IHistogram1D* hist = histogramFactory().createHistogram1D(path, title, nbins, lower, upper);
00273 MSG_TRACE("Made histogram " << hname << " for " << name());
00274 hist->setXTitle(xtitle);
00275 hist->setYTitle(ytitle);
00276 return hist;
00277 }
00278
00279
00280 IHistogram1D* Analysis::bookHistogram1D(const string& hname,
00281 const vector<double>& binedges,
00282 const string& title,
00283 const string& xtitle, const string& ytitle) {
00284 _makeHistoDir();
00285 const string path = histoPath(hname);
00286 IHistogram1D* hist = histogramFactory().createHistogram1D(path, title, binedges);
00287 MSG_TRACE("Made histogram " << hname << " for " << name());
00288 hist->setXTitle(xtitle);
00289 hist->setYTitle(ytitle);
00290 return hist;
00291 }
00292
00293 IHistogram2D*
00294 Analysis::bookHistogram2D(const string& hname,
00295 size_t nxbins, double xlower, double xupper,
00296 size_t nybins, double ylower, double yupper,
00297 const string& title, const string& xtitle,
00298 const string& ytitle, const string& ztitle) {
00299 _makeHistoDir();
00300 const string path = histoPath(hname);
00301 IHistogram2D* hist =
00302 histogramFactory().createHistogram2D(path, title, nxbins, xlower, xupper,
00303 nybins, ylower, yupper);
00304 MSG_TRACE("Made 2D histogram " << hname << " for " << name());
00305 hist->setXTitle(xtitle);
00306 hist->setYTitle(ytitle);
00307 hist->setZTitle(ztitle);
00308 return hist;
00309 }
00310
00311
00312 IHistogram2D*
00313 Analysis::bookHistogram2D(const string& hname,
00314 const vector<double>& xbinedges,
00315 const vector<double>& ybinedges,
00316 const string& title, const string& xtitle,
00317 const string& ytitle, const string& ztitle) {
00318 _makeHistoDir();
00319 const string path = histoPath(hname);
00320 IHistogram2D* hist =
00321 histogramFactory().createHistogram2D(path, title, xbinedges, ybinedges);
00322 MSG_TRACE("Made 2D histogram " << hname << " for " << name());
00323 hist->setXTitle(xtitle);
00324 hist->setYTitle(ytitle);
00325 hist->setZTitle(ztitle);
00326 return hist;
00327 }
00328
00329
00330
00331
00332
00333 IProfile1D* Analysis::bookProfile1D(size_t datasetId, size_t xAxisId,
00334 size_t yAxisId, const string& title,
00335 const string& xtitle, const string& ytitle) {
00336 const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00337 return bookProfile1D(axisCode, title, xtitle, ytitle);
00338 }
00339
00340
00341 IProfile1D* Analysis::bookProfile1D(const string& hname, const string& title,
00342 const string& xtitle, const string& ytitle)
00343 {
00344
00345 const BinEdges edges = binEdges(hname);
00346 _makeHistoDir();
00347 const string path = histoPath(hname);
00348 IProfile1D* prof = histogramFactory().createProfile1D(path, title, edges);
00349 MSG_TRACE("Made profile histogram " << hname << " for " << name());
00350 prof->setXTitle(xtitle);
00351 prof->setYTitle(ytitle);
00352 return prof;
00353 }
00354
00355
00356 IProfile1D* Analysis::bookProfile1D(const string& hname,
00357 size_t nbins, double lower, double upper,
00358 const string& title,
00359 const string& xtitle, const string& ytitle) {
00360 _makeHistoDir();
00361 const string path = histoPath(hname);
00362 IProfile1D* prof = histogramFactory().createProfile1D(path, title, nbins, lower, upper);
00363 MSG_TRACE("Made profile histogram " << hname << " for " << name());
00364 prof->setXTitle(xtitle);
00365 prof->setYTitle(ytitle);
00366 return prof;
00367 }
00368
00369
00370 IProfile1D* Analysis::bookProfile1D(const string& hname,
00371 const vector<double>& binedges,
00372 const string& title,
00373 const string& xtitle, const string& ytitle) {
00374 _makeHistoDir();
00375 const string path = histoPath(hname);
00376 IProfile1D* prof = histogramFactory().createProfile1D(path, title, binedges);
00377 MSG_TRACE("Made profile histogram " << hname << " for " << name());
00378 prof->setXTitle(xtitle);
00379 prof->setYTitle(ytitle);
00380 return prof;
00381 }
00382
00383
00384
00385
00386
00387
00388 IDataPointSet* Analysis::bookDataPointSet(const string& hname, const string& title,
00389 const string& xtitle, const string& ytitle) {
00390 _makeHistoDir();
00391 const string path = histoPath(hname);
00392 IDataPointSet* dps = datapointsetFactory().create(path, title, 2);
00393 MSG_TRACE("Made data point set " << hname << " for " << name());
00394 dps->setXTitle(xtitle);
00395 dps->setYTitle(ytitle);
00396 return dps;
00397 }
00398
00399
00400 IDataPointSet* Analysis::bookDataPointSet(const string& hname,
00401 size_t npts, double lower, double upper,
00402 const string& title,
00403 const string& xtitle, const string& ytitle) {
00404 IDataPointSet* dps = bookDataPointSet(hname, title, xtitle, ytitle);
00405 for (size_t pt = 0; pt < npts; ++pt) {
00406 const double binwidth = (upper-lower)/npts;
00407 const double bincentre = lower + (pt + 0.5) * binwidth;
00408 dps->addPoint();
00409 IMeasurement* meas = dps->point(pt)->coordinate(0);
00410 meas->setValue(bincentre);
00411 meas->setErrorPlus(binwidth/2.0);
00412 meas->setErrorMinus(binwidth/2.0);
00413 }
00414 return dps;
00415 }
00416
00417
00418 IDataPointSet* Analysis::bookDataPointSet(size_t datasetId, size_t xAxisId,
00419 size_t yAxisId, const string& title,
00420 const string& xtitle, const string& ytitle) {
00421
00422 _cacheXAxisData();
00423
00424 const string axisCode = makeAxisCode(datasetId, xAxisId, yAxisId);
00425
00426 MSG_TRACE("Using DPS x-positions for " << name() << ":" << axisCode);
00427 IDataPointSet* dps = bookDataPointSet(axisCode, title, xtitle, ytitle);
00428 const vector<DPSXPoint> xpts = _dpsData.find(axisCode)->second;
00429 for (size_t pt = 0; pt < xpts.size(); ++pt) {
00430 dps->addPoint();
00431 IMeasurement* meas = dps->point(pt)->coordinate(0);
00432 meas->setValue(xpts[pt].val);
00433 meas->setErrorPlus(xpts[pt].errplus);
00434 meas->setErrorMinus(xpts[pt].errminus);
00435 }
00436 MSG_TRACE("Made DPS " << axisCode << " for " << name());
00437 return dps;
00438 }
00439
00440
00441
00442
00443
00444 void Analysis::_makeHistoDir() {
00445 if (!_madeHistoDir) {
00446 if (! name().empty()) {
00447
00448
00449
00450
00451
00452
00453 tree().mkdirs(histoDir());
00454 }
00455 _madeHistoDir = true;
00456 }
00457 }
00458
00459
00460 void Analysis::normalize(AIDA::IHistogram1D*& histo, double norm) {
00461 if (!histo) {
00462 MSG_ERROR("Failed to normalize histo=NULL in analysis "
00463 << name() << " (norm=" << norm << ")");
00464 return;
00465 }
00466 const string hpath = tree().findPath(dynamic_cast<const AIDA::IManagedObject&>(*histo));
00467 MSG_TRACE("Normalizing histo " << hpath << " to " << norm);
00468
00469 double oldintg = 0.0;
00470 int nBins = histo->axis().bins();
00471 for (int iBin = 0; iBin != nBins; ++iBin) {
00472
00473 oldintg += histo->binHeight(iBin);
00474 }
00475 if (oldintg == 0.0) {
00476 MSG_WARNING("Histo " << hpath << " has null integral during normalization");
00477 return;
00478 }
00479
00480
00481 scale(histo, norm/oldintg);
00482 }
00483
00484
00485 void Analysis::scale(AIDA::IHistogram1D*& histo, double scale) {
00486 if (!histo) {
00487 MSG_ERROR("Failed to scale histo=NULL in analysis "
00488 << name() << " (scale=" << scale << ")");
00489 return;
00490 }
00491 const string hpath = tree().findPath(dynamic_cast<const AIDA::IManagedObject&>(*histo));
00492 MSG_TRACE("Scaling histo " << hpath);
00493
00494 vector<double> x, y, ex, ey;
00495 for (size_t i = 0, N = histo->axis().bins(); i < N; ++i) {
00496 x.push_back(0.5 * (histo->axis().binLowerEdge(i) + histo->axis().binUpperEdge(i)));
00497 ex.push_back(histo->axis().binWidth(i)*0.5);
00498
00499
00500
00501 y.push_back(histo->binHeight(i)*scale/histo->axis().binWidth(i));
00502
00503
00504
00505 ey.push_back(histo->binError(i)*scale/histo->axis().binWidth(i));
00506 }
00507
00508 string title = histo->title();
00509 string xtitle = histo->xtitle();
00510 string ytitle = histo->ytitle();
00511
00512 tree().mkdir("/tmpnormalize");
00513 tree().mv(hpath, "/tmpnormalize");
00514
00515 AIDA::IDataPointSet* dps = datapointsetFactory().createXY(hpath, title, x, y, ex, ey);
00516 dps->setXTitle(xtitle);
00517 dps->setYTitle(ytitle);
00518
00519 tree().rm(tree().findPath(dynamic_cast<AIDA::IManagedObject&>(*histo)));
00520 tree().rmdir("/tmpnormalize");
00521
00522
00523 histo = 0;
00524 }
00525
00526
00527 void Analysis::normalize(AIDA::IHistogram2D*& histo, double norm) {
00528 if (!histo) {
00529 MSG_ERROR("Failed to normalize histo=NULL in analysis "
00530 << name() << " (norm=" << norm << ")");
00531 return;
00532 }
00533 const string hpath = tree().findPath(dynamic_cast<const AIDA::IManagedObject&>(*histo));
00534 MSG_TRACE("Normalizing histo " << hpath << " to " << norm);
00535
00536 double oldintg = 0.0;
00537 int nxBins = histo->xAxis().bins();
00538 int nyBins = histo->yAxis().bins();
00539 for (int ixBin = 0; ixBin != nxBins; ++ixBin)
00540 for (int iyBin = 0; iyBin != nyBins; ++iyBin) {
00541
00542
00543 oldintg += histo->binHeight(ixBin, iyBin);
00544 }
00545 if (oldintg == 0.0) {
00546 MSG_WARNING("Histo " << hpath << " has null integral during normalization");
00547 return;
00548 }
00549
00550
00551 scale(histo, norm/oldintg);
00552 }
00553
00554
00555 void Analysis::scale(AIDA::IHistogram2D*& histo, double scale) {
00556 if (!histo) {
00557 MSG_ERROR("Failed to scale histo=NULL in analysis "
00558 << name() << " (scale=" << scale << ")");
00559 return;
00560 }
00561 const string hpath =
00562 tree().findPath(dynamic_cast<const AIDA::IManagedObject&>(*histo));
00563 MSG_TRACE("Scaling histo " << hpath);
00564
00565 vector<double> x, y, z, ex, ey, ez;
00566 for (size_t ix = 0, Nx = histo->xAxis().bins(); ix < Nx; ++ix)
00567 for (size_t iy = 0, Ny = histo->yAxis().bins(); iy < Ny; ++iy) {
00568 x.push_back(0.5 * (histo->xAxis().binLowerEdge(ix) +
00569 histo->xAxis().binUpperEdge(ix)));
00570 ex.push_back(histo->xAxis().binWidth(ix)*0.5);
00571 y.push_back(0.5 * (histo->yAxis().binLowerEdge(iy) +
00572 histo->yAxis().binUpperEdge(iy)));
00573 ey.push_back(histo->yAxis().binWidth(iy)*0.5);
00574
00575
00576
00577 z.push_back(histo->binHeight(ix, iy)*scale/
00578 (histo->xAxis().binWidth(ix)*histo->yAxis().binWidth(iy)));
00579
00580
00581 ez.push_back(histo->binError(ix, iy)*scale/
00582 (histo->xAxis().binWidth(ix)*histo->yAxis().binWidth(iy)));
00583 }
00584
00585 string title = histo->title();
00586 string xtitle = histo->xtitle();
00587 string ytitle = histo->ytitle();
00588 string ztitle = histo->ztitle();
00589
00590 tree().mkdir("/tmpnormalize");
00591 tree().mv(hpath, "/tmpnormalize");
00592
00593 AIDA::IDataPointSet* dps =
00594 datapointsetFactory().createXYZ(hpath, title, x, y, z, ex, ey, ez);
00595 dps->setXTitle(xtitle);
00596 dps->setYTitle(ytitle);
00597 dps->setZTitle(ztitle);
00598
00599 tree().rm(tree().findPath(dynamic_cast<AIDA::IManagedObject&>(*histo)));
00600 tree().rmdir("/tmpnormalize");
00601
00602
00603 histo = 0;
00604 }
00605
00606
00607 }