CMS 3D CMS Logo

PFRecoTauDiscriminationAgainstMuonMVA.cc
Go to the documentation of this file.
1 
11 
17 
19 
26 
30 
31 #include <TMath.h>
32 #include <TFile.h>
33 
34 #include <iostream>
35 
36 using namespace reco;
37 
38 namespace
39 {
40  const GBRForest* loadMVAfromFile(const edm::FileInPath& inputFileName, const std::string& mvaName, std::vector<TFile*>& inputFilesToDelete)
41  {
42  if ( inputFileName.location() == edm::FileInPath::Unknown ) throw cms::Exception("PFRecoTauDiscriminationAgainstMuonMVA::loadMVA")
43  << " Failed to find File = " << inputFileName << " !!\n";
44  TFile* inputFile = new TFile(inputFileName.fullPath().data());
45 
46  //const GBRForest* mva = dynamic_cast<GBRForest*>(inputFile->Get(mvaName.data())); // CV: dynamic_cast<GBRForest*> fails for some reason ?!
47  const GBRForest* mva = (GBRForest*)inputFile->Get(mvaName.data());
48  if ( !mva )
49  throw cms::Exception("PFRecoTauDiscriminationAgainstMuonMVA::loadMVA")
50  << " Failed to load MVA = " << mvaName.data() << " from file = " << inputFileName.fullPath().data() << " !!\n";
51 
52  inputFilesToDelete.push_back(inputFile);
53 
54  return mva;
55  }
56 
57  const GBRForest* loadMVAfromDB(const edm::EventSetup& es, const std::string& mvaName)
58  {
60  es.get<GBRWrapperRcd>().get(mvaName, mva);
61  return mva.product();
62  }
63 
64 
66 {
67  public:
70  moduleLabel_(cfg.getParameter<std::string>("@module_label")),
71  mvaReader_(nullptr),
72  mvaInput_(nullptr)
73  {
74  mvaName_ = cfg.getParameter<std::string>("mvaName");
75  loadMVAfromDB_ = cfg.exists("loadMVAfromDB") ? cfg.getParameter<bool>("loadMVAfromDB") : false;
76  if ( !loadMVAfromDB_ ) {
77  if(cfg.exists("inputFileName")){
78  inputFileName_ = cfg.getParameter<edm::FileInPath>("inputFileName");
79  }else throw cms::Exception("MVA input not defined") << "Requested to load tau MVA input from ROOT file but no file provided in cfg file";
80  }
81  mvaInput_ = new float[11];
82 
83  srcMuons_ = cfg.getParameter<edm::InputTag>("srcMuons");
84  Muons_token=consumes<reco::MuonCollection>(srcMuons_);
85  dRmuonMatch_ = cfg.getParameter<double>("dRmuonMatch");
86 
87  verbosity_ = ( cfg.exists("verbosity") ) ?
88  cfg.getParameter<int>("verbosity") : 0;
89 
90  produces<PFTauDiscriminator>("category");
91  }
92 
93  void beginEvent(const edm::Event&, const edm::EventSetup&) override;
94 
95  double discriminate(const PFTauRef&) const override;
96 
97  void endEvent(edm::Event&) override;
98 
100  {
101  if ( !loadMVAfromDB_ ) delete mvaReader_;
102  delete[] mvaInput_;
103  for ( std::vector<TFile*>::iterator it = inputFilesToDelete_.begin();
104  it != inputFilesToDelete_.end(); ++it ) {
105  delete (*it);
106  }
107  }
108 
109  private:
110 
111  std::string moduleLabel_;
112 
113  std::string mvaName_;
114  bool loadMVAfromDB_;
115  edm::FileInPath inputFileName_;
116  const GBRForest* mvaReader_;
117  float* mvaInput_;
118 
119  edm::InputTag srcMuons_;
122  double dRmuonMatch_;
123 
125  std::unique_ptr<PFTauDiscriminator> category_output_;
126 
127  std::vector<TFile*> inputFilesToDelete_;
128 
129  int verbosity_;
130 };
131 
133 {
134  if ( !mvaReader_ ) {
135  if ( loadMVAfromDB_ ) {
136  mvaReader_ = loadMVAfromDB(es, mvaName_);
137  } else {
138  mvaReader_ = loadMVAfromFile(inputFileName_, mvaName_, inputFilesToDelete_);
139  }
140  }
141 
142  evt.getByToken(Muons_token, muons_);
143 
144  evt.getByToken(Tau_token, taus_);
145  category_output_.reset(new PFTauDiscriminator(TauRefProd(taus_)));
146 }
147 
148 namespace
149 {
150  void countHits(const reco::Muon& muon, std::vector<int>& numHitsDT, std::vector<int>& numHitsCSC, std::vector<int>& numHitsRPC)
151  {
152  if ( muon.outerTrack().isNonnull() ) {
153  const reco::HitPattern &muonHitPattern = muon.outerTrack()->hitPattern();
154  for (int iHit = 0; iHit < muonHitPattern.numberOfAllHits(HitPattern::TRACK_HITS); ++iHit) {
155  uint32_t hit = muonHitPattern.getHitPattern(HitPattern::TRACK_HITS, iHit);
156  if ( hit == 0 ) break;
157  if ( muonHitPattern.muonHitFilter(hit) && (muonHitPattern.getHitType(hit) == TrackingRecHit::valid || muonHitPattern.getHitType(hit) == TrackingRecHit::bad) ) {
158  int muonStation = muonHitPattern.getMuonStation(hit) - 1; // CV: map into range 0..3
159  if ( muonStation >= 0 && muonStation < 4 ) {
160  if ( muonHitPattern.muonDTHitFilter(hit) ) ++numHitsDT[muonStation];
161  else if ( muonHitPattern.muonCSCHitFilter(hit) ) ++numHitsCSC[muonStation];
162  else if ( muonHitPattern.muonRPCHitFilter(hit) ) ++numHitsRPC[muonStation];
163  }
164  }
165  }
166  }
167  }
168 }
169 
171 {
172  if ( verbosity_ ) {
173  edm::LogPrint("PFTauAgainstMuonMVA") << "<PFRecoTauDiscriminationAgainstMuonMVA::discriminate>:";
174  edm::LogPrint("PFTauAgainstMuonMVA") << " moduleLabel = " << moduleLabel_;
175  }
176 
177  // CV: define dummy category index in order to use RecoTauDiscriminantCutMultiplexer module to appy WP cuts
178  double category = 0.;
179  category_output_->setValue(tauIndex_, category);
180 
181  // CV: computation of anti-muon MVA value requires presence of leading charged hadron
182  if ( tau->leadPFChargedHadrCand().isNull() ) return 0.;
183 
184  mvaInput_[0] = TMath::Abs(tau->eta());
185  double tauCaloEnECAL = 0.;
186  double tauCaloEnHCAL = 0.;
187  const std::vector<reco::PFCandidatePtr>& tauSignalPFCands = tau->signalPFCands();
188  for ( std::vector<reco::PFCandidatePtr>::const_iterator tauSignalPFCand = tauSignalPFCands.begin();
189  tauSignalPFCand != tauSignalPFCands.end(); ++tauSignalPFCand ) {
190  tauCaloEnECAL += (*tauSignalPFCand)->ecalEnergy();
191  tauCaloEnHCAL += (*tauSignalPFCand)->hcalEnergy();
192  }
193  mvaInput_[1] = TMath::Sqrt(TMath::Max(0., tauCaloEnECAL));
194  mvaInput_[2] = TMath::Sqrt(TMath::Max(0., tauCaloEnHCAL));
195  mvaInput_[3] = tau->leadPFChargedHadrCand()->pt()/TMath::Max(1.,Double_t(tau->pt()));
196  mvaInput_[4] = TMath::Sqrt(TMath::Max(0., tau->leadPFChargedHadrCand()->ecalEnergy()));
197  mvaInput_[5] = TMath::Sqrt(TMath::Max(0., tau->leadPFChargedHadrCand()->hcalEnergy()));
198  int numMatches = 0;
199  std::vector<int> numHitsDT(4);
200  std::vector<int> numHitsCSC(4);
201  std::vector<int> numHitsRPC(4);
202  for ( int iStation = 0; iStation < 4; ++iStation ) {
203  numHitsDT[iStation] = 0;
204  numHitsCSC[iStation] = 0;
205  numHitsRPC[iStation] = 0;
206  }
207  if ( tau->leadPFChargedHadrCand().isNonnull() ) {
208  reco::MuonRef muonRef = tau->leadPFChargedHadrCand()->muonRef();
209  if ( muonRef.isNonnull() ) {
210  numMatches = muonRef->numberOfMatches(reco::Muon::NoArbitration);
211  countHits(*muonRef, numHitsDT, numHitsCSC, numHitsRPC);
212  }
213  }
214  size_t numMuons = muons_->size();
215  for ( size_t idxMuon = 0; idxMuon < numMuons; ++idxMuon ) {
216  reco::MuonRef muon(muons_, idxMuon);
217  if ( tau->leadPFChargedHadrCand().isNonnull() && tau->leadPFChargedHadrCand()->muonRef().isNonnull() && muon == tau->leadPFChargedHadrCand()->muonRef() ) {
218  continue;
219  }
220  double dR = deltaR(muon->p4(), tau->p4());
221  if ( dR < dRmuonMatch_ ) {
222  numMatches += muon->numberOfMatches(reco::Muon::NoArbitration);
223  countHits(*muon, numHitsDT, numHitsCSC, numHitsRPC);
224  }
225  }
226  mvaInput_[6] = numMatches;
227  mvaInput_[7] = numHitsDT[0] + numHitsCSC[0] + numHitsRPC[0];
228  mvaInput_[8] = numHitsDT[1] + numHitsCSC[1] + numHitsRPC[1];
229  mvaInput_[9] = numHitsDT[2] + numHitsCSC[2] + numHitsRPC[2];
230  mvaInput_[10] = numHitsDT[3] + numHitsCSC[3] + numHitsRPC[3];
231 
232  double mvaValue = mvaReader_->GetClassifier(mvaInput_);
233  if ( verbosity_ ) {
234  edm::LogPrint("PFTauAgainstMuonMVA") << "mvaValue = " << mvaValue;
235  }
236  return mvaValue;
237 }
238 
240 {
241  // add all category indices to event
242  evt.put(std::move(category_output_), "category");
243 }
244 
245 }
246 
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:136
edm::RefProd< TauCollection > TauRefProd
Definition: Tau.h:39
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:253
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:519
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
bool exists(std::string const &parameterName) const
checks if a parameter exists
#define nullptr
static bool muonCSCHitFilter(uint16_t pattern)
Definition: HitPattern.h:640
virtual void beginEvent(const edm::Event &, const edm::EventSetup &)
static uint32_t getHitType(uint16_t pattern)
Definition: HitPattern.h:733
T Abs(T a)
Definition: MathUtil.h:49
int numberOfAllHits(HitCategory category) const
Definition: HitPattern.h:807
auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:28
const LorentzVector & p4() const final
four-momentum Lorentz vector
Definition: LeafCandidate.h:99
LocationCode location() const
Where was the file found?
Definition: FileInPath.cc:191
bool isNull() const
Checks for null.
Definition: Ref.h:250
virtual TrackRef outerTrack() const
reference to Track reconstructed in the muon detector only
Definition: Muon.h:51
T Max(T a, T b)
Definition: MathUtil.h:44
static bool muonHitFilter(uint16_t pattern)
Definition: HitPattern.h:682
virtual double discriminate(const TauRef &tau) const =0
const T & get() const
Definition: EventSetup.h:59
int numberOfMatches(ArbitrationType type=SegmentAndTrackArbitration) const
get number of chambers with matched segments
static bool muonDTHitFilter(uint16_t pattern)
Definition: HitPattern.h:630
fixed size matrix
std::string fullPath() const
Definition: FileInPath.cc:197
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:742
uint16_t getHitPattern(HitCategory category, int position) const
Definition: HitPattern.h:515
static bool muonRPCHitFilter(uint16_t pattern)
Definition: HitPattern.h:650
T const * product() const
Definition: ESHandle.h:86
def move(src, dest)
Definition: eostools.py:510