00001 #include "cafe/StatSample.hpp"
00002 #include <string>
00003
00004 using namespace std ;
00005
00006 namespace cafe {
00007
00008 StatSample::StatSample(const string& sample) : _name(sample)
00009 {
00010 _events.push_back(new StatSelection("Initial",0)) ;
00011 _weight = new StatWeight("Efficiency correction") ;
00012 }
00013
00014 StatSample::~StatSample() {
00015 }
00016
00017 void StatSample::AddTags(const vector<string>& tags) {
00018 for (vector<string>::const_iterator it = tags.begin() ;
00019 it != tags.end(); it++) {
00020 string s = *it ;
00021 while (s.size() > 0 && s.substr(0,1) == " ") s.erase(0,1) ;
00022 while (s.size() > 0 && s.substr(s.size()-1,1) == " ") s.erase(s.size()-1,1) ;
00023 if (s.size() ==0 ) continue ;
00024 _tags.push_back(s) ;
00025 }
00026 return ;
00027 }
00028
00029
00030 void StatSample::AddAndTags(const vector<string>& tags) {
00031 for (vector<string>::const_iterator it = tags.begin() ;
00032 it != tags.end(); it++) {
00033 string s = *it ;
00034 while (s.size() > 0 && s.substr(0,1) == " ") s.erase(0,1) ;
00035 while (s.size() > 0 && s.substr(s.size()-1,1) == " ") s.erase(s.size()-1,1) ;
00036 if (s.size() ==0 ) continue ;
00037 _tags_and.push_back(s) ;
00038 }
00039 return ;
00040 }
00041
00042 unsigned long StatSample::add(cafe::Event* event, const std::string& name) {
00043 if (!event) {
00044 cerr << "StatSample ERROR!. Event pointer == 0." << endl ;
00045 return 0;
00046 }
00047
00048 if (!tagged(event)) return 0 ;
00049
00050 vector<StatSelection*>::const_iterator it = _events.begin();
00051 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00052
00053 if (it == _events.end()) {
00054 _events.push_back(new StatSelection(name)) ;
00055 it = _events.end()-1 ;
00056 }
00057
00058 return (*it)->addEvent() ;
00059 }
00060
00061
00062
00063 double StatSample::applyWeight(cafe::Event* event, const std::string& name,
00064 double weight, double weight_pos, double weight_neg) {
00065 if (!event) {
00066 cerr << "StatSample ERROR!. Event pointer == 0." << endl ;
00067 return 0;
00068 }
00069
00070 if (!tagged(event)) return 0.0 ;
00071
00072 vector<StatSelection*>::const_iterator it = _events.begin();
00073 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00074
00075 if (it == _events.end()) {
00076 _events.push_back(new StatWeight(name)) ;
00077 it = _events.end()-1 ;
00078 }
00079
00080
00081 _weight->applyWeight(weight, weight_pos, weight_neg) ;
00082
00083
00084 return dynamic_cast<StatWeight*>(*it) ->applyWeight(weight, weight_pos, weight_neg) ;
00085 }
00086
00087 double StatSample::calculateGlobalWeight(cafe::Event* event) {
00088
00089 if (!event) {
00090 cerr << "StatSample ERROR!. Event pointer == 0." << endl ;
00091 return 0;
00092 }
00093
00094
00095 if (!tagged(event)) return -1.0 ;
00096
00097 vector<StatSelection*>::const_iterator it = _events.begin();
00098 for (; it != _events.end(); it++) if ((*it)->name() == _weight->name() ) break ;
00099
00100
00101
00102 if (it == _events.end()) {
00103 _events.push_back(new StatWeight(_weight->name())) ;
00104 it = _events.end()-1 ;
00105 }
00106
00107
00108
00109 for(vector<StatSelection*>::const_iterator jt = _events.begin();
00110 jt != it; jt++) {
00111 if ((*jt)->isWeight()) {
00112 StatWeight* w = dynamic_cast<StatWeight*>(*jt) ;
00113
00114
00115
00116
00117
00118 if (w->weight_average_pos() >= 0 || w->weight_average_neg() >= 0 ) {
00119 vector<pair<StatWeight*,StatWeight*> >::iterator wt = _syst.begin();
00120 for(; wt != _syst.end(); wt++)
00121 if (wt->first->name().find(w->name()) != string::npos) break ;
00122
00123 if(wt == _syst.end()) {
00124 _syst.push_back(pair<StatWeight*,StatWeight*>(new StatWeight(w->name()),
00125 new StatWeight(w->name()))) ;
00126 wt = _syst.end()-1 ;
00127 }
00128
00129 for(vector<StatSelection*>::const_iterator jtt = _events.begin();
00130 jtt != it; jtt++) {
00131 if ((*jtt)->isWeight()) {
00132 StatWeight* ww = dynamic_cast<StatWeight*>(*jtt) ;
00133 if (jtt == jt) {
00134 wt->first->applyWeight(ww->weight_pos()) ;
00135 wt->second->applyWeight(ww->weight_neg()) ;
00136 } else {
00137 wt->first->applyWeight(ww->weight()) ;
00138 wt->second->applyWeight(ww->weight()) ;
00139 }
00140 }
00141 }
00142 }
00143 }
00144 }
00145
00146 return (dynamic_cast<StatWeight*>(*it))->applyWeight(_weight->weight(),_weight->weight_pos(),_weight->weight_neg()) ;
00147 }
00148
00149
00150 unsigned long StatSample::nevents(unsigned int n ) const {
00151 if (n >= _events.size()) {
00152 cerr << "ERROR! StatSample \"" << _name << "\": selection number " << n
00153 << " greater than selection size " << _events.size() << endl ;
00154 exit(1) ;
00155 }
00156 return _events[n]->nevents() ;
00157 }
00158
00159
00160 unsigned long StatSample::nevents(const string& name) const {
00161
00162 vector<StatSelection*>::const_iterator it = _events.begin();
00163 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00164
00165 if (it == _events.end()) {
00166 cout << "cafe::StatSample: \"" << _name << "\": No weight with name \"" << name
00167 << "\" found in the Stat class" << endl ;
00168 return 0 ;
00169 }
00170 return (*it)->nevents() ;
00171 }
00172
00173 void StatSample::Clear() {
00174 for (vector<StatSelection*>::iterator it = _events.begin() ;
00175 it != _events.end(); it++)
00176 (*it)->Clear() ;
00177
00178 for (vector<pair<StatWeight*,StatWeight*> >::iterator it = _syst.begin() ;
00179 it != _syst.end(); it++) {
00180 it->first->Clear() ;
00181 it->second->Clear() ;
00182 }
00183
00184 _weight->Clear() ;
00185 return ;
00186 }
00187
00188 const StatWeight* StatSample::eventWeight(const std::string& name) const {
00189
00190 if (name == "global") return _weight ;
00191
00192 vector<StatSelection*>::const_iterator it = _events.begin();
00193 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00194
00195 if (it == _events.end()) {
00196 cout << "cafe::StatSample: \"" << _name << "\": No weight with name \"" << name
00197 << "\" found in the Stat class" << endl ;
00198 return 0 ;
00199 }
00200
00201 if (!(*it)->isWeight()) {
00202 cout << "cafe::StatSample: \"" << _name << "\": Selection with name \"" << name
00203 << "\" is not the event weight!" << endl ;
00204 return 0 ;
00205 }
00206 return dynamic_cast<StatWeight*> (*it) ;
00207 }
00208
00209 const StatWeight* StatSample::eventWeight(unsigned int n) const {
00210 if (n >= _events.size()) {
00211 cerr << "ERROR! StatSample: \"" << _name << "\": weight number " << n
00212 << " greater than selection size " << _events.size() << endl ;
00213 exit(1) ;
00214 }
00215 if (!_events[n]->isWeight()) {
00216 cout << "cafe::StatSample \"" << _name << "\": Selection with number \"" << n
00217 << "\" is not the event weight!" << endl ;
00218 return 0 ;
00219 }
00220 return dynamic_cast<StatWeight*> (_events[n]);
00221 }
00222
00223 const StatSelection* StatSample::eventSelection(unsigned int n) const {
00224 if (n >= _events.size()) {
00225 cerr << "ERROR! StatSample \"" << _name << "\": Selection number " << n
00226 << " greater than selection size " << _events.size() << endl ;
00227 exit(1) ;
00228 }
00229 return _events[n];
00230 }
00231
00232 const pair<StatWeight*,StatWeight*>& StatSample::systematics(unsigned int n) const {
00233 if (n >= _syst.size()) {
00234 cerr << "ERROR! StatSample \"" << _name << "\": Systematics number " << n
00235 << " greater than systematics size " << _syst.size() << endl ;
00236 exit(1) ;
00237 }
00238 return _syst[n];
00239 }
00240
00241
00242 const StatSelection* StatSample::eventSelection(const string& name) const {
00243
00244 vector<StatSelection*>::const_iterator it = _events.begin();
00245 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00246
00247 if (it == _events.end()) {
00248 cout << "cafe::StatSample \"" << _name << "\": No selection with name \"" << name
00249 << "\" found in the Stat class" << endl ;
00250 return 0 ;
00251 }
00252
00253 return (*it) ;
00254 }
00255
00256 double StatSample::eff(unsigned int n) const {
00257 if (n >= _events.size()) {
00258 cerr << "ERROR! StatSamplec\"" << _name << "\": Selection number " << n
00259 << " greater than selection size " << _events.size() << endl ;
00260 exit(1) ;
00261 }
00262
00263 if (_events[n]->isWeight()) return dynamic_cast<StatWeight*> (_events[n])->weight_average() ;
00264
00265 if ( n > 0)
00266 return ((double)_events[n]->nevents())/_events[n-1]->nevents() ;
00267
00268 return -1.0 ;
00269 }
00270
00271
00272 double StatSample::eff(const std::string& name) const {
00273
00274 vector<StatSelection*>::const_iterator it = _events.begin();
00275 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00276
00277 if (it == _events.end()) {
00278 cout << "cafe::StatSample \"" << _name << "\": No selection with name \"" << name
00279 << "\" found in the Stat class" << endl ;
00280 return 0 ;
00281 }
00282
00283 if (it == _events.begin()) return 0 ;
00284
00285 return ((double) (*it)->nevents())/(*(it-1))->nevents() ;
00286 }
00287
00288
00289 double StatSample::effErr(unsigned int n) const {
00290 if (n >= _events.size()) {
00291 cerr << "ERROR! StatSample \"" << _name << "\": Selection number " << n
00292 << " greater than selection size " << _events.size() << endl ;
00293 exit(1) ;
00294 }
00295
00296 if (_events[n]->isWeight()) return dynamic_cast<StatWeight*> (_events[n])->err() ;
00297
00298 if ( n >0)
00299 return _events[n]->err(*_events[n-1]) ;
00300
00301 return -1.0 ;
00302 }
00303
00304 double StatSample::effErr(const std::string& name) const {
00305
00306 vector<StatSelection*>::const_iterator it = _events.begin();
00307 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00308
00309 if (it == _events.end()) {
00310 cout << "cafe::StatSample \"" << _name << "\": No selection with name \"" << name
00311 << "\" found in the Stat class" << endl ;
00312 return 0 ;
00313 }
00314
00315 if (it == _events.begin()) return 0 ;
00316
00317 return (*it)->err(**(it-1)) ;
00318 }
00319
00320
00321 double StatSample::effGlob(unsigned int n) const {
00322 if (n >= _events.size()) {
00323 cerr << "ERROR! StatSample \"" << _name << "\": Selection number " << n
00324 << " greater than selection size " << _events.size() << endl ;
00325 exit(1) ;
00326 }
00327
00328 if ( _events.front()->nevents() == 0 ) return -1.0 ;
00329
00330 if (n == 0)
00331 return ((double)_events.back()->nevents())/_events.front()->nevents() ;
00332
00333 return ((double)_events[n]->nevents())/_events.front()->nevents() ;
00334 }
00335
00336
00337 double StatSample::effGlob(const std::string& name) const {
00338
00339 if ( _events.front()->nevents() == 0 ) return -1.0 ;
00340
00341 vector<StatSelection*>::const_iterator it = _events.begin();
00342 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00343
00344 if (it == _events.end()) {
00345 cout << "cafe::StatSample \"" << _name << "\": No selection with name \"" << name
00346 << "\" found in the Stat class" << endl ;
00347 return -1.0 ;
00348 }
00349
00350 if (it == _events.begin()) return -1.0 ;
00351
00352 return ((double) (*it)->nevents())/_events.front()->nevents() ;
00353 }
00354
00355
00356 double StatSample::effErrGlob(unsigned int n) const {
00357 if (n >= _events.size()) {
00358 cerr << "ERROR! StatSample \"" << _name << "\": Selection number " << n
00359 << " greater than selection size " << _events.size() << endl ;
00360 exit(1) ;
00361 }
00362
00363 if ( _events.front()->nevents() == 0) return -1.0 ;
00364
00365 if ( n == 0)
00366 return _events.back()->err(*_events.front());
00367
00368 return _events[n]->err(*_events.front());
00369 }
00370
00371 double StatSample::effErrGlob(const std::string& name) const {
00372
00373 if ( _events.front()->nevents() == 0 ) return -1.0 ;
00374
00375 vector<StatSelection*>::const_iterator it = _events.begin();
00376 for (; it != _events.end(); it++) if ((*it)->name() == name ) break ;
00377
00378 if (it == _events.end()) {
00379 cout << "cafe::StatSample \"" << _name << "\": No selection with name \"" << name
00380 << "\" found in the Stat class" << endl ;
00381 return -1.0 ;
00382 }
00383
00384 if (it == _events.begin()) return -1.0 ;
00385
00386 return (*it)->err(*_events.front());
00387 }
00388
00389 bool StatSample::compareNames(const StatSample& sample) const {
00390
00391 if (_events.size() != sample._events.size()) return false ;
00392
00393 for (unsigned int n = 0 ; n < _events.size() ; n++)
00394 if (_events[n]->name() != sample._events[n]->name() ) return false ;
00395
00396 return true ;
00397 }
00398
00399 double StatSample::correctedEff(const StatWeight* w) const {
00400 if(!w) {
00401 vector<StatSelection*>::const_iterator it = _events.begin();
00402 for (; it != _events.end(); it++) if ((*it)->name() == _weight->name() ) break ;
00403 if (it == _events.end()) {
00404 cout << "cafe::StatSample ERROR: The global weight processor is not used! Add cafe.Run: StatGWeight. "
00405 << "Will return non-corrected efficiency" << endl ;
00406 return effGlob() ;
00407 }
00408 w = dynamic_cast<StatWeight*>(*it) ;
00409 }
00410 return effGlob()*w->weight_average() ;
00411 }
00412
00413 double StatSample::correctedEffErr(const StatWeight* w) const {
00414 if(!w) w = _weight ;
00415 return sqrt(pow(w->weight_average()*effErrGlob(),2)
00416 + pow(effGlob()*w->err(),2)) ;
00417 }
00418
00419 double StatSample::totalsyst_pos() const {
00420 double w = _weight->weight_average() ;
00421 if (w<=0) return 0.0 ;
00422 double s = 0.0 ;
00423 for (std::vector<std::pair<StatWeight*,StatWeight*> >::const_iterator it = _syst.begin() ;
00424 it != _syst.end(); it++)
00425 s += pow(it->first->weight_average() / w - 1.0 , 2) ;
00426 return sqrt(s) ;
00427 }
00428
00429 double StatSample::totalsyst_neg() const {
00430 double w = _weight->weight_average() ;
00431 if (w<=0) return 0.0 ;
00432 double s = 0.0 ;
00433 for (std::vector<std::pair<StatWeight*,StatWeight*> >::const_iterator it = _syst.begin() ;
00434 it != _syst.end(); it++)
00435 s += pow(it->second->weight_average() / w - 1.0 , 2) ;
00436 return sqrt(s) ;
00437 }
00438
00439 bool StatSample::tagged(const cafe::Event* event) const {
00440
00441 if (_tags.size() == 0 && _tags_and.size() == 0 ) return true ;
00442
00443 for (vector<string>::const_iterator it = _tags_and.begin() ;
00444 it != _tags_and.end(); it++) {
00445 if (!event->hasTag(*it)) return false ;
00446 }
00447
00448 return _tags.size() == 0 || event->hasTag(_tags) ;
00449 }
00450
00451
00452 ostream& StatSample::HtmlTable(ostream& os) const {
00453
00454 os << "<TABLE BORDERCOLORDARK=\"996633\" BORDERCOLOR=\"CC9966\" BORDERCOLORLIGHT=\"FFCC99\" border=3 cellPadding=5 width=\"99%\">" << endl ;
00455 os << "<TBODY align=right>" << endl ;
00456
00457 os << "<TR>" << endl ;
00458 os << "<TH align=left>" << endl ;
00459 os << "SELECTION" ;
00460 os << " </TH>" << endl ;
00461 os << "<TH align=center colspan=3>" << endl ;
00462 os << name() << endl ;
00463 os << "</TH>" << endl ;
00464 os << "</TR>" << endl ;
00465
00466 bool color = false ;
00467
00468 for (unsigned int n = 0; n < size() ; n++) {
00469
00470 if (color) {
00471 os << "<TR BGCOLOR=#bfefff>" << endl ;
00472 color = !color ;
00473 } else {
00474 os << "<TR>" << endl ;
00475 color = !color ;
00476 }
00477
00478 os << "<TD align=left>" << endl ;
00479 os << eventSelection(n)->name() << endl ;
00480 os << "</TD>" << endl ;
00481
00482 os << "<TD TITLE=\"Number of events\">" << endl ;
00483 os << nevents(n) << endl ;
00484 if (n==0) {
00485 os << "<TD> </TD> <TD> </TD>" << endl ;
00486 continue ;
00487 }
00488
00489 if (eventSelection(n)->isWeight()) {
00490 if (eventSelection(n)->name() == eventWeight()->name())
00491 os << "</TD> <TD TITLE=\"Global event weight\">" << endl ;
00492 else
00493 os << "</TD> <TD TITLE=\"Average weight\">" << endl ;
00494 os << eff(n) << "±" << effErr(n)<< endl ;
00495 os << "</TD> <TD>  </TD>"<< endl ;
00496 continue ;
00497 }
00498
00499 os << "</TD><TD TITLE=\"Selection efficiency\">"<< endl ;
00500 os << 100.0*eff(n) << "±" << 100.0*effErr(n) << "%"
00501 << endl ;
00502 os << "</TD><TD TITLE=\"Global efficiency\">"<< endl ;
00503 os << 100.0*effGlob(n) << "±" << 100.0*effErrGlob(n) << "%"
00504 << endl ;
00505 os << "</TD>" << endl ;
00506 os << "</TR>" << endl ;
00507 }
00508
00509 if(eventWeight()->nevents() > 0) {
00510
00511 os << "<TR BGCOLOR=#FFCCCC>" << endl ;
00512 os << "<TD align=left>Corrected Efficiency</TD>" << endl ;
00513 os << "<TD TITLE=\"Number Of Events\">"<< endl ;
00514 os << nevents(size()-1) << endl ;
00515 os << "</TD> <TD>" << endl ;
00516 os << "</TD><TD TITLE=\"Global efficiency\">"<< endl ;
00517 os << 100.0*correctedEff() << "±"
00518 << 100.0*correctedEffErr()<< "%"
00519 << endl ;
00520 os << "</TD>"<< endl ;
00521 os << "</TR>" << endl ;
00522 }
00523 os << "</TBODY></TABLE>" << endl ;
00524
00525 return os ;
00526 }
00527
00528
00530 ostream& StatSample::print_tex (ostream& os, const string title) const {
00531
00532 os << "" << endl;
00533 os << "% Efficiency table %" << endl;
00534 os << "" << endl;
00535 os << "\\begin{table}[p]" << endl;
00536 os << "\\begin{center}" << endl;
00537 os << "\\begin{tabular}{lrrr}" << endl;
00538 os << " \\hline \\hline" << endl;
00539 os << " Selection & Events & Relative & Total \\\\ \\hline" << endl;
00540
00541 os << tex(eventSelection(0)->name()) << " & " ;
00542 os << nevents(0) << " & & \\\\ " << endl ;
00543
00544 for (unsigned int n = 1; n < size() ; n++) {
00545
00546 os << tex(eventSelection(n)->name()) << " & " ;
00547 os << nevents(n) << " & ";
00548
00549 if (eventSelection(n)->isWeight()) {
00550 os << " $\\mathit{ " << eff(n) << " \\pm "
00551 << effErr(n) << " }$ & " ;
00552 } else {
00553 os << " $ " << 100.0*eff(n) << " \\pm "
00554 << 100.0*effErr(n) << " ~\\% $ & " ;
00555 os << " $ " << 100.0*effGlob(n) << " \\pm "
00556 << 100.0*effErrGlob(n) << "~\\% $ " ;
00557 }
00558
00559 os << " \\\\ " << endl ;
00560 }
00561
00562 os << " \\hline " << endl;
00563 const StatWeight* w = eventWeight() ;
00564 if (w->nevents() > 0) {
00565 os << " Corrected efficiency & " ;
00566 os << nevents(size()-1) << " & ";
00567
00568 os << "& $" << 100.0*correctedEff()<< " \\pm "
00569 << 100.0*correctedEffErr() << "~\\% $ \\\\" ;
00570
00571 os << " \\hline"<< endl ;
00572 }
00573 os << " \\hline" << endl;
00574 os << " \\end{tabular}" << endl;
00575 os << " \\caption{" << title << " Sample " << name() << " }" << endl;
00576 os << " \\label{Table:" << title.c_str() << ":" << name() << "}" << endl;
00577 os << "\\end{center}" << endl;
00578 os << "\\end{table}" << endl;
00579 os << endl;
00580
00581 return os ;
00582 }
00583
00584
00585 ostream& StatSample::print_tex_syst (ostream& os) const {
00586
00587 if (_weight->weight_average() <= 0) return os;
00588
00589 os << "" << endl;
00590 os << "% Systematics table %" << endl;
00591 os << "" << endl;
00592 os << "\\begin{table}[p]" << endl;
00593 os << "\\begin{center}" << endl;
00594 os << "\\begin{tabular}{lrr}" << endl;
00595 os << " \\hline \\hline" << endl;
00596 os << " Systematics & Positive [\\%] & Negative [\\%] \\\\ \\hline" << endl;
00597
00598
00599 for (vector<pair<StatWeight*,StatWeight*> >::const_iterator jt = _syst.begin();
00600 jt != _syst.end() ; jt++) {
00601 os << tex(jt->first->name()) << " & " ;
00602 double pos = jt->first->weight_average() / _weight->weight_average() - 1.0 ;
00603 double neg = jt->second->weight_average() / _weight->weight_average() - 1.0 ;
00604 os << " $ " << 100.0*pos << " $ & $ " << 100.0*neg << " $ \\\\ " << endl ;
00605 }
00606
00607 os << " \\hline " << endl;
00608
00609 os << " Total : & $ " << 100.0*totalsyst_pos() << " $ & $ " ;
00610 os << -100.0*totalsyst_neg() << " $ \\\\ " ;
00611 os << " \\hline"<< endl ;
00612
00613 os << " \\hline" << endl;
00614 os << " \\end{tabular}" << endl;
00615 os << " \\caption{ Systematics for the sample " << name() << " }" << endl;
00616 os << " \\label{Table:syst:" << name() << "}" << endl;
00617 os << "\\end{center}" << endl;
00618 os << "\\end{table}" << endl;
00619 os << endl;
00620
00621 return os ;
00622 }
00623
00624 std::string StatSample::tex(const std::string& init) {
00625 string name ;
00626 for (unsigned int i=0; i<init.size(); i++) {
00627 string ch ;
00628 if (init.substr(i,1) == "_") ch = "\\_" ;
00629 else if (init.substr(i,2) == ">=") {
00630 ch = "$\\geq$" ;
00631 i++ ;
00632 }
00633 else if (init.substr(i,2) == "<=") {
00634 ch = "$\\leq$" ;
00635 i++ ;
00636 }
00637 else if (init.substr(i,1) == "<") ch = "$<$" ;
00638 else if (init.substr(i,1) == ">") ch = "$>$" ;
00639 else ch = init.substr(i,1) ;
00640 name = name + ch ;
00641 }
00642 return name ;
00643 }
00644
00645 }
00646
00647 ClassImp(cafe::StatSample);