CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/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("hltPt", "pt", ";p_{T} of HLT object");
00116   book1D("hltEta", "eta", ";#eta of HLT object");
00117   book1D("hltPhi", "phi", ";#phi of HLT object");
00118   book1D("resolutionEta", "resolutionEta", ";#eta^{reco}-#eta^{HLT};");
00119   book1D("resolutionPhi", "resolutionPhi", ";#phi^{reco}-#phi^{HLT};");
00120   book1D("resolutionPt", "resolutionRel", 
00121          ";(p_{T}^{reco}-p_{T}^{HLT})/|p_{T}^{reco}|;");
00122 
00123   for (size_t i = 0; i < 2; i++) {
00124 
00125     string suffix = EFFICIENCY_SUFFIXES[i];
00126 
00127     book1D("efficiencyEta_" + suffix, "eta", ";#eta;");
00128     book1D("efficiencyPhi_" + suffix, "phi", ";#phi;");
00129     book1D("efficiencyTurnOn_" + suffix, "pt", ";p_{T};");
00130     book1D("efficiencyD0_" + suffix, "d0", ";d0;");
00131     book1D("efficiencyZ0_" + suffix, "z0", ";z0;");
00132     book1D("efficiencyCharge_" + suffix, "charge", ";charge;");
00133     book2D("efficiencyPhiVsEta_" + suffix, "etaCoarse", "phiCoarse", 
00134            ";#eta;#phi");
00135 
00136     book1D("fakerateEta_" + suffix, "eta", ";#eta;");
00137     book1D("fakeratePhi_" + suffix, "phi", ";#phi;");
00138     book1D("fakerateTurnOn_" + suffix, "pt", ";p_{T};");
00139 
00140     // Charge Flip?
00141  
00142     // Book histograms for tag and probe
00143     if (probeParams_.exists("recoCuts")) {
00144       book2D("massVsEtaZ_" + suffix, "zMass", "etaCoarse", ";m_{#mu#mu};#eta");
00145       book2D("massVsEtaJpsi_" + suffix, "jpsiMass", "etaCoarse", ";m_{#mu#mu};#eta");
00146     }
00147 
00148   }
00149   
00150 }
00151 
00152 
00153 
00154 void HLTMuonMatchAndPlot::endRun(const edm::Run& iRun, 
00155                                  const edm::EventSetup& iSetup)
00156 {
00157 }
00158 
00159 
00160 
00161 void HLTMuonMatchAndPlot::analyze(const Event & iEvent,
00162                                   const edm::EventSetup& iSetup)
00163 
00164 {
00165 
00166   // Get objects from the event.
00167   Handle<MuonCollection> allMuons;
00168   iEvent.getByLabel(inputTags_["recoMuon"], allMuons);
00169   Handle<BeamSpot> beamSpot;
00170   iEvent.getByLabel(inputTags_["beamSpot"], beamSpot);
00171   Handle<TriggerEvent> triggerSummary;
00172   iEvent.getByLabel(inputTags_["triggerSummary"], triggerSummary);
00173   Handle<TriggerResults> triggerResults;
00174   if(!triggerSummary.isValid()) 
00175   {
00176     edm::LogError("HLTMuonMatchAndPlot")<<"Missing triggerSummary with label " << inputTags_["triggerSummary"] <<std::endl;
00177     return;
00178   }
00179   iEvent.getByLabel(inputTags_["triggerResults"], triggerResults);
00180   if(!triggerResults.isValid()) 
00181   {
00182     edm::LogError("HLTMuonMatchAndPlot")<<"Missing triggerResults with label " << inputTags_["triggerResults"] <<std::endl;
00183     return;
00184   }
00185   // Throw out this event if it doesn't pass the required triggers.
00186   for (size_t i = 0; i < requiredTriggers_.size(); i++) {
00187     unsigned int triggerIndex = triggerResults->find(requiredTriggers_[i]);
00188     if (triggerIndex < triggerResults->size() ||
00189         !triggerResults->accept(triggerIndex))
00190       return;
00191   }
00192 
00193   // Select objects based on the configuration.
00194   MuonCollection targetMuons = selectedMuons(* allMuons, * beamSpot, hasTargetRecoCuts, targetMuonSelector_, targetD0Cut_, targetZ0Cut_);
00195   MuonCollection probeMuons = selectedMuons(* allMuons, * beamSpot, hasProbeRecoCuts, probeMuonSelector_, probeD0Cut_, probeZ0Cut_);
00196   TriggerObjectCollection allTriggerObjects = triggerSummary->getObjects();
00197   TriggerObjectCollection hltMuons = 
00198     selectedTriggerObjects(allTriggerObjects, * triggerSummary, targetParams_);
00199 
00200   // Fill plots for HLT muons.
00201   for (size_t i = 0; i < hltMuons.size(); i++) {
00202     hists_["hltPt"]->Fill(hltMuons[i].pt());
00203     hists_["hltEta"]->Fill(hltMuons[i].eta());
00204     hists_["hltPhi"]->Fill(hltMuons[i].phi());
00205   }
00206 
00207   // Find the best trigger object matches for the targetMuons.
00208   vector<size_t> matches = matchByDeltaR(targetMuons, hltMuons, 
00209                                          plotCuts_[triggerLevel_ + "DeltaR"]);
00210 
00211   // Fill plots for matched muons.
00212   for (size_t i = 0; i < targetMuons.size(); i++) {
00213 
00214     Muon & muon = targetMuons[i];
00215 
00216     // Fill plots which are not efficiencies.
00217     if (matches[i] < targetMuons.size()) {
00218       TriggerObject & hltMuon = hltMuons[matches[i]];
00219       double ptRes = (muon.pt() - hltMuon.pt()) / muon.pt();
00220       double etaRes = muon.eta() - hltMuon.eta();
00221       double phiRes = muon.phi() - hltMuon.phi();
00222       hists_["resolutionEta"]->Fill(etaRes);
00223       hists_["resolutionPhi"]->Fill(phiRes);
00224       hists_["resolutionPt"]->Fill(ptRes);
00225       hists_["deltaR"]->Fill(deltaR(muon, hltMuon));
00226     }
00227 
00228     // Fill numerators and denominators for efficiency plots.
00229     for (size_t j = 0; j < 2; j++) {
00230 
00231       string suffix = EFFICIENCY_SUFFIXES[j];
00232 
00233       // If no match was found, then the numerator plots don't get filled.
00234       if (suffix == "numer" && matches[i] >= targetMuons.size()) continue;
00235 
00236       if (muon.pt() > cutMinPt_) {
00237         hists_["efficiencyEta_" + suffix]->Fill(muon.eta());
00238         hists_["efficiencyPhiVsEta_" + suffix]->Fill(muon.eta(), muon.phi());
00239       }
00240       
00241       if (fabs(muon.eta()) < plotCuts_["maxEta"]) {
00242         hists_["efficiencyTurnOn_" + suffix]->Fill(muon.pt());
00243       }
00244       
00245       if (muon.pt() > cutMinPt_ && fabs(muon.eta()) < plotCuts_["maxEta"]) {
00246         const Track * track = 0;
00247         if (muon.isTrackerMuon()) track = & * muon.innerTrack();
00248         else if (muon.isStandAloneMuon()) track = & * muon.outerTrack();
00249         if (track) {
00250           double d0 = track->dxy(beamSpot->position());
00251           double z0 = track->dz(beamSpot->position());
00252           hists_["efficiencyPhi_" + suffix]->Fill(muon.phi());
00253           hists_["efficiencyD0_" + suffix]->Fill(d0);
00254           hists_["efficiencyZ0_" + suffix]->Fill(z0);
00255           hists_["efficiencyCharge_" + suffix]->Fill(muon.charge());
00256         }
00257       }
00258       
00259       // Fill plots for tag and probe
00260       for (size_t k = 0; k < probeMuons.size(); k++) {
00261         Muon & probe = targetMuons[k];
00262         if (muon.charge() != probe.charge()) {
00263           double mass = (muon.p4() + probe.p4()).M();
00264           hists_["massVsEtaZ_" + suffix]->Fill(mass, muon.eta());
00265           hists_["massVsEtaJpsi_" + suffix]->Fill(mass, muon.eta());
00266         }
00267       }
00268 
00269     } // End loop over denominator and numerator.
00270 
00271   } // End loop over targetMuons.
00272 
00273   // Plot fake rates (efficiency for HLT objects to not get matched to RECO).
00274   vector<size_t> hltMatches = matchByDeltaR(hltMuons, targetMuons,
00275                                             plotCuts_[triggerLevel_ + "DeltaR"]);
00276   for (size_t i = 0; i < hltMuons.size(); i++) {
00277     TriggerObject & hltMuon = hltMuons[i];
00278     bool isFake = hltMatches[i] > hltMuons.size();
00279     for (size_t j = 0; j < 2; j++) {
00280       string suffix = EFFICIENCY_SUFFIXES[j];
00281       // If match is found, then numerator plots should not get filled
00282       if (suffix == "numer" && ! isFake) continue;
00283       hists_["fakerateEta_" + suffix]->Fill(hltMuon.eta());
00284       hists_["fakeratePhi_" + suffix]->Fill(hltMuon.phi());
00285       hists_["fakerateTurnOn_" + suffix]->Fill(hltMuon.pt());
00286     } // End loop over numerator and denominator.
00287   } // End loop over hltMuons.
00288   
00289 
00290 } // End analyze() method.
00291 
00292 
00293 
00294 // Method to fill binning parameters from a vector of doubles.
00295 void 
00296 HLTMuonMatchAndPlot::fillEdges(size_t & nBins, float * & edges, 
00297                                vector<double> binning) {
00298 
00299   if (binning.size() < 3) {
00300     LogWarning("HLTMuonVal") << "Invalid binning parameters!"; 
00301     return;
00302   }
00303 
00304   // Fixed-width binning.
00305   if (binning.size() == 3) {
00306     nBins = binning[0];
00307     edges = new float[nBins + 1];
00308     const double min = binning[1];
00309     const double binwidth = (binning[2] - binning[1]) / nBins;
00310     for (size_t i = 0; i <= nBins; i++) edges[i] = min + (binwidth * i);
00311   } 
00312 
00313   // Variable-width binning.
00314   else {
00315     nBins = binning.size() - 1;
00316     edges = new float[nBins + 1];
00317     for (size_t i = 0; i <= nBins; i++) edges[i] = binning[i];
00318   }
00319 
00320 }
00321 
00322 
00323 
00324 // This is an unorthodox method of getting parameters, but cleaner in my mind
00325 // It looks for parameter 'target' in the pset, and assumes that all entries
00326 // have the same class (T), filling the values into a std::map.
00327 template <class T>
00328 void 
00329 HLTMuonMatchAndPlot::fillMapFromPSet(map<string, T> & m, 
00330                                      ParameterSet pset, string target) {
00331 
00332   // Get the ParameterSet with name 'target' from 'pset'
00333   ParameterSet targetPset;
00334   if (pset.existsAs<ParameterSet>(target, true))        // target is tracked
00335     targetPset = pset.getParameterSet(target);
00336   else if (pset.existsAs<ParameterSet>(target, false))  // target is untracked
00337     targetPset = pset.getUntrackedParameterSet(target);
00338   
00339   // Get the parameter names from targetPset
00340   vector<string> names = targetPset.getParameterNames();
00341   vector<string>::const_iterator iter;
00342   
00343   for (iter = names.begin(); iter != names.end(); ++iter) {
00344     if (targetPset.existsAs<T>(* iter, true))           // target is tracked
00345       m[* iter] = targetPset.getParameter<T>(* iter);
00346     else if (targetPset.existsAs<T>(* iter, false))     // target is untracked
00347       m[* iter] = targetPset.getUntrackedParameter<T>(* iter);
00348   }
00349 
00350 }
00351 
00352 
00353 
00354 // A generic method to find the best deltaR matches from 2 collections.
00355 template <class T1, class T2> 
00356 vector<size_t> 
00357 HLTMuonMatchAndPlot::matchByDeltaR(const vector<T1> & collection1, 
00358                                    const vector<T2> & collection2,
00359                                    const double maxDeltaR) {
00360 
00361   const size_t n1 = collection1.size();
00362   const size_t n2 = collection2.size();
00363 
00364   vector<size_t> result(n1, -1);
00365   vector<vector<double> > deltaRMatrix(n1, vector<double>(n2, NOMATCH));
00366 
00367   for (size_t i = 0; i < n1; i++)
00368     for (size_t j = 0; j < n2; j++) {
00369       deltaRMatrix[i][j] = deltaR(collection1[i], collection2[j]);
00370     }
00371 
00372   // Run through the matrix n1 times to make sure we've found all matches.
00373   for (size_t k = 0; k < n1; k++) {
00374     size_t i_min = -1;
00375     size_t j_min = -1;
00376     double minDeltaR = maxDeltaR;
00377     // find the smallest deltaR
00378     for (size_t i = 0; i < n1; i++)
00379       for (size_t j = 0; j < n2; j++)
00380         if (deltaRMatrix[i][j] < minDeltaR) {
00381           i_min = i;
00382           j_min = j;
00383           minDeltaR = deltaRMatrix[i][j];
00384         }
00385     // If a match has been made, save it and make those candidates unavailable.
00386     if (minDeltaR < maxDeltaR) {
00387       result[i_min] = j_min;
00388       deltaRMatrix[i_min] = vector<double>(n2, NOMATCH);
00389       for (size_t i = 0; i < n1; i++)
00390         deltaRMatrix[i][j_min] = NOMATCH;
00391     }
00392   }
00393 
00394   return result;
00395 
00396 }
00397 
00398 
00399 
00400 MuonCollection
00401 HLTMuonMatchAndPlot::selectedMuons(const MuonCollection & allMuons, 
00402                                    const BeamSpot & beamSpot,
00403                                    bool hasRecoCuts,
00404                                    const StringCutObjectSelector<reco::Muon> &selector,
00405                                    double d0Cut, double z0Cut)
00406 {
00407   // If there is no selector (recoCuts does not exists), return an empty collection. 
00408   if (!hasRecoCuts)
00409     return MuonCollection();
00410 
00411   MuonCollection reducedMuons(allMuons);
00412   MuonCollection::iterator iter = reducedMuons.begin();
00413   while (iter != reducedMuons.end()) {
00414     const Track * track = 0;
00415     if (iter->isTrackerMuon()) track = & * iter->innerTrack();
00416     else if (iter->isStandAloneMuon()) track = & * iter->outerTrack();
00417     if (track && selector(* iter) &&
00418         fabs(track->dxy(beamSpot.position())) < d0Cut &&
00419         fabs(track->dz(beamSpot.position())) < z0Cut)
00420       ++iter;
00421     else reducedMuons.erase(iter);
00422   }
00423 
00424   return reducedMuons;
00425 
00426 }
00427 
00428 
00429 
00430 TriggerObjectCollection
00431 HLTMuonMatchAndPlot::selectedTriggerObjects(
00432   const TriggerObjectCollection & triggerObjects,
00433   const TriggerEvent & triggerSummary,
00434   const ParameterSet & pset) 
00435 {
00436 
00437   // If pset is empty, return an empty collection.
00438   if (!pset.exists("hltCuts"))
00439     return TriggerObjectCollection();
00440 
00441   StringCutObjectSelector<TriggerObject> selector
00442     (pset.getUntrackedParameter<string>("hltCuts"));
00443 
00444   InputTag filterTag(moduleLabels_[moduleLabels_.size() - 1], "", 
00445                      hltProcessName_);
00446   size_t filterIndex = triggerSummary.filterIndex(filterTag);
00447 
00448   TriggerObjectCollection selectedObjects;
00449 
00450   if (filterIndex < triggerSummary.sizeFilters()) {
00451     const Keys &keys = triggerSummary.filterKeys(filterIndex);
00452     for (size_t j = 0; j < keys.size(); j++ ){
00453       TriggerObject foundObject = triggerObjects[keys[j]];
00454       if (selector(foundObject))
00455         selectedObjects.push_back(foundObject);
00456     }
00457   }
00458 
00459   return selectedObjects;
00460 
00461 }
00462 
00463 
00464 
00465 void HLTMuonMatchAndPlot::book1D(string name, string binningType, string title)
00466 {
00467   /* Properly delete the array of floats that has been allocated on
00468    * the heap by fillEdges.  Avoid multiple copies and internal ROOT
00469    * clones by simply creating the histograms directly in the DQMStore
00470    * using the appropriate book1D method to handle the variable bins
00471    * case. */ 
00472 
00473   size_t nBins; 
00474   float * edges = 0; 
00475   fillEdges(nBins, edges, binParams_[binningType]);
00476 
00477   hists_[name] = dbe_->book1D(name, title, nBins, edges);
00478   if (hists_[name])
00479     if (hists_[name]->getTH1F()->GetSumw2N())
00480       hists_[name]->getTH1F()->Sumw2();
00481 
00482   if (edges)
00483     delete [] edges;
00484 }
00485 
00486 
00487 
00488 void
00489 HLTMuonMatchAndPlot::book2D(string name, string binningTypeX, 
00490                             string binningTypeY, string title) 
00491 {
00492   
00493   /* Properly delete the arrays of floats that have been allocated on
00494    * the heap by fillEdges.  Avoid multiple copies and internal ROOT
00495    * clones by simply creating the histograms directly in the DQMStore
00496    * using the appropriate book2D method to handle the variable bins
00497    * case. */ 
00498 
00499   size_t  nBinsX;
00500   float * edgesX = 0;
00501   fillEdges(nBinsX, edgesX, binParams_[binningTypeX]);
00502 
00503   size_t  nBinsY;
00504   float * edgesY = 0;
00505   fillEdges(nBinsY, edgesY, binParams_[binningTypeY]);
00506 
00507   hists_[name] = dbe_->book2D(name.c_str(), title.c_str(),
00508                               nBinsX, edgesX, nBinsY, edgesY);
00509   if (hists_[name])
00510     if (hists_[name]->getTH2F()->GetSumw2N())
00511       hists_[name]->getTH2F()->Sumw2();
00512 
00513   if (edgesX)
00514     delete [] edgesX;
00515   if (edgesY)
00516     delete [] edgesY;
00517 }
00518