CMS 3D CMS Logo

PFRecoTauDiscriminationAgainstMuon2.cc
Go to the documentation of this file.
1 
11 
13 
23 
24 #include <vector>
25 #include <string>
26 #include <iostream>
27 
28 namespace {
29 
30 class PFRecoTauDiscriminationAgainstMuon2 final : public PFTauDiscriminationProducerBase
31 {
32  enum { kLoose, kMedium, kTight, kCustom };
33  public:
34  explicit PFRecoTauDiscriminationAgainstMuon2(const edm::ParameterSet& cfg)
36  moduleLabel_(cfg.getParameter<std::string>("@module_label"))
37  {
38  std::string discriminatorOption_string = cfg.getParameter<std::string>("discriminatorOption");
39  if ( discriminatorOption_string == "loose" ) discriminatorOption_ = kLoose;
40  else if ( discriminatorOption_string == "medium" ) discriminatorOption_ = kMedium;
41  else if ( discriminatorOption_string == "tight" ) discriminatorOption_ = kTight;
42  else if ( discriminatorOption_string == "custom" ) discriminatorOption_ = kCustom;
44  << " Invalid Configuration parameter 'discriminatorOption' = " << discriminatorOption_string << " !!\n";
45  hop_ = cfg.getParameter<double>("HoPMin");
46  maxNumberOfMatches_ = cfg.exists("maxNumberOfMatches") ? cfg.getParameter<int>("maxNumberOfMatches"): 0;
47  doCaloMuonVeto_ = cfg.exists("doCaloMuonVeto") ? cfg.getParameter<bool>("doCaloMuonVeto"): false;
48  maxNumberOfHitsLast2Stations_ = cfg.exists("maxNumberOfHitsLast2Stations") ? cfg.getParameter<int>("maxNumberOfHitsLast2Stations"): 0;
49  if ( cfg.exists("srcMuons") ) {
50  srcMuons_ = cfg.getParameter<edm::InputTag>("srcMuons");
51  Muons_token = consumes<reco::MuonCollection>(srcMuons_);
52  dRmuonMatch_ = cfg.getParameter<double>("dRmuonMatch");
53  dRmuonMatchLimitedToJetArea_ = cfg.getParameter<bool>("dRmuonMatchLimitedToJetArea");
54  minPtMatchedMuon_ = cfg.getParameter<double>("minPtMatchedMuon");
55  }
56  typedef std::vector<int> vint;
57  maskMatchesDT_ = cfg.getParameter<vint>("maskMatchesDT");
58  maskMatchesCSC_ = cfg.getParameter<vint>("maskMatchesCSC");
59  maskMatchesRPC_ = cfg.getParameter<vint>("maskMatchesRPC");
60  maskHitsDT_ = cfg.getParameter<vint>("maskHitsDT");
61  maskHitsCSC_ = cfg.getParameter<vint>("maskHitsCSC");
62  maskHitsRPC_ = cfg.getParameter<vint>("maskHitsRPC");
63  numWarnings_ = 0;
64  maxWarnings_ = 3;
65  verbosity_ = cfg.exists("verbosity") ? cfg.getParameter<int>("verbosity") : 0;
66  }
67  ~PFRecoTauDiscriminationAgainstMuon2() override {}
68 
69  void beginEvent(const edm::Event&, const edm::EventSetup&) override;
70 
71  double discriminate(const reco::PFTauRef&) const override;
72 
73  private:
75  int discriminatorOption_;
76  double hop_;
77  int maxNumberOfMatches_;
78  bool doCaloMuonVeto_;
79  int maxNumberOfHitsLast2Stations_;
80  edm::InputTag srcMuons_;
83  double dRmuonMatch_;
84  bool dRmuonMatchLimitedToJetArea_;
85  double minPtMatchedMuon_;
86  std::vector<int> maskMatchesDT_;
87  std::vector<int> maskMatchesCSC_;
88  std::vector<int> maskMatchesRPC_;
89  std::vector<int> maskHitsDT_;
90  std::vector<int> maskHitsCSC_;
91  std::vector<int> maskHitsRPC_;
92  mutable int numWarnings_;
93  int maxWarnings_;
94  int verbosity_;
95 };
96 
98 {
99  if ( srcMuons_.label() != "" ) {
100  evt.getByToken(Muons_token, muons_);
101  }
102 }
103 
104 namespace
105 {
106  void countHits(const reco::Muon& muon, std::vector<int>& numHitsDT, std::vector<int>& numHitsCSC, std::vector<int>& numHitsRPC)
107  {
108  if ( muon.outerTrack().isNonnull() ) {
109  const reco::HitPattern &muonHitPattern = muon.outerTrack()->hitPattern();
110  for (int iHit = 0; iHit < muonHitPattern.numberOfAllHits(reco::HitPattern::TRACK_HITS); ++iHit) {
111  uint32_t hit = muonHitPattern.getHitPattern(reco::HitPattern::TRACK_HITS, iHit);
112  if ( hit == 0 ) break;
113  if ( muonHitPattern.muonHitFilter(hit) && (muonHitPattern.getHitType(hit) == TrackingRecHit::valid || muonHitPattern.getHitType(hit) == TrackingRecHit::bad) ) {
114  int muonStation = muonHitPattern.getMuonStation(hit) - 1; // CV: map into range 0..3
115  if ( muonStation >= 0 && muonStation < 4 ) {
116  if ( muonHitPattern.muonDTHitFilter(hit) ) ++numHitsDT[muonStation];
117  else if ( muonHitPattern.muonCSCHitFilter(hit) ) ++numHitsCSC[muonStation];
118  else if ( muonHitPattern.muonRPCHitFilter(hit) ) ++numHitsRPC[muonStation];
119  }
120  }
121  }
122  }
123  }
124 
125  std::string format_vint(const std::vector<int>& vi)
126  {
127  std::ostringstream os;
128  os << "{ ";
129  unsigned numEntries = vi.size();
130  for ( unsigned iEntry = 0; iEntry < numEntries; ++iEntry ) {
131  os << vi[iEntry];
132  if ( iEntry < (numEntries - 1) ) os << ", ";
133  }
134  os << " }";
135  return os.str();
136  }
137 
138  void countMatches(const reco::Muon& muon, std::vector<int>& numMatchesDT, std::vector<int>& numMatchesCSC, std::vector<int>& numMatchesRPC)
139  {
140  const std::vector<reco::MuonChamberMatch>& muonSegments = muon.matches();
141  for ( std::vector<reco::MuonChamberMatch>::const_iterator muonSegment = muonSegments.begin();
142  muonSegment != muonSegments.end(); ++muonSegment ) {
143  if ( muonSegment->segmentMatches.empty() ) continue;
144  int muonDetector = muonSegment->detector();
145  int muonStation = muonSegment->station() - 1;
146  assert(muonStation >= 0 && muonStation <= 3);
147  if ( muonDetector == MuonSubdetId::DT ) ++numMatchesDT[muonStation];
148  else if ( muonDetector == MuonSubdetId::CSC ) ++numMatchesCSC[muonStation];
149  else if ( muonDetector == MuonSubdetId::RPC ) ++numMatchesRPC[muonStation];
150  }
151  }
152 }
153 
155 {
156  if ( verbosity_ ) {
157  edm::LogPrint("PFTauAgainstMuon2") << "<PFRecoTauDiscriminationAgainstMuon2::discriminate>:" ;
158  edm::LogPrint("PFTauAgainstMuon2") << " moduleLabel = " << moduleLabel_ ;
159  edm::LogPrint("PFTauAgainstMuon2") << "tau #" << pfTau.key() << ": Pt = " << pfTau->pt() << ", eta = " << pfTau->eta() << ", phi = " << pfTau->phi() ;
160  }
161 
162  std::vector<int> numMatchesDT(4);
163  std::vector<int> numMatchesCSC(4);
164  std::vector<int> numMatchesRPC(4);
165  std::vector<int> numHitsDT(4);
166  std::vector<int> numHitsCSC(4);
167  std::vector<int> numHitsRPC(4);
168  for ( int iStation = 0; iStation < 4; ++iStation ) {
169  numMatchesDT[iStation] = 0;
170  numMatchesCSC[iStation] = 0;
171  numMatchesRPC[iStation] = 0;
172  numHitsDT[iStation] = 0;
173  numHitsCSC[iStation] = 0;
174  numHitsRPC[iStation] = 0;
175  }
176 
177  const reco::PFCandidatePtr& pfLeadChargedHadron = pfTau->leadPFChargedHadrCand();
178  if ( pfLeadChargedHadron.isNonnull() ) {
179  reco::MuonRef muonRef = pfLeadChargedHadron->muonRef();
180  if ( muonRef.isNonnull() ) {
181  if ( verbosity_ ) edm::LogPrint("PFTauAgainstMuon2") << " has muonRef." ;
182  countMatches(*muonRef, numMatchesDT, numMatchesCSC, numMatchesRPC);
183  countHits(*muonRef, numHitsDT, numHitsCSC, numHitsRPC);
184  }
185  }
186 
187  if ( srcMuons_.label() != "" ) {
188  size_t numMuons = muons_->size();
189  for ( size_t idxMuon = 0; idxMuon < numMuons; ++idxMuon ) {
190  reco::MuonRef muon(muons_, idxMuon);
191  if ( verbosity_ ) edm::LogPrint("PFTauAgainstMuon2") << "muon #" << muon.key() << ": Pt = " << muon->pt() << ", eta = " << muon->eta() << ", phi = " << muon->phi() ;
192  if ( !(muon->pt() > minPtMatchedMuon_) ) {
193  if ( verbosity_ ){ edm::LogPrint("PFTauAgainstMuon2") << " fails Pt cut --> skipping it." ;}
194  continue;
195  }
196  if ( pfLeadChargedHadron.isNonnull() && pfLeadChargedHadron->muonRef().isNonnull() && muon == pfLeadChargedHadron->muonRef() ) {
197  if ( verbosity_ ){ edm::LogPrint("PFTauAgainstMuon2") << " matches muonRef of tau --> skipping it." ;}
198  continue;
199  }
200  double dR = deltaR(muon->p4(), pfTau->p4());
201  double dRmatch = dRmuonMatch_;
202  if ( dRmuonMatchLimitedToJetArea_ ) {
203  double jetArea = 0.;
204  if ( pfTau->jetRef().isNonnull() ) jetArea = pfTau->jetRef()->jetArea();
205  if ( jetArea > 0. ) {
206  dRmatch = TMath::Min(dRmatch, TMath::Sqrt(jetArea/TMath::Pi()));
207  } else {
208  if ( numWarnings_ < maxWarnings_ ) {
209  edm::LogInfo("PFRecoTauDiscriminationAgainstMuon2::discriminate")
210  << "Jet associated to Tau: Pt = " << pfTau->pt() << ", eta = " << pfTau->eta() << ", phi = " << pfTau->phi() << " has area = " << jetArea << " !!" ;
211  ++numWarnings_;
212  }
213  dRmatch = 0.1;
214  }
215  }
216  if ( dR < dRmatch ) {
217  if ( verbosity_ ) edm::LogPrint("PFTauAgainstMuon2") << " overlaps with tau, dR = " << dR ;
218  countMatches(*muon, numMatchesDT, numMatchesCSC, numMatchesRPC);
219  countHits(*muon, numHitsDT, numHitsCSC, numHitsRPC);
220  }
221  }
222  }
223 
224  int numStationsWithMatches = 0;
225  for ( int iStation = 0; iStation < 4; ++iStation ) {
226  if ( numMatchesDT[iStation] > 0 && !maskMatchesDT_[iStation] ) ++numStationsWithMatches;
227  if ( numMatchesCSC[iStation] > 0 && !maskMatchesCSC_[iStation] ) ++numStationsWithMatches;
228  if ( numMatchesRPC[iStation] > 0 && !maskMatchesRPC_[iStation] ) ++numStationsWithMatches;
229  }
230 
231  int numLast2StationsWithHits = 0;
232  for ( int iStation = 2; iStation < 4; ++iStation ) {
233  if ( numHitsDT[iStation] > 0 && !maskHitsDT_[iStation] ) ++numLast2StationsWithHits;
234  if ( numHitsCSC[iStation] > 0 && !maskHitsCSC_[iStation] ) ++numLast2StationsWithHits;
235  if ( numHitsRPC[iStation] > 0 && !maskHitsRPC_[iStation] ) ++numLast2StationsWithHits;
236  }
237 
238  if ( verbosity_ ) {
239  edm::LogPrint("PFTauAgainstMuon2") << "numMatchesDT = " << format_vint(numMatchesDT) ;
240  edm::LogPrint("PFTauAgainstMuon2") << "numMatchesCSC = " << format_vint(numMatchesCSC) ;
241  edm::LogPrint("PFTauAgainstMuon2") << "numMatchesRPC = " << format_vint(numMatchesRPC) ;
242  edm::LogPrint("PFTauAgainstMuon2") << " --> numStationsWithMatches = " << numStationsWithMatches ;
243  edm::LogPrint("PFTauAgainstMuon2") << "numHitsDT = " << format_vint(numHitsDT) ;
244  edm::LogPrint("PFTauAgainstMuon2") << "numHitsCSC = " << format_vint(numHitsCSC) ;
245  edm::LogPrint("PFTauAgainstMuon2") << "numHitsRPC = " << format_vint(numHitsRPC) ;
246  edm::LogPrint("PFTauAgainstMuon2") << " --> numLast2StationsWithHits = " << numLast2StationsWithHits ;
247  }
248 
249  bool passesCaloMuonVeto = true;
250  if ( pfLeadChargedHadron.isNonnull() ) {
251  double energyECALplusHCAL = pfLeadChargedHadron->ecalEnergy() + pfLeadChargedHadron->hcalEnergy();
252  if ( verbosity_ ) {
253  if ( pfLeadChargedHadron->trackRef().isNonnull() ) {
254  edm::LogPrint("PFTauAgainstMuon2") << "decayMode = " << pfTau->decayMode() << ", energy(ECAL+HCAL) = " << energyECALplusHCAL << ", leadPFChargedHadronP = " << pfLeadChargedHadron->trackRef()->p() ;
255  } else if ( pfLeadChargedHadron->gsfTrackRef().isNonnull() ) {
256  edm::LogPrint("PFTauAgainstMuon2") << "decayMode = " << pfTau->decayMode() << ", energy(ECAL+HCAL) = " << energyECALplusHCAL << ", leadPFChargedHadronP = " << pfLeadChargedHadron->gsfTrackRef()->p() ;
257  }
258  }
259  const reco::Track* leadTrack = nullptr;
260  if ( pfLeadChargedHadron->trackRef().isNonnull() ) leadTrack = pfLeadChargedHadron->trackRef().get();
261  else if ( pfLeadChargedHadron->gsfTrackRef().isNonnull() ) leadTrack = pfLeadChargedHadron->gsfTrackRef().get();
262  if ( pfTau->decayMode() == 0 && leadTrack && energyECALplusHCAL < (hop_*leadTrack->p()) ) passesCaloMuonVeto = false;
263  }
264 
265  double discriminatorValue = 0.;
266  if ( discriminatorOption_ == kLoose && numStationsWithMatches <= maxNumberOfMatches_ ) discriminatorValue = 1.;
267  else if ( discriminatorOption_ == kMedium && numStationsWithMatches <= maxNumberOfMatches_ && numLast2StationsWithHits <= maxNumberOfHitsLast2Stations_ ) discriminatorValue = 1.;
268  else if ( discriminatorOption_ == kTight && numStationsWithMatches <= maxNumberOfMatches_ && numLast2StationsWithHits <= maxNumberOfHitsLast2Stations_ && passesCaloMuonVeto ) discriminatorValue = 1.;
269  else if ( discriminatorOption_ == kCustom ) {
270  bool pass = true;
271  if ( maxNumberOfMatches_ >= 0 && numStationsWithMatches > maxNumberOfMatches_ ) pass = false;
272  if ( maxNumberOfHitsLast2Stations_ >= 0 && numLast2StationsWithHits > maxNumberOfHitsLast2Stations_ ) pass = false;
273  if ( doCaloMuonVeto_ && !passesCaloMuonVeto ) pass = false;
274  discriminatorValue = pass ? 1.: 0.;
275  }
276  if ( verbosity_ ) edm::LogPrint("PFTauAgainstMuon2") << "--> returning discriminatorValue = " << discriminatorValue ;
277 
278  return discriminatorValue;
279 }
280 
281 }
282 
283 DEFINE_FWK_MODULE(PFRecoTauDiscriminationAgainstMuon2);
double p() const
momentum vector magnitude
Definition: TrackBase.h:615
const double Pi
T getParameter(std::string const &) const
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:253
double eta() const final
momentum pseudorapidity
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
T const * get() const
Returns C++ pointer to the item.
Definition: Ptr.h:159
bool exists(std::string const &parameterName) const
checks if a parameter exists
double pt() const final
transverse momentum
key_type key() const
Accessor for product key.
Definition: Ref.h:265
T Min(T a, T b)
Definition: MathUtil.h:39
double vint[400]
static bool muonCSCHitFilter(uint16_t pattern)
Definition: HitPattern.h:641
virtual void beginEvent(const edm::Event &, const edm::EventSetup &)
static uint32_t getHitType(uint16_t pattern)
Definition: HitPattern.h:734
Long64_t numEntries(TFile *hdl, std::string const &trname)
Definition: CollUtil.cc:50
int numberOfAllHits(HitCategory category) const
Definition: HitPattern.h:808
const LorentzVector & p4() const final
four-momentum Lorentz vector
Definition: LeafCandidate.h:99
virtual TrackRef outerTrack() const
reference to Track reconstructed in the muon detector only
Definition: Muon.h:51
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:168
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
static bool muonHitFilter(uint16_t pattern)
Definition: HitPattern.h:683
virtual double discriminate(const TauRef &tau) const =0
static constexpr int RPC
Definition: MuonSubdetId.h:14
std::vector< MuonChamberMatch > & matches()
get muon matching information
Definition: Muon.h:144
static bool muonDTHitFilter(uint16_t pattern)
Definition: HitPattern.h:631
static uint16_t getMuonStation(uint16_t pattern)
Muon station (1-4). Only valid for muon patterns, of course. only for patterns from muon...
Definition: HitPattern.h:743
static constexpr int DT
Definition: MuonSubdetId.h:12
uint16_t getHitPattern(HitCategory category, int position) const
Definition: HitPattern.h:516
static bool muonRPCHitFilter(uint16_t pattern)
Definition: HitPattern.h:651
static constexpr int CSC
Definition: MuonSubdetId.h:13
double phi() const final
momentum azimuthal angle