26 #include <boost/tokenizer.hpp>
33 TPRegexp
metacharacters(
"[\\^\\$\\.\\*\\+\\?\\|\\(\\)\\{\\}\\[\\]]");
38 typedef std::vector<edm::ParameterSet> VPSet;
39 typedef std::vector<std::string>
vstring;
40 typedef boost::escaped_list_separator<char> elsc;
42 elsc commonEscapes(
"\\",
" \t",
"\'");
47 vstring effCmds = pset.
getParameter<vstring>(
"efficiency");
48 for ( vstring::const_iterator effCmd = effCmds.begin();
49 effCmd != effCmds.end(); ++effCmd )
51 if ( effCmd->empty() )
continue;
53 boost::tokenizer<elsc> tokens(*effCmd, commonEscapes);
56 for(boost::tokenizer<elsc>::const_iterator iToken = tokens.begin();
57 iToken != tokens.end(); ++iToken) {
58 if ( iToken->empty() )
continue;
59 args.push_back(*iToken);
62 if ( args.size() < 4 ) {
63 LogInfo(
"DQMGenericClient") <<
"Wrong input to effCmds\n";
74 const string typeName = args.size() == 4 ?
"eff" : args[4];
75 if ( typeName ==
"eff" ) opt.
type = 1;
76 else if ( typeName ==
"fake" ) opt.
type = 2;
79 efficOptions_.push_back(opt);
83 for ( VPSet::const_iterator
efficSet = efficSets.begin();
87 opt.
name =
efficSet->getUntrackedParameter<
string>(
"name");
93 const string typeName =
efficSet->getUntrackedParameter<
string>(
"typeName",
"eff");
94 if ( typeName ==
"eff" ) opt.
type = 1;
95 else if ( typeName ==
"fake" ) opt.
type = 2;
98 efficOptions_.push_back(opt);
103 for ( vstring::const_iterator profileCmd = profileCmds.begin();
104 profileCmd != profileCmds.end(); ++profileCmd )
106 if ( profileCmd->empty() )
continue;
108 boost::tokenizer<elsc> tokens(*profileCmd, commonEscapes);
111 for(boost::tokenizer<elsc>::const_iterator iToken = tokens.begin();
112 iToken != tokens.end(); ++iToken) {
113 if ( iToken->empty() )
continue;
114 args.push_back(*iToken);
117 if ( args.size() < 4 ) {
118 LogInfo(
"DQMGenericClient") <<
"Wrong input to profileCmds\n";
129 const string typeName = args.size() == 4 ?
"eff" : args[4];
130 if ( typeName ==
"eff" ) opt.
type = 1;
131 else if ( typeName ==
"fake" ) opt.
type = 2;
134 efficOptions_.push_back(opt);
138 for ( VPSet::const_iterator profileSet = profileSets.begin();
139 profileSet != profileSets.end(); ++profileSet )
142 opt.
name = profileSet->getUntrackedParameter<
string>(
"name");
143 opt.
title = profileSet->getUntrackedParameter<
string>(
"title");
144 opt.
numerator = profileSet->getUntrackedParameter<
string>(
"numerator");
145 opt.
denominator = profileSet->getUntrackedParameter<
string>(
"denominator");
148 const string typeName = profileSet->getUntrackedParameter<
string>(
"typeName",
"eff");
149 if ( typeName ==
"eff" ) opt.
type = 1;
150 else if ( typeName ==
"fake" ) opt.
type = 2;
153 efficOptions_.push_back(opt);
157 vstring resCmds = pset.
getParameter<vstring>(
"resolution");
158 for ( vstring::const_iterator resCmd = resCmds.begin();
159 resCmd != resCmds.end(); ++resCmd )
161 if ( resCmd->empty() )
continue;
162 boost::tokenizer<elsc> tokens(*resCmd, commonEscapes);
165 for(boost::tokenizer<elsc>::const_iterator iToken = tokens.begin();
166 iToken != tokens.end(); ++iToken) {
167 if ( iToken->empty() )
continue;
168 args.push_back(*iToken);
171 if ( args.size() != 3 ) {
172 LogInfo(
"DQMGenericClient") <<
"Wrong input to resCmds\n";
181 resolOptions_.push_back(opt);
185 for ( VPSet::const_iterator resolSet = resolSets.begin();
186 resolSet != resolSets.end(); ++resolSet )
189 opt.
namePrefix = resolSet->getUntrackedParameter<
string>(
"namePrefix");
190 opt.
titlePrefix = resolSet->getUntrackedParameter<
string>(
"titlePrefix");
191 opt.
srcName = resolSet->getUntrackedParameter<
string>(
"srcName");
193 resolOptions_.push_back(opt);
198 for ( vstring::const_iterator normCmd = normCmds.begin();
199 normCmd != normCmds.end(); ++normCmd )
201 if ( normCmd->empty() )
continue;
202 boost::tokenizer<elsc> tokens(*normCmd, commonEscapes);
205 for(boost::tokenizer<elsc>::const_iterator iToken = tokens.begin();
206 iToken != tokens.end(); ++iToken) {
207 if ( iToken->empty() )
continue;
208 args.push_back(*iToken);
211 if ( args.empty()
or args.size() > 2 ) {
212 LogInfo(
"DQMGenericClient") <<
"Wrong input to normCmds\n";
218 opt.
normHistName = args.size() == 2 ? args[1] : args[0];
220 normOptions_.push_back(opt);
224 for ( VPSet::const_iterator normSet = normSets.begin();
225 normSet != normSets.end(); ++normSet )
228 opt.
name = normSet->getUntrackedParameter<
string>(
"name");
229 opt.
normHistName = normSet->getUntrackedParameter<
string>(
"normalizedTo", opt.
name);
231 normOptions_.push_back(opt);
236 for ( vstring::const_iterator cdCmd = cdCmds.begin();
237 cdCmd != cdCmds.end(); ++cdCmd )
239 if ( cdCmd->empty() )
continue;
240 boost::tokenizer<elsc> tokens(*cdCmd, commonEscapes);
243 for(boost::tokenizer<elsc>::const_iterator iToken = tokens.begin();
244 iToken != tokens.end(); ++iToken) {
245 if ( iToken->empty() )
continue;
246 args.push_back(*iToken);
249 if ( args.size() != 1 ) {
250 LogInfo(
"DQMGenericClient") <<
"Wrong input to cdCmds\n";
257 cdOptions_.push_back(opt);
261 for ( VPSet::const_iterator cdSet = cdSets.begin();
262 cdSet != cdSets.end(); ++cdSet )
265 opt.
name = cdSet->getUntrackedParameter<
string>(
"name");
267 cdOptions_.push_back(opt);
274 isWildcardUsed_ =
false;
279 typedef vector<string>
vstring;
295 LogInfo(
"DQMGenericClient") <<
"Cannot create DQMStore instance\n";
300 set<string> subDirSet;
302 for(vstring::const_iterator iSubDir = subDirs_.begin();
303 iSubDir != subDirs_.end(); ++iSubDir) {
304 string subDir = *iSubDir;
306 if ( subDir[subDir.size()-1] ==
'/' ) subDir.erase(subDir.size()-1);
309 isWildcardUsed_ =
true;
312 const string searchPath = subDir.substr(0, shiftPos);
313 const string pattern = subDir.substr(shiftPos + 1, subDir.length());
316 findAllSubdirectories (searchPath, &subDirSet, pattern);
320 subDirSet.insert(subDir);
324 for(set<string>::const_iterator iSubDir = subDirSet.begin();
325 iSubDir != subDirSet.end(); ++iSubDir) {
326 const string&
dirName = *iSubDir;
328 for ( vector<EfficOption>::const_iterator efficOption = efficOptions_.begin();
329 efficOption != efficOptions_.end(); ++efficOption )
331 computeEfficiency(dirName, efficOption->name, efficOption->title,
332 efficOption->numerator, efficOption->denominator,
333 efficOption->type, efficOption->isProfile);
336 for ( vector<ResolOption>::const_iterator resolOption = resolOptions_.begin();
337 resolOption != resolOptions_.end(); ++resolOption )
339 computeResolution(dirName, resolOption->namePrefix, resolOption->titlePrefix, resolOption->srcName);
342 for ( vector<NormOption>::const_iterator normOption = normOptions_.begin();
343 normOption != normOptions_.end(); ++normOption )
345 normalizeToEntries(dirName, normOption->name, normOption->normHistName);
348 for ( vector<CDOption>::const_iterator cdOption = cdOptions_.begin();
349 cdOption != cdOptions_.end(); ++cdOption )
351 makeCumulativeDist(dirName, cdOption->name);
357 if ( ! outputFileName_.empty() ) theDQM->save(outputFileName_);
367 LogTrace (
"DQMGenericClient") <<
"inside of DQMGenericClient::endJob()"
373 const string& recoMEName,
const string& simMEName,
const int type,
const bool makeProfile)
375 if ( ! theDQM->dirExists(startDir) ) {
376 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
377 LogInfo(
"DQMGenericClient") <<
"computeEfficiency() : "
378 <<
"Cannot find sub-directory " << startDir << endl;
385 ME* simME = theDQM->get(startDir+
"/"+simMEName);
386 ME* recoME = theDQM->get(startDir+
"/"+recoMEName);
389 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
390 LogInfo(
"DQMGenericClient") <<
"computeEfficiency() : "
391 <<
"No sim-ME '" << simMEName <<
"' found\n";
397 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
398 LogInfo(
"DQMGenericClient") <<
"computeEfficiency() : "
399 <<
"No reco-ME '" << recoMEName <<
"' found\n";
406 TH1* hSim = simME ->getTH1();
407 TH1* hReco = recoME->getTH1();
409 if ( !hSim || !hReco ) {
410 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
411 LogInfo(
"DQMGenericClient") <<
"computeEfficiency() : "
412 <<
"Cannot create TH1 from ME\n";
417 string efficDir = startDir;
418 string newEfficMEName = efficMEName;
420 if ( string::npos != (shiftPos = efficMEName.rfind(
'/')) ) {
421 efficDir +=
"/"+efficMEName.substr(0, shiftPos);
422 newEfficMEName.erase(0, shiftPos+1);
424 theDQM->setCurrentFolder(efficDir);
427 TProfile * efficHist = (hReco->GetXaxis()->GetXbins()->GetSize()==0) ?
428 new TProfile(newEfficMEName.c_str(), efficMETitle.c_str(),
429 hReco->GetXaxis()->GetNbins(),
430 hReco->GetXaxis()->GetXmin(),
431 hReco->GetXaxis()->GetXmax()) :
432 new TProfile(newEfficMEName.c_str(), efficMETitle.c_str(),
433 hReco->GetXaxis()->GetNbins(),
434 hReco->GetXaxis()->GetXbins()->GetArray());
435 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,0)
436 for (
int i=1;
i <= hReco->GetNbinsX();
i++) {
437 const double nReco = hReco->GetBinContent(
i);
438 const double nSim = hSim->GetBinContent(
i);
440 if ( nSim == 0 || nReco > nSim )
continue;
441 const double effVal = nReco/nSim;
443 const double errLo = TEfficiency::ClopperPearson((
int)hSim->GetBinContent(
i),
444 (int)hReco->GetBinContent(
i),
446 const double errUp = TEfficiency::ClopperPearson((
int)hSim->GetBinContent(
i),
447 (int)hReco->GetBinContent(
i),
449 const double errVal = (effVal - errLo > errUp - effVal) ? effVal - errLo : errUp - effVal;
450 efficHist->SetBinContent(
i, effVal);
451 efficHist->SetBinEntries(
i, 1);
452 efficHist->SetBinError(
i,
sqrt(effVal * effVal + errVal * errVal));
455 for (
int i=1;
i <= hReco->GetNbinsX();
i++) {
456 TGraphAsymmErrorsWrapper asymm;
457 std::pair<double, double> efficiencyWithError;
458 efficiencyWithError = asymm.efficiency((
int)hReco->GetBinContent(
i),
459 (int)hSim->GetBinContent(
i));
460 double effVal = efficiencyWithError.first;
461 double errVal = efficiencyWithError.second;
462 if ((
int)hSim->GetBinContent(
i) > 0) {
463 efficHist->SetBinContent(
i, effVal);
464 efficHist->SetBinEntries(
i, 1);
465 efficHist->SetBinError(
i,
sqrt(effVal * effVal + errVal * errVal));
469 theDQM->bookProfile(newEfficMEName.c_str(),efficHist);
475 TH1* efficHist = (TH1*)hSim->Clone(newEfficMEName.c_str());
476 efficHist->SetTitle(efficMETitle.c_str());
485 TClass * myHistClass = efficHist->IsA();
486 TString histClassName = myHistClass->GetName();
488 if (histClassName ==
"TH1F"){
489 efficME = theDQM->book1D(newEfficMEName, (TH1F*)efficHist);
490 }
else if (histClassName ==
"TH2F"){
491 efficME = theDQM->book2D(newEfficMEName, (TH2F*)efficHist);
492 }
else if (histClassName ==
"TH3F"){
493 efficME = theDQM->book3D(newEfficMEName, (TH3F*)efficHist);
498 LogInfo(
"DQMGenericClient") <<
"computeEfficiency() : "
499 <<
"Cannot book effic-ME from the DQM\n";
507 generic_eff (hSim, hReco, efficME, type);
520 efficME->setEntries(simME->getEntries());
525 ME* globalEfficME = theDQM->get(efficDir+
"/globalEfficiencies");
526 if ( !globalEfficME ) globalEfficME = theDQM->book1D(
"globalEfficiencies",
"Global efficiencies", 1, 0, 1);
527 if ( !globalEfficME ) {
528 LogInfo(
"DQMGenericClient") <<
"computeEfficiency() : "
529 <<
"Cannot book globalEffic-ME from the DQM\n";
532 TH1F* hGlobalEffic = globalEfficME->getTH1F();
533 if ( !hGlobalEffic ) {
534 LogInfo(
"DQMGenericClient") <<
"computeEfficiency() : "
535 <<
"Cannot create TH1F from ME, globalEfficME\n";
539 const float nSimAll = hSim->GetEntries();
540 const float nRecoAll = hReco->GetEntries();
542 if ( type == 1 ) efficAll = nSimAll ? nRecoAll/nSimAll : 0;
543 else if ( type == 2 ) efficAll = nSimAll ? 1-nRecoAll/nSimAll : 0;
544 const float errorAll = nSimAll && efficAll < 1 ?
sqrt(efficAll*(1-efficAll)/nSimAll) : 0;
546 const int iBin = hGlobalEffic->Fill(newEfficMEName.c_str(), 0);
547 hGlobalEffic->SetBinContent(iBin, efficAll);
548 hGlobalEffic->SetBinError(iBin, errorAll);
554 if ( ! theDQM->dirExists(startDir) ) {
555 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
556 LogInfo(
"DQMGenericClient") <<
"computeResolution() : "
557 <<
"Cannot find sub-directory " << startDir << endl;
564 ME* srcME = theDQM->get(startDir+
"/"+srcName);
566 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
567 LogInfo(
"DQMGenericClient") <<
"computeResolution() : "
568 <<
"No source ME '" << srcName <<
"' found\n";
573 TH2F* hSrc = srcME->getTH2F();
575 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
576 LogInfo(
"DQMGenericClient") <<
"computeResolution() : "
577 <<
"Cannot create TH2F from source-ME\n";
582 const int nBin = hSrc->GetNbinsX();
584 string newDir = startDir;
585 string newPrefix = namePrefix;
587 if ( string::npos != (shiftPos = namePrefix.rfind(
'/')) ) {
588 newDir +=
"/"+namePrefix.substr(0, shiftPos);
589 newPrefix.erase(0, shiftPos+1);
592 theDQM->setCurrentFolder(newDir);
594 float * lowedgesfloats =
new float[nBin+1];
597 if (hSrc->GetXaxis()->GetXbins()->GetSize())
599 for (
int j=0;
j<nBin+1; ++
j)
600 lowedgesfloats[
j] = (
float)hSrc->GetXaxis()->GetXbins()->GetAt(
j);
601 meanME = theDQM->book1D(newPrefix+
"_Mean", titlePrefix+
" Mean", nBin, lowedgesfloats);
602 sigmaME = theDQM->book1D(newPrefix+
"_Sigma", titlePrefix+
" Sigma", nBin, lowedgesfloats);
606 meanME = theDQM->book1D(newPrefix+
"_Mean", titlePrefix+
" Mean", nBin,
607 hSrc->GetXaxis()->GetXmin(),
608 hSrc->GetXaxis()->GetXmax());
609 sigmaME = theDQM->book1D(newPrefix+
"_Sigma", titlePrefix+
" Sigma", nBin,
610 hSrc->GetXaxis()->GetXmin(),
611 hSrc->GetXaxis()->GetXmax());
614 if (meanME && sigmaME)
616 meanME->setEfficiencyFlag();
617 sigmaME->setEfficiencyFlag();
619 if (! resLimitedFit_ ) {
625 limitedFit(srcME,meanME,sigmaME);
628 delete[] lowedgesfloats;
633 if ( ! theDQM->dirExists(startDir) ) {
634 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
635 LogInfo(
"DQMGenericClient") <<
"normalizeToEntries() : "
636 <<
"Cannot find sub-directory " << startDir << endl;
643 ME* element = theDQM->get(startDir+
"/"+histName);
644 ME* normME = theDQM->get(startDir+
"/"+normHistName);
647 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
648 LogInfo(
"DQMGenericClient") <<
"normalizeToEntries() : "
649 <<
"No such element '" << histName <<
"' found\n";
655 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
656 LogInfo(
"DQMGenericClient") <<
"normalizeToEntries() : "
657 <<
"No such element '" << normHistName <<
"' found\n";
662 TH1F*
hist = element->getTH1F();
664 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
665 LogInfo(
"DQMGenericClient") <<
"normalizeToEntries() : "
666 <<
"Cannot create TH1F from ME\n";
671 TH1F* normHist = normME->getTH1F();
673 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
674 LogInfo(
"DQMGenericClient") <<
"normalizeToEntries() : "
675 <<
"Cannot create TH1F from ME\n";
680 const double entries = normHist->GetEntries();
681 if ( entries != 0 ) {
682 hist->Scale(1./entries);
685 LogInfo(
"DQMGenericClient") <<
"normalizeToEntries() : "
686 <<
"Zero entries in histogram\n";
694 if ( ! theDQM->dirExists(startDir) ) {
695 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
696 LogInfo(
"DQMGenericClient") <<
"makeCumulativeDist() : "
697 <<
"Cannot find sub-directory " << startDir << endl;
704 ME* element_cd = theDQM->get(startDir+
"/"+cdName);
707 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
708 LogInfo(
"DQMGenericClient") <<
"makeCumulativeDist() : "
709 <<
"No such element '" << cdName <<
"' found\n";
714 TH1F* cd = element_cd->getTH1F();
717 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
718 LogInfo(
"DQMGenericClient") <<
"makeCumulativeDist() : "
719 <<
"Cannot create TH1F from ME\n";
724 int n_bins = cd->GetNbinsX() + 1;
726 for (
int i = 1;
i <= n_bins;
i++) {
727 cd->SetBinContent(
i,cd->GetBinContent(
i) + cd->GetBinContent(
i-1));
741 double cont_min = 100;
742 Int_t binx = histo->GetXaxis()->GetNbins();
744 for (
int i = 1; i <= binx ; i++) {
746 TH1 *histoY = histo->ProjectionY(
" ", i, i);
747 double cont = histoY->GetEntries();
749 if (cont >= cont_min) {
750 float minfit = histoY->GetMean() - histoY->GetRMS();
751 float maxfit = histoY->GetMean() + histoY->GetRMS();
753 TF1 *fitFcn =
new TF1(TString(
"g")+histo->GetName()+iString,
"gaus",minfit,maxfit);
755 fitFcn->GetRange(x1,x2);
757 histoY->Fit(fitFcn,
"QR0",
"",x1,x2);
760 double *par = fitFcn->GetParameters();
761 double *err = fitFcn->GetParErrors();
773 if(fitFcn)
delete fitFcn;
774 if(histoY)
delete histoY;
777 if(histoY)
delete histoY;
787 if (!theDQM->dirExists(dir)) {
788 LogError(
"DQMGenericClient") <<
" DQMGenericClient::findAllSubdirectories ==> Missing folder " << dir <<
" !!!";
793 TPRegexp regexp(pattern);
795 vector <string> foundDirs = theDQM->getSubdirs();
796 for(vector<string>::const_iterator iDir = foundDirs.begin();
797 iDir != foundDirs.end(); ++iDir) {
798 TString
dirName = iDir->substr(iDir->rfind(
'/') + 1, iDir->length());
799 if (dirName.Contains(regexp))
800 findAllSubdirectories ( *iDir, myList);
804 else if (theDQM->dirExists(dir)){
809 findAllSubdirectories (dir, myList,
"*");
813 LogInfo (
"DQMGenericClient") <<
"Trying to find sub-directories of " << dir
814 <<
" failed because " << dir <<
" does not exist";
822 for (
int iBinX = 1; iBinX < denom->GetNbinsX()+1; iBinX++){
823 for (
int iBinY = 1; iBinY < denom->GetNbinsY()+1; iBinY++){
824 for (
int iBinZ = 1; iBinZ < denom->GetNbinsZ()+1; iBinZ++){
826 int globalBinNum = denom->GetBin(iBinX, iBinY, iBinZ);
828 float numerVal = numer->GetBinContent(globalBinNum);
829 float denomVal = denom->GetBinContent(globalBinNum);
835 effVal = denomVal ? (1 - numerVal / denomVal) : 0;
837 effVal = denomVal ? numerVal / denomVal : 0;
840 float errVal = (denomVal && (effVal <=1)) ?
sqrt(effVal*(1-effVal)/denomVal) : 0;
842 LogDebug (
"DQMGenericClient") <<
"(iBinX, iBinY, iBinZ) = "
845 << iBinZ <<
"), global bin = " << globalBinNum
846 <<
"eff = " << numerVal <<
" / " << denomVal
848 <<
" ... setting the error for that bin ... " << endl
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
void setBinContent(int binx, double content)
set content of bin (1-D)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
TPRegexp metacharacters("[\\^\\$\\.\\*\\+\\?\\|\\(\\)\\{\\}\\[\\]]")
void endRun(const edm::Run &r, const edm::EventSetup &c)
EndRun.
void makeCumulativeDist(const std::string &startDir, const std::string &cdName)
void computeResolution(const std::string &startDir, const std::string &fitMEPrefix, const std::string &fitMETitlePrefix, const std::string &srcMEName)
void setBinError(int binx, double error)
set uncertainty on content of bin (1-D)
void findAllSubdirectories(std::string dir, std::set< std::string > *myList, const TString &pattern)
TPRegexp nonPerlWildcard("\\w\\*|^\\*")
void computeEfficiency(const std::string &startDir, const std::string &efficMEName, const std::string &efficMETitle, const std::string &recoMEName, const std::string &simMEName, const int type=1, const bool makeProfile=false)
void setEfficiencyFlag(void)
DQMGenericClient(const edm::ParameterSet &pset)
TH2F * getTH2F(void) const
void normalizeToEntries(const std::string &startDir, const std::string &histName, const std::string &normHistName)
void limitedFit(MonitorElement *srcME, MonitorElement *meanME, MonitorElement *sigmaME)
void generic_eff(TH1 *denom, TH1 *numer, MonitorElement *efficiencyHist, const int type=1)