CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DQMOffline/Trigger/src/HLTMuonMatchAndPlot.cc

Go to the documentation of this file.
00001 
00009 #include "DQMOffline/Trigger/interface/HLTMuonMatchAndPlot.h"
00010 
00011 #include "FWCore/Framework/interface/Run.h"
00012 #include "FWCore/Framework/interface/EventSetup.h"
00013 
00014 #include "FWCore/ServiceRegistry/interface/Service.h"
00015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00016 #include "DataFormats/Common/interface/Handle.h"
00017 #include "DataFormats/HLTReco/interface/TriggerEventWithRefs.h"
00018 #include "DataFormats/HLTReco/interface/TriggerEvent.h"
00019 #include "DataFormats/Candidate/interface/CandMatchMap.h"
00020 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00021 #include "DataFormats/VertexReco/interface/Vertex.h"
00022 #include "DataFormats/Common/interface/TriggerResults.h"
00023 
00024 #include <iostream>
00025 
00028 
00029 using namespace std;
00030 using namespace edm;
00031 using namespace reco;
00032 using namespace trigger;
00033 using namespace l1extra;
00034 
00035 typedef std::vector<std::string> vstring;
00036 
00037 
00040 
00042 HLTMuonMatchAndPlot::HLTMuonMatchAndPlot(const ParameterSet & pset, 
00043                                          string hltPath, 
00044                                          vector<string> moduleLabels) :
00045   hltProcessName_(pset.getParameter<string>("hltProcessName")),
00046   destination_(pset.getUntrackedParameter<string>("destination")),
00047   requiredTriggers_(pset.getUntrackedParameter<vstring>("requiredTriggers")),
00048   targetParams_(pset.getParameterSet("targetParams")),
00049   probeParams_(pset.getParameterSet("probeParams")),
00050   hltPath_(hltPath),
00051   moduleLabels_(moduleLabels),
00052   hasTargetRecoCuts(targetParams_.exists("recoCuts")),
00053   hasProbeRecoCuts(probeParams_.exists("recoCuts")),
00054   targetMuonSelector_(targetParams_.getUntrackedParameter<string>("recoCuts", "")),
00055   targetZ0Cut_(targetParams_.getUntrackedParameter<double>("z0Cut",0.)),
00056   targetD0Cut_(targetParams_.getUntrackedParameter<double>("d0Cut",0.)),
00057   probeMuonSelector_(probeParams_.getUntrackedParameter<string>("recoCuts", "")),
00058   probeZ0Cut_(probeParams_.getUntrackedParameter<double>("z0Cut",0.)),                                                                                                                                                                                                        
00059   probeD0Cut_(probeParams_.getUntrackedParameter<double>("d0Cut",0.))
00060 {
00061 
00062   // Create std::map<string, T> from ParameterSets. 
00063   fillMapFromPSet(inputTags_, pset, "inputTags");
00064   fillMapFromPSet(binParams_, pset, "binParams");
00065   fillMapFromPSet(plotCuts_, pset, "plotCuts");
00066 
00067   // Set HLT process name for TriggerResults and TriggerSummary.
00068   InputTag & resTag = inputTags_["triggerResults"];
00069   resTag = InputTag(resTag.label(), resTag.instance(), hltProcessName_);
00070   InputTag & sumTag = inputTags_["triggerSummary"];
00071   sumTag = InputTag(sumTag.label(), sumTag.instance(), hltProcessName_);
00072 
00073   // Prepare the DQMStore object.
00074   dbe_ = edm::Service<DQMStore>().operator->();
00075   dbe_->setVerbose(0);
00076 
00077   // Get the trigger level.
00078   triggerLevel_ = "L3";
00079   TPRegexp levelRegexp("L[1-3]");
00080   size_t nModules = moduleLabels_.size();
00081   TObjArray * levelArray = levelRegexp.MatchS(moduleLabels_[nModules - 1]);
00082   if (levelArray->GetEntriesFast() > 0) {
00083     triggerLevel_ = ((TObjString *)levelArray->At(0))->GetString();
00084   }
00085   delete levelArray;
00086 
00087   // Get the pT cut by parsing the name of the HLT path.
00088   cutMinPt_ = 3;
00089   TPRegexp ptRegexp("Mu([0-9]*)");
00090   TObjArray * objArray = ptRegexp.MatchS(hltPath_);
00091   if (objArray->GetEntriesFast() >= 2) {
00092     TObjString * ptCutString = (TObjString *)objArray->At(1);
00093     cutMinPt_ = atoi(ptCutString->GetString());
00094     cutMinPt_ = ceil(cutMinPt_ * plotCuts_["minPtFactor"]);
00095   }
00096   delete objArray;
00097 }
00098 
00099 void HLTMuonMatchAndPlot::beginRun(const edm::Run& iRun, 
00100                                    const edm::EventSetup& iSetup)
00101 {
00102 
00103   TPRegexp suffixPtCut("Mu[0-9]+$");
00104 
00105   string baseDir = destination_;
00106   if (baseDir[baseDir.size() - 1] != '/') baseDir += '/';
00107   string pathSansSuffix = hltPath_;
00108   if (hltPath_.rfind("_v") < hltPath_.length())
00109     pathSansSuffix = hltPath_.substr(0, hltPath_.rfind("_v"));
00110   dbe_->setCurrentFolder(baseDir + pathSansSuffix);
00111 
00112   // Form is book1D(name, binningType, title) where 'binningType' is used 
00113   // to fetch the bin settings from binParams_.
00114   book1D("deltaR", "deltaR", ";#Deltar(reco, HLT);");
00115   book1D("resolutionEta", "resolution", 
00116          ";(#eta^{reco}-#eta^{HLT})/|#eta^{reco}|;");
00117   book1D("resolutionPhi", "resolution", 
00118          ";(#phi^{reco}-#phi^{HLT})/|#phi^{reco}|;");
00119   book1D("resolutionPt", "resolution", 
00120          ";(p_{T}^{reco}-p_{T}^{HLT})/|p_{T}^{reco}|;");
00121 
00122   for (size_t i = 0; i < 2; i++) {
00123 
00124     string suffix = EFFICIENCY_SUFFIXES[i];
00125 
00126     book1D("efficiencyEta_" + suffix, "eta", ";#eta;");
00127     book1D("efficiencyPhi_" + suffix, "phi", ";#phi;");
00128     book1D("efficiencyTurnOn_" + suffix, "pt", ";p_{T};");
00129     book1D("efficiencyD0_" + suffix, "d0", ";d0;");
00130     book1D("efficiencyZ0_" + suffix, "z0", ";z0;");
00131     book1D("efficiencyCharge_" + suffix, "charge", ";charge;");
00132     book2D("efficiencyPhiVsEta_" + suffix, "etaCoarse", "phiCoarse", 
00133            ";#eta;#phi");
00134 
00135     book1D("fakerateEta_" + suffix, "eta", ";#eta;");
00136     book1D("fakeratePhi_" + suffix, "phi", ";#phi;");
00137     book1D("fakerateTurnOn_" + suffix, "pt", ";p_{T};");
00138 
00139     // Charge Flip?
00140  
00141     // Book histograms for tag and probe
00142     if (probeParams_.exists("recoCuts")) {
00143       book2D("massVsEta_" + suffix, "zMass", "etaCoarse", ";m_{#mu#mu};#eta");
00144     }
00145 
00146   }
00147   
00148 }
00149 
00150 
00151 
00152 void HLTMuonMatchAndPlot::endRun(const edm::Run& iRun, 
00153                                  const edm::EventSetup& iSetup)
00154 {
00155 }
00156 
00157 
00158 
00159 void HLTMuonMatchAndPlot::analyze(const Event & iEvent,
00160                                   const edm::EventSetup& iSetup)
00161 
00162 {
00163 
00164   // Get objects from the event.
00165   Handle<MuonCollection> allMuons;
00166   iEvent.getByLabel(inputTags_["recoMuon"], allMuons);
00167   Handle<BeamSpot> beamSpot;
00168   iEvent.getByLabel(inputTags_["beamSpot"], beamSpot);
00169   Handle<TriggerEvent> triggerSummary;
00170   iEvent.getByLabel(inputTags_["triggerSummary"], triggerSummary);
00171   Handle<TriggerResults> triggerResults;
00172   iEvent.getByLabel(inputTags_["triggerResults"], triggerResults);
00173 
00174   // Throw out this event if it doesn't pass the required triggers.
00175   for (size_t i = 0; i < requiredTriggers_.size(); i++) {
00176     unsigned int triggerIndex = triggerResults->find(requiredTriggers_[i]);
00177     if (triggerIndex < triggerResults->size() ||
00178         !triggerResults->accept(triggerIndex))
00179       return;
00180   }
00181 
00182   // Select objects based on the configuration.
00183   MuonCollection targetMuons = selectedMuons(* allMuons, * beamSpot, hasTargetRecoCuts, targetMuonSelector_, targetD0Cut_, targetZ0Cut_);
00184   MuonCollection probeMuons = selectedMuons(* allMuons, * beamSpot, hasProbeRecoCuts, probeMuonSelector_, probeD0Cut_, probeZ0Cut_);
00185   TriggerObjectCollection allTriggerObjects = triggerSummary->getObjects();
00186   TriggerObjectCollection hltMuons = 
00187     selectedTriggerObjects(allTriggerObjects, * triggerSummary, targetParams_);
00188 
00189   // Find the best trigger object matches for the targetMuons.
00190   vector<size_t> matches = matchByDeltaR(targetMuons, hltMuons, 
00191                                          plotCuts_[triggerLevel_ + "DeltaR"]);
00192 
00193   // Fill plots for matched muons.
00194   for (size_t i = 0; i < targetMuons.size(); i++) {
00195 
00196     Muon & muon = targetMuons[i];
00197 
00198     // Fill plots which are not efficiencies.
00199     if (matches[i] < targetMuons.size()) {
00200       TriggerObject & hltMuon = hltMuons[matches[i]];
00201       double ptRes = (muon.pt() - hltMuon.pt()) / muon.pt();
00202       double etaRes = (muon.eta() - hltMuon.eta()) / fabs(muon.eta());
00203       double phiRes = (muon.phi() - hltMuon.phi()) / fabs(muon.phi());
00204       hists_["resolutionEta"]->Fill(etaRes);
00205       hists_["resolutionPhi"]->Fill(phiRes);
00206       hists_["resolutionPt"]->Fill(ptRes);
00207       hists_["deltaR"]->Fill(deltaR(muon, hltMuon));
00208     }
00209 
00210     // Fill numerators and denominators for efficiency plots.
00211     for (size_t j = 0; j < 2; j++) {
00212 
00213       string suffix = EFFICIENCY_SUFFIXES[j];
00214 
00215       // If no match was found, then the numerator plots don't get filled.
00216       if (suffix == "numer" && matches[i] >= targetMuons.size()) continue;
00217 
00218       if (muon.pt() > cutMinPt_) {
00219         hists_["efficiencyEta_" + suffix]->Fill(muon.eta());
00220         hists_["efficiencyPhiVsEta_" + suffix]->Fill(muon.eta(), muon.phi());
00221       }
00222       
00223       if (fabs(muon.eta()) < plotCuts_["maxEta"]) {
00224         hists_["efficiencyTurnOn_" + suffix]->Fill(muon.pt());
00225       }
00226       
00227       if (muon.pt() > cutMinPt_ && fabs(muon.eta()) < plotCuts_["maxEta"]) {
00228         const Track * track = 0;
00229         if (muon.isTrackerMuon()) track = & * muon.innerTrack();
00230         else if (muon.isStandAloneMuon()) track = & * muon.outerTrack();
00231         if (track) {
00232           double d0 = track->dxy(beamSpot->position());
00233           double z0 = track->dz(beamSpot->position());
00234           hists_["efficiencyPhi_" + suffix]->Fill(muon.phi());
00235           hists_["efficiencyD0_" + suffix]->Fill(d0);
00236           hists_["efficiencyZ0_" + suffix]->Fill(z0);
00237           hists_["efficiencyCharge_" + suffix]->Fill(muon.charge());
00238         }
00239       }
00240       
00241       // Fill plots for tag and probe
00242       for (size_t k = 0; k < probeMuons.size(); k++) {
00243         Muon & probe = targetMuons[k];
00244         if (muon.charge() != probe.charge()) {
00245           double mass = (muon.p4() + probe.p4()).M();
00246           hists_["massVsEta_" + suffix]->Fill(mass, muon.eta());
00247         }
00248       }
00249 
00250     } // End loop over denominator and numerator.
00251 
00252   } // End loop over targetMuons.
00253 
00254   // Plot fake rates (efficiency for HLT objects to not get matched to RECO).
00255   vector<size_t> hltMatches = matchByDeltaR(hltMuons, targetMuons,
00256                                             plotCuts_[triggerLevel_ + "DeltaR"]);
00257   for (size_t i = 0; i < hltMuons.size(); i++) {
00258     TriggerObject & hltMuon = hltMuons[i];
00259     bool isFake = hltMatches[i] > hltMuons.size();
00260     for (size_t j = 0; j < 2; j++) {
00261       string suffix = EFFICIENCY_SUFFIXES[j];
00262       // If match is found, then numerator plots should not get filled
00263       if (suffix == "numer" && ! isFake) continue;
00264       hists_["fakerateEta_" + suffix]->Fill(hltMuon.eta());
00265       hists_["fakeratePhi_" + suffix]->Fill(hltMuon.phi());
00266       hists_["fakerateTurnOn_" + suffix]->Fill(hltMuon.pt());
00267     } // End loop over numerator and denominator.
00268   } // End loop over hltMuons.
00269   
00270 
00271 } // End analyze() method.
00272 
00273 
00274 
00275 // Method to fill binning parameters from a vector of doubles.
00276 void 
00277 HLTMuonMatchAndPlot::fillEdges(size_t & nBins, float * & edges, 
00278                                vector<double> binning) {
00279 
00280   if (binning.size() < 3) {
00281     LogWarning("HLTMuonVal") << "Invalid binning parameters!"; 
00282     return;
00283   }
00284 
00285   // Fixed-width binning.
00286   if (binning.size() == 3) {
00287     nBins = binning[0];
00288     edges = new float[nBins + 1];
00289     const double min = binning[1];
00290     const double binwidth = (binning[2] - binning[1]) / nBins;
00291     for (size_t i = 0; i <= nBins; i++) edges[i] = min + (binwidth * i);
00292   } 
00293 
00294   // Variable-width binning.
00295   else {
00296     nBins = binning.size() - 1;
00297     edges = new float[nBins + 1];
00298     for (size_t i = 0; i <= nBins; i++) edges[i] = binning[i];
00299   }
00300 
00301 }
00302 
00303 
00304 
00305 // This is an unorthodox method of getting parameters, but cleaner in my mind
00306 // It looks for parameter 'target' in the pset, and assumes that all entries
00307 // have the same class (T), filling the values into a std::map.
00308 template <class T>
00309 void 
00310 HLTMuonMatchAndPlot::fillMapFromPSet(map<string, T> & m, 
00311                                      ParameterSet pset, string target) {
00312 
00313   // Get the ParameterSet with name 'target' from 'pset'
00314   ParameterSet targetPset;
00315   if (pset.existsAs<ParameterSet>(target, true))        // target is tracked
00316     targetPset = pset.getParameterSet(target);
00317   else if (pset.existsAs<ParameterSet>(target, false))  // target is untracked
00318     targetPset = pset.getUntrackedParameterSet(target);
00319   
00320   // Get the parameter names from targetPset
00321   vector<string> names = targetPset.getParameterNames();
00322   vector<string>::const_iterator iter;
00323   
00324   for (iter = names.begin(); iter != names.end(); ++iter) {
00325     if (targetPset.existsAs<T>(* iter, true))           // target is tracked
00326       m[* iter] = targetPset.getParameter<T>(* iter);
00327     else if (targetPset.existsAs<T>(* iter, false))     // target is untracked
00328       m[* iter] = targetPset.getUntrackedParameter<T>(* iter);
00329   }
00330 
00331 }
00332 
00333 
00334 
00335 // A generic method to find the best deltaR matches from 2 collections.
00336 template <class T1, class T2> 
00337 vector<size_t> 
00338 HLTMuonMatchAndPlot::matchByDeltaR(const vector<T1> & collection1, 
00339                                    const vector<T2> & collection2,
00340                                    const double maxDeltaR) {
00341 
00342   const size_t n1 = collection1.size();
00343   const size_t n2 = collection2.size();
00344 
00345   vector<size_t> result(n1, -1);
00346   vector<vector<double> > deltaRMatrix(n1, vector<double>(n2, NOMATCH));
00347 
00348   for (size_t i = 0; i < n1; i++)
00349     for (size_t j = 0; j < n2; j++) {
00350       deltaRMatrix[i][j] = deltaR(collection1[i], collection2[j]);
00351     }
00352 
00353   // Run through the matrix n1 times to make sure we've found all matches.
00354   for (size_t k = 0; k < n1; k++) {
00355     size_t i_min = -1;
00356     size_t j_min = -1;
00357     double minDeltaR = maxDeltaR;
00358     // find the smallest deltaR
00359     for (size_t i = 0; i < n1; i++)
00360       for (size_t j = 0; j < n2; j++)
00361         if (deltaRMatrix[i][j] < minDeltaR) {
00362           i_min = i;
00363           j_min = j;
00364           minDeltaR = deltaRMatrix[i][j];
00365         }
00366     // If a match has been made, save it and make those candidates unavailable.
00367     if (minDeltaR < maxDeltaR) {
00368       result[i_min] = j_min;
00369       deltaRMatrix[i_min] = vector<double>(n2, NOMATCH);
00370       for (size_t i = 0; i < n1; i++)
00371         deltaRMatrix[i][j_min] = NOMATCH;
00372     }
00373   }
00374 
00375   return result;
00376 
00377 }
00378 
00379 
00380 
00381 MuonCollection
00382 HLTMuonMatchAndPlot::selectedMuons(const MuonCollection & allMuons, 
00383                                    const BeamSpot & beamSpot,
00384                                    bool hasRecoCuts,
00385                                    const StringCutObjectSelector<reco::Muon> &selector,
00386                                    double d0Cut, double z0Cut)
00387 {
00388   // If there is no selector (recoCuts does not exists), return an empty collection. 
00389   if (!hasRecoCuts)
00390     return MuonCollection();
00391 
00392   MuonCollection reducedMuons(allMuons);
00393   MuonCollection::iterator iter = reducedMuons.begin();
00394   while (iter != reducedMuons.end()) {
00395     const Track * track = 0;
00396     if (iter->isTrackerMuon()) track = & * iter->innerTrack();
00397     else if (iter->isStandAloneMuon()) track = & * iter->outerTrack();
00398     if (track && selector(* iter) &&
00399         fabs(track->dxy(beamSpot.position())) < d0Cut &&
00400         fabs(track->dz(beamSpot.position())) < z0Cut)
00401       ++iter;
00402     else reducedMuons.erase(iter);
00403   }
00404 
00405   return reducedMuons;
00406 
00407 }
00408 
00409 
00410 
00411 TriggerObjectCollection
00412 HLTMuonMatchAndPlot::selectedTriggerObjects(
00413   const TriggerObjectCollection & triggerObjects,
00414   const TriggerEvent & triggerSummary,
00415   const ParameterSet & pset) 
00416 {
00417 
00418   // If pset is empty, return an empty collection.
00419   if (!pset.exists("hltCuts"))
00420     return TriggerObjectCollection();
00421 
00422   StringCutObjectSelector<TriggerObject> selector
00423     (pset.getUntrackedParameter<string>("hltCuts"));
00424 
00425   InputTag filterTag(moduleLabels_[moduleLabels_.size() - 1], "", 
00426                      hltProcessName_);
00427   size_t filterIndex = triggerSummary.filterIndex(filterTag);
00428 
00429   TriggerObjectCollection selectedObjects;
00430 
00431   if (filterIndex < triggerSummary.sizeFilters()) {
00432     const Keys &keys = triggerSummary.filterKeys(filterIndex);
00433     for (size_t j = 0; j < keys.size(); j++ ){
00434       TriggerObject foundObject = triggerObjects[keys[j]];
00435       if (selector(foundObject))
00436         selectedObjects.push_back(foundObject);
00437     }
00438   }
00439 
00440   return selectedObjects;
00441 
00442 }
00443 
00444 
00445 
00446 void
00447 HLTMuonMatchAndPlot::book1D(string name, string binningType, string title) {
00448   
00449   size_t nBins;
00450   float * edges;
00451   fillEdges(nBins, edges, binParams_[binningType]);
00452 
00453   TH1F * h = new TH1F(name.c_str(), title.c_str(), nBins, edges);
00454   h->Sumw2();
00455   hists_[name] = dbe_->book1D(name, h);
00456   delete h;
00457 
00458 }
00459 
00460 
00461 
00462 void
00463 HLTMuonMatchAndPlot::book2D(string name, string binningTypeX, 
00464                             string binningTypeY, string title) {
00465   
00466   size_t  nBinsX;
00467   float * edgesX;
00468   fillEdges(nBinsX, edgesX, binParams_[binningTypeX]);
00469 
00470   size_t  nBinsY;
00471   float * edgesY;
00472   fillEdges(nBinsY, edgesY, binParams_[binningTypeY]);
00473 
00474   TH2F * h = new TH2F(name.c_str(), title.c_str(), 
00475                       nBinsX, edgesX, nBinsY, edgesY);
00476   h->Sumw2();
00477   hists_[name] = dbe_->book2D(name, h);
00478   delete h;
00479 
00480 }
00481