00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Validation/Tools/interface/PostProcessor.h"
00012
00013 #include "Validation/Tools/interface/FitSlicesYTool.h"
00014 #include "DQMServices/Core/interface/DQMStore.h"
00015 #include "DQMServices/Core/interface/MonitorElement.h"
00016 #include "FWCore/ServiceRegistry/interface/Service.h"
00017
00018 #include <TH1F.h>
00019 #include <cmath>
00020
00021 using namespace std;
00022 using namespace edm;
00023
00024 typedef MonitorElement ME;
00025 typedef vector<string> vstring;
00026
00027 PostProcessor::PostProcessor(const ParameterSet& pset)
00028 {
00029 verbose_ = pset.getUntrackedParameter<unsigned int>("verbose", 0);
00030
00031 effCmds_ = pset.getParameter<vstring>("efficiency");
00032 resCmds_ = pset.getParameter<vstring>("resolution");
00033
00034 resLimitedFit_ = pset.getUntrackedParameter<bool>("resolutionLimitedFit",false);
00035
00036 outputFileName_ = pset.getUntrackedParameter<string>("outputFileName", "");
00037 subDirs_ = pset.getUntrackedParameter<vstring>("subDirs");
00038
00039 isWildcardUsed_ = false;
00040 }
00041
00042 void PostProcessor::endJob()
00043 {
00044 theDQM = 0;
00045 theDQM = Service<DQMStore>().operator->();
00046
00047 if ( ! theDQM ) {
00048 LogError("PostProcessor") << "Cannot create DQMStore instance\n";
00049 return;
00050 }
00051
00052
00053 set<string> subDirSet;
00054
00055 for(vstring::const_iterator iSubDir = subDirs_.begin();
00056 iSubDir != subDirs_.end(); ++iSubDir) {
00057 string subDir = *iSubDir;
00058
00059 if ( subDir[subDir.size()-1] == '/' ) subDir.erase(subDir.size()-1);
00060
00061 if ( subDir[subDir.size()-1] == '*' ) {
00062 isWildcardUsed_ = true;
00063 const string::size_type shiftPos = subDir.rfind('/');
00064
00065 const string searchPath = subDir.substr(0, shiftPos);
00066 theDQM->cd(searchPath);
00067
00068 vector<string> foundDirs = theDQM->getSubdirs();
00069 const string matchStr = subDir.substr(0, subDir.size()-2);
00070
00071 for(vector<string>::const_iterator iDir = foundDirs.begin();
00072 iDir != foundDirs.end(); ++iDir) {
00073 const string dirPrefix = iDir->substr(0, matchStr.size());
00074
00075 if ( dirPrefix == matchStr ) {
00076 subDirSet.insert(*iDir);
00077 }
00078 }
00079 }
00080 else {
00081 subDirSet.insert(subDir);
00082 }
00083 }
00084
00085 for(set<string>::const_iterator iSubDir = subDirSet.begin();
00086 iSubDir != subDirSet.end(); ++iSubDir) {
00087 typedef boost::escaped_list_separator<char> elsc;
00088
00089 const string& dirName = *iSubDir;
00090
00091 for(vstring::const_iterator iCmd = effCmds_.begin();
00092 iCmd != effCmds_.end(); ++iCmd) {
00093 if ( iCmd->empty() ) continue;
00094 boost::tokenizer<elsc> tokens(*iCmd, elsc("\\", " \t", "\'"));
00095
00096 vector<string> args;
00097 for(boost::tokenizer<elsc>::const_iterator iToken = tokens.begin();
00098 iToken != tokens.end(); ++iToken) {
00099 if ( iToken->empty() ) continue;
00100 args.push_back(*iToken);
00101 }
00102
00103 if ( args.size() < 4 ) {
00104 LogError("PostProcessor") << "Wrong input to effCmds\n";
00105 continue;
00106 }
00107
00108 if ( args.size() == 4 ) args.push_back("eff");
00109
00110 computeEfficiency(dirName, args[0], args[1], args[2], args[3], args[4]);
00111 }
00112
00113 for(vstring::const_iterator iCmd = resCmds_.begin();
00114 iCmd != resCmds_.end(); ++ iCmd) {
00115 if ( iCmd->empty() ) continue;
00116 boost::tokenizer<elsc> tokens(*iCmd, elsc("\\", " \t", "\'"));
00117
00118 vector<string> args;
00119 for(boost::tokenizer<elsc>::const_iterator iToken = tokens.begin();
00120 iToken != tokens.end(); ++iToken) {
00121 if ( iToken->empty() ) continue;
00122 args.push_back(*iToken);
00123 }
00124
00125 if ( args.size() != 3 ) {
00126 LogError("PostProcessor") << "Wrong input to resCmds\n";
00127 continue;
00128 }
00129
00130 computeResolution(dirName, args[0], args[1], args[2]);
00131 }
00132 }
00133
00134 if ( verbose_ > 0 ) theDQM->showDirStructure();
00135
00136 if ( ! outputFileName_.empty() ) theDQM->save(outputFileName_);
00137 }
00138
00139 void PostProcessor::computeEfficiency(const string& startDir, const string& efficMEName, const string& efficMETitle,
00140 const string& recoMEName, const string& simMEName, const std::string & type)
00141 {
00142 if ( ! theDQM->dirExists(startDir) ) {
00143 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
00144 LogWarning("PostProcessor") << "computeEfficiency() : "
00145 << "Cannot find sub-directory " << startDir << endl;
00146 }
00147 return;
00148 }
00149
00150 theDQM->cd();
00151
00152 ME* simME = theDQM->get(startDir+"/"+simMEName);
00153 ME* recoME = theDQM->get(startDir+"/"+recoMEName);
00154
00155 if ( !simME ) {
00156 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
00157 LogWarning("PostProcessor") << "computeEfficiency() : "
00158 << "No sim-ME '" << simMEName << "' found\n";
00159 }
00160 return;
00161 }
00162
00163 if ( !recoME ) {
00164 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
00165 LogWarning("PostProcessor") << "computeEfficiency() : "
00166 << "No reco-ME '" << recoMEName << "' found\n";
00167 }
00168 return;
00169 }
00170
00171 TH1F* hSim = simME ->getTH1F();
00172 TH1F* hReco = recoME->getTH1F();
00173 if ( !hSim || !hReco ) {
00174 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
00175 LogWarning("PostProcessor") << "computeEfficiency() : "
00176 << "Cannot create TH1F from ME\n";
00177 }
00178 return;
00179 }
00180
00181 string efficDir = startDir;
00182 string newEfficMEName = efficMEName;
00183 string::size_type shiftPos;
00184 if ( string::npos != (shiftPos = efficMEName.rfind('/')) ) {
00185 efficDir += "/"+efficMEName.substr(0, shiftPos);
00186 newEfficMEName.erase(0, shiftPos+1);
00187 }
00188 theDQM->setCurrentFolder(efficDir);
00189 ME* efficME = theDQM->book1D(newEfficMEName, efficMETitle, hSim->GetNbinsX(), hSim->GetXaxis()->GetXmin(), hSim->GetXaxis()->GetXmax());
00190
00191 if ( !efficME ) {
00192 LogWarning("PostProcessor") << "computeEfficiency() : "
00193 << "Cannot book effic-ME from the DQM\n";
00194 return;
00195 }
00196
00197 const int nBin = efficME->getNbinsX();
00198 for(int bin = 0; bin <= nBin; ++bin) {
00199 const float nSim = simME ->getBinContent(bin);
00200 const float nReco = recoME->getBinContent(bin);
00201 float eff =0;
00202 if (type=="fake")eff = nSim ? 1-nReco/nSim : 0.;
00203 else eff= nSim ? nReco/nSim : 0.;
00204 const float err = nSim && eff <= 1 ? sqrt(eff*(1-eff)/nSim) : 0.;
00205 efficME->setBinContent(bin, eff);
00206 efficME->setBinError(bin, err);
00207 }
00208 efficME->setEntries(simME->getEntries());
00209
00210
00211 ME* globalEfficME = theDQM->get(efficDir+"/globalEfficiencies");
00212 if ( !globalEfficME ) globalEfficME = theDQM->book1D("globalEfficiencies", "Global efficiencies", 1, 0, 1);
00213 if ( !globalEfficME ) {
00214 LogError("PostProcessor") << "computeEfficiency() : "
00215 << "Cannot book globalEffic-ME from the DQM\n";
00216 return;
00217 }
00218 TH1F* hGlobalEffic = globalEfficME->getTH1F();
00219 if ( !hGlobalEffic ) {
00220 LogError("PostProcessor") << "computeEfficiency() : "
00221 << "Cannot create TH1F from ME, globalEfficME\n";
00222 return;
00223 }
00224
00225 const float nSimAll = hSim->GetEntries();
00226 const float nRecoAll = hReco->GetEntries();
00227 float efficAll=0;
00228 if (type=="fake") efficAll = nSimAll ? 1-nRecoAll/nSimAll : 0;
00229 else efficAll = nSimAll ? nRecoAll/nSimAll : 0;
00230 const float errorAll = nSimAll && efficAll < 1 ? sqrt(efficAll*(1-efficAll)/nSimAll) : 0;
00231
00232 const int iBin = hGlobalEffic->Fill(newEfficMEName.c_str(), 0);
00233 hGlobalEffic->SetBinContent(iBin, efficAll);
00234 hGlobalEffic->SetBinError(iBin, errorAll);
00235 }
00236
00237 void PostProcessor::computeResolution(const string& startDir, const string& namePrefix, const string& titlePrefix,
00238 const std::string& srcName)
00239 {
00240 if ( ! theDQM->dirExists(startDir) ) {
00241 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
00242 LogWarning("PostProcessor") << "computeResolution() : "
00243 << "Cannot find sub-directory " << startDir << endl;
00244 }
00245 return;
00246 }
00247
00248 theDQM->cd();
00249
00250 ME* srcME = theDQM->get(startDir+"/"+srcName);
00251 if ( !srcME ) {
00252 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
00253 LogWarning("PostProcessor") << "computeResolution() : "
00254 << "No source ME '" << srcName << "' found\n";
00255 }
00256 return;
00257 }
00258
00259 TH2F* hSrc = srcME->getTH2F();
00260 if ( !hSrc ) {
00261 if ( verbose_ >= 2 || (verbose_ == 1 && !isWildcardUsed_) ) {
00262 LogWarning("PostProcessor") << "computeResolution() : "
00263 << "Cannot create TH2F from source-ME\n";
00264 }
00265 return;
00266 }
00267
00268 const int nBin = hSrc->GetNbinsX();
00269 const double xMin = hSrc->GetXaxis()->GetXmin();
00270 const double xMax = hSrc->GetXaxis()->GetXmax();
00271
00272 string newDir = startDir;
00273 string newPrefix = namePrefix;
00274 string::size_type shiftPos;
00275 if ( string::npos != (shiftPos = namePrefix.rfind('/')) ) {
00276 newDir += "/"+namePrefix.substr(0, shiftPos);
00277 newPrefix.erase(0, shiftPos+1);
00278 }
00279
00280 theDQM->setCurrentFolder(newDir);
00281
00282 ME* meanME = theDQM->book1D(newPrefix+"_Mean", titlePrefix+" Mean", nBin, xMin, xMax);
00283 ME* sigmaME = theDQM->book1D(newPrefix+"_Sigma", titlePrefix+" Sigma", nBin, xMin, xMax);
00284
00285
00286 if (! resLimitedFit_ ) {
00287 FitSlicesYTool fitTool(srcME);
00288 fitTool.getFittedMeanWithError(meanME);
00289 fitTool.getFittedSigmaWithError(sigmaME);
00291 } else {
00292 limitedFit(srcME,meanME,sigmaME);
00293 }
00294 }
00295
00296 void PostProcessor::limitedFit(MonitorElement * srcME, MonitorElement * meanME, MonitorElement * sigmaME)
00297 {
00298 TH2F * histo = srcME->getTH2F();
00299
00300 static int i = 0;
00301 i++;
00302
00303
00304 double cont_min = 100;
00305 Int_t binx = histo->GetXaxis()->GetNbins();
00306
00307 for (int i = 1; i <= binx ; i++) {
00308 TString iString(i);
00309 TH1 *histoY = histo->ProjectionY(" ", i, i);
00310 double cont = histoY->GetEntries();
00311
00312 if (cont >= cont_min) {
00313 float minfit = histoY->GetMean() - histoY->GetRMS();
00314 float maxfit = histoY->GetMean() + histoY->GetRMS();
00315
00316 TF1 *fitFcn = new TF1(TString("g")+histo->GetName()+iString,"gaus",minfit,maxfit);
00317 double x1,x2;
00318 fitFcn->GetRange(x1,x2);
00319
00320 histoY->Fit(fitFcn,"QR0","",x1,x2);
00321
00322
00323 double *par = fitFcn->GetParameters();
00324 double *err = fitFcn->GetParErrors();
00325
00326 meanME->setBinContent(i,par[1]);
00327 meanME->setBinError(i,err[1]);
00328
00329 sigmaME->setBinContent(i,par[2]);
00330 sigmaME->setBinError(i,err[2]);
00331 if(fitFcn) delete fitFcn;
00332 if(histoY) delete histoY;
00333 }
00334 else {
00335 if(histoY) delete histoY;
00336 continue;
00337 }
00338 }
00339 }
00340
00341