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