CMS 3D CMS Logo

PFRecoTauDiscriminationByMVAIsolationRun2.cc
Go to the documentation of this file.
1 
11 
17 
19 
27 
31 
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("PFRecoTauDiscriminationByIsolationMVA2::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("PFRecoTauDiscriminationByIsolationMVA2::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  category_output_()
74  {
75  mvaName_ = cfg.getParameter<std::string>("mvaName");
76  loadMVAfromDB_ = cfg.exists("loadMVAfromDB") ? cfg.getParameter<bool>("loadMVAfromDB") : false;
77  if ( !loadMVAfromDB_ ) {
78  if(cfg.exists("inputFileName")){
79  inputFileName_ = cfg.getParameter<edm::FileInPath>("inputFileName");
80  }else throw cms::Exception("MVA input not defined") << "Requested to load tau MVA input from ROOT file but no file provided in cfg file";
81  }
82  std::string mvaOpt_string = cfg.getParameter<std::string>("mvaOpt");
83  if ( mvaOpt_string == "oldDMwoLT" ) mvaOpt_ = kOldDMwoLT;
84  else if ( mvaOpt_string == "oldDMwLT" ) mvaOpt_ = kOldDMwLT;
85  else if ( mvaOpt_string == "newDMwoLT" ) mvaOpt_ = kNewDMwoLT;
86  else if ( mvaOpt_string == "newDMwLT" ) mvaOpt_ = kNewDMwLT;
87  else if ( mvaOpt_string == "DBoldDMwLT" ) mvaOpt_ = kDBoldDMwLT;
88  else if ( mvaOpt_string == "DBnewDMwLT" ) mvaOpt_ = kDBnewDMwLT;
89  else if ( mvaOpt_string == "PWoldDMwLT" ) mvaOpt_ = kPWoldDMwLT;
90  else if ( mvaOpt_string == "PWnewDMwLT" ) mvaOpt_ = kPWnewDMwLT;
91  else if ( mvaOpt_string == "DBoldDMwLTwGJ" ) mvaOpt_ = kDBoldDMwLTwGJ;
92  else if ( mvaOpt_string == "DBnewDMwLTwGJ" ) mvaOpt_ = kDBnewDMwLTwGJ;
93  else throw cms::Exception("PFRecoTauDiscriminationByMVAIsolationRun2")
94  << " Invalid Configuration Parameter 'mvaOpt' = " << mvaOpt_string << " !!\n";
95 
96  if ( mvaOpt_ == kOldDMwoLT || mvaOpt_ == kNewDMwoLT ) mvaInput_ = new float[6];
97  else if ( mvaOpt_ == kOldDMwLT || mvaOpt_ == kNewDMwLT ) mvaInput_ = new float[12];
98  else if ( mvaOpt_ == kDBoldDMwLT || mvaOpt_ == kDBnewDMwLT ||
99  mvaOpt_ == kPWoldDMwLT || mvaOpt_ == kPWnewDMwLT ||
100  mvaOpt_ == kDBoldDMwLTwGJ || mvaOpt_ == kDBnewDMwLTwGJ) mvaInput_ = new float[23];
101  else assert(0);
102 
103  TauTransverseImpactParameters_token = consumes<PFTauTIPAssociationByRef>(cfg.getParameter<edm::InputTag>("srcTauTransverseImpactParameters"));
104 
105  ChargedIsoPtSum_token = consumes<reco::PFTauDiscriminator>(cfg.getParameter<edm::InputTag>("srcChargedIsoPtSum"));
106  NeutralIsoPtSum_token = consumes<reco::PFTauDiscriminator>(cfg.getParameter<edm::InputTag>("srcNeutralIsoPtSum"));
107  PUcorrPtSum_token = consumes<reco::PFTauDiscriminator>(cfg.getParameter<edm::InputTag>("srcPUcorrPtSum"));
108  PhotonPtSumOutsideSignalCone_token = consumes<reco::PFTauDiscriminator>(cfg.getParameter<edm::InputTag>("srcPhotonPtSumOutsideSignalCone"));
109  FootprintCorrection_token = consumes<reco::PFTauDiscriminator>(cfg.getParameter<edm::InputTag>("srcFootprintCorrection"));
110 
111  verbosity_ = ( cfg.exists("verbosity") ) ?
112  cfg.getParameter<int>("verbosity") : 0;
113 
114  produces<PFTauDiscriminator>("category");
115  }
116 
117  void beginEvent(const edm::Event&, const edm::EventSetup&) override;
118 
119  double discriminate(const PFTauRef&) const override;
120 
121  void endEvent(edm::Event&) override;
122 
124  {
125  if(!loadMVAfromDB_) delete mvaReader_;
126  delete[] mvaInput_;
127  for ( std::vector<TFile*>::iterator it = inputFilesToDelete_.begin();
128  it != inputFilesToDelete_.end(); ++it ) {
129  delete (*it);
130  }
131  }
132 
133  private:
134 
136 
141  enum { kOldDMwoLT, kOldDMwLT, kNewDMwoLT, kNewDMwLT, kDBoldDMwLT, kDBnewDMwLT, kPWoldDMwLT, kPWnewDMwLT, kDBoldDMwLTwGJ, kDBnewDMwLTwGJ };
142  int mvaOpt_;
143  float* mvaInput_;
144 
148 
159 
161  std::unique_ptr<PFTauDiscriminator> category_output_;
162 
163  std::vector<TFile*> inputFilesToDelete_;
165 
167 };
168 
170 {
171  if ( !mvaReader_ ) {
172  if ( loadMVAfromDB_ ) {
173  mvaReader_ = loadMVAfromDB(es, mvaName_);
174  } else {
175  mvaReader_ = loadMVAfromFile(inputFileName_, mvaName_, inputFilesToDelete_);
176  }
177  }
178 
179  evt.getByToken(TauTransverseImpactParameters_token, tauLifetimeInfos);
180 
181  evt.getByToken(ChargedIsoPtSum_token, chargedIsoPtSums_);
182  evt.getByToken(NeutralIsoPtSum_token, neutralIsoPtSums_);
183  evt.getByToken(PUcorrPtSum_token, puCorrPtSums_);
184  evt.getByToken(PhotonPtSumOutsideSignalCone_token, photonPtSumOutsideSignalCone_);
185  evt.getByToken(FootprintCorrection_token, footprintCorrection_);
186 
187  evt.getByToken(Tau_token, taus_);
188  category_output_.reset(new PFTauDiscriminator(TauRefProd(taus_)));
189 }
190 
192 {
193  // CV: define dummy category index in order to use RecoTauDiscriminantCutMultiplexer module to appy WP cuts
194  double category = 0.;
195  category_output_->setValue(tauIndex_, category);
196 
197  // CV: computation of MVA value requires presence of leading charged hadron
198  if ( tau->leadPFChargedHadrCand().isNull() ) return 0.;
199 
200  int tauDecayMode = tau->decayMode();
201 
202  if ( ((mvaOpt_ == kOldDMwoLT || mvaOpt_ == kOldDMwLT || mvaOpt_ == kDBoldDMwLT || mvaOpt_ == kPWoldDMwLT || mvaOpt_ == kDBoldDMwLTwGJ)
203  && (tauDecayMode == 0 || tauDecayMode == 1 || tauDecayMode == 2 || tauDecayMode == 10))
204  ||
205  ((mvaOpt_ == kNewDMwoLT || mvaOpt_ == kNewDMwLT || mvaOpt_ == kDBnewDMwLT || mvaOpt_ == kPWnewDMwLT || mvaOpt_ == kDBnewDMwLTwGJ)
206  && (tauDecayMode == 0 || tauDecayMode == 1 || tauDecayMode == 2 || tauDecayMode == 5 || tauDecayMode == 6 || tauDecayMode == 10 || tauDecayMode == 11))
207  ) {
208 
209  float chargedIsoPtSum = (*chargedIsoPtSums_)[tau];
210  float neutralIsoPtSum = (*neutralIsoPtSums_)[tau];
211  float puCorrPtSum = (*puCorrPtSums_)[tau];
212  float photonPtSumOutsideSignalCone = (*photonPtSumOutsideSignalCone_)[tau];
213  float footprintCorrection = (*footprintCorrection_)[tau];
214 
215  const reco::PFTauTransverseImpactParameter& tauLifetimeInfo = *(*tauLifetimeInfos)[tau];
216 
217  float decayDistX = tauLifetimeInfo.flightLength().x();
218  float decayDistY = tauLifetimeInfo.flightLength().y();
219  float decayDistZ = tauLifetimeInfo.flightLength().z();
220  float decayDistMag = std::sqrt(decayDistX*decayDistX + decayDistY*decayDistY + decayDistZ*decayDistZ);
221 
222  float nPhoton = (float)clusterVariables_.tau_n_photons_total(*tau);
223  float ptWeightedDetaStrip = clusterVariables_.tau_pt_weighted_deta_strip(*tau, tauDecayMode);
224  float ptWeightedDphiStrip = clusterVariables_.tau_pt_weighted_dphi_strip(*tau, tauDecayMode);
225  float ptWeightedDrSignal = clusterVariables_.tau_pt_weighted_dr_signal(*tau, tauDecayMode);
226  float ptWeightedDrIsolation = clusterVariables_.tau_pt_weighted_dr_iso(*tau, tauDecayMode);
227  float leadingTrackChi2 = clusterVariables_.tau_leadTrackChi2(*tau);
228  float eRatio = clusterVariables_.tau_Eratio(*tau);
229 
230  // Difference between measured and maximally allowed Gottfried-Jackson angle
231  float gjAngleDiff = -999;
232  if ( tauDecayMode == 10 ) {
233  double mTau = 1.77682;
234  double mAOne = tau->p4().M();
235  double pAOneMag = tau->p();
236  double argumentThetaGJmax = (std::pow(mTau,2) - std::pow(mAOne,2) ) / ( 2 * mTau * pAOneMag );
237  double argumentThetaGJmeasured = ( tau->p4().px() * decayDistX + tau->p4().py() * decayDistY + tau->p4().pz() * decayDistZ ) / ( pAOneMag * decayDistMag );
238  if ( std::abs(argumentThetaGJmax) <= 1. && std::abs(argumentThetaGJmeasured) <= 1. ) {
239  double thetaGJmax = std::asin( argumentThetaGJmax );
240  double thetaGJmeasured = std::acos( argumentThetaGJmeasured );
241  gjAngleDiff = thetaGJmeasured - thetaGJmax;
242  }
243  }
244 
245  if ( mvaOpt_ == kOldDMwoLT || mvaOpt_ == kNewDMwoLT ) {
246  mvaInput_[0] = std::log(std::max(1.f, (float)tau->pt()));
247  mvaInput_[1] = std::abs((float)tau->eta());
248  mvaInput_[2] = std::log(std::max(1.e-2f, chargedIsoPtSum));
249  mvaInput_[3] = std::log(std::max(1.e-2f, neutralIsoPtSum - 0.125f*puCorrPtSum));
250  mvaInput_[4] = std::log(std::max(1.e-2f, puCorrPtSum));
251  mvaInput_[5] = tauDecayMode;
252  } else if ( mvaOpt_ == kOldDMwLT || mvaOpt_ == kNewDMwLT ) {
253  mvaInput_[0] = std::log(std::max(1.f, (float)tau->pt()));
254  mvaInput_[1] = std::abs((float)tau->eta());
255  mvaInput_[2] = std::log(std::max(1.e-2f, chargedIsoPtSum));
256  mvaInput_[3] = std::log(std::max(1.e-2f, neutralIsoPtSum - 0.125f*puCorrPtSum));
257  mvaInput_[4] = std::log(std::max(1.e-2f, puCorrPtSum));
258  mvaInput_[5] = tauDecayMode;
259  mvaInput_[6] = std::copysign(+1.f, (float)tauLifetimeInfo.dxy());
260  mvaInput_[7] = std::sqrt(std::abs(std::min(1.f, (float)tauLifetimeInfo.dxy())));
261  mvaInput_[8] = std::min(10.f, std::abs((float)tauLifetimeInfo.dxy_Sig()));
262  mvaInput_[9] = ( tauLifetimeInfo.hasSecondaryVertex() ) ? 1. : 0.;
263  mvaInput_[10] = std::sqrt(decayDistMag);
264  mvaInput_[11] = std::min(10.f, (float)tauLifetimeInfo.flightLengthSig());
265  } else if ( mvaOpt_ == kDBoldDMwLT || mvaOpt_ == kDBnewDMwLT ) {
266  mvaInput_[0] = std::log(std::max(1.f, (float)tau->pt()));
267  mvaInput_[1] = std::abs((float)tau->eta());
268  mvaInput_[2] = std::log(std::max(1.e-2f, chargedIsoPtSum));
269  mvaInput_[3] = std::log(std::max(1.e-2f, neutralIsoPtSum));
270  mvaInput_[4] = std::log(std::max(1.e-2f, puCorrPtSum));
271  mvaInput_[5] = std::log(std::max(1.e-2f, photonPtSumOutsideSignalCone));
272  mvaInput_[6] = tauDecayMode;
273  mvaInput_[7] = std::min(30.f, nPhoton);
274  mvaInput_[8] = std::min(0.5f, ptWeightedDetaStrip);
275  mvaInput_[9] = std::min(0.5f, ptWeightedDphiStrip);
276  mvaInput_[10] = std::min(0.5f, ptWeightedDrSignal);
277  mvaInput_[11] = std::min(0.5f, ptWeightedDrIsolation);
278  mvaInput_[12] = std::min(100.f, leadingTrackChi2);
279  mvaInput_[13] = std::min(1.f, eRatio);
280  mvaInput_[14] = std::copysign(+1.f, (float)tauLifetimeInfo.dxy());
281  mvaInput_[15] = std::sqrt(std::min(1.f, std::abs((float)tauLifetimeInfo.dxy())));
282  mvaInput_[16] = std::min(10.f, std::abs((float)tauLifetimeInfo.dxy_Sig()));
283  mvaInput_[17] = std::copysign(+1.f, (float)tauLifetimeInfo.ip3d());
284  mvaInput_[18] = std::sqrt(std::min(1.f, std::abs((float)tauLifetimeInfo.ip3d())));
285  mvaInput_[19] = std::min(10.f, std::abs((float)tauLifetimeInfo.ip3d_Sig()));
286  mvaInput_[20] = ( tauLifetimeInfo.hasSecondaryVertex() ) ? 1. : 0.;
287  mvaInput_[21] = std::sqrt(decayDistMag);
288  mvaInput_[22] = std::min(10.f, (float)tauLifetimeInfo.flightLengthSig());
289  } else if ( mvaOpt_ == kPWoldDMwLT || mvaOpt_ == kPWnewDMwLT ) {
290  mvaInput_[0] = std::log(std::max(1.f, (float)tau->pt()));
291  mvaInput_[1] = std::abs((float)tau->eta());
292  mvaInput_[2] = std::log(std::max(1.e-2f, chargedIsoPtSum));
293  mvaInput_[3] = std::log(std::max(1.e-2f, neutralIsoPtSum));
294  mvaInput_[4] = std::log(std::max(1.e-2f, footprintCorrection));
295  mvaInput_[5] = std::log(std::max(1.e-2f, photonPtSumOutsideSignalCone));
296  mvaInput_[6] = tauDecayMode;
297  mvaInput_[7] = std::min(30.f, nPhoton);
298  mvaInput_[8] = std::min(0.5f, ptWeightedDetaStrip);
299  mvaInput_[9] = std::min(0.5f, ptWeightedDphiStrip);
300  mvaInput_[10] = std::min(0.5f, ptWeightedDrSignal);
301  mvaInput_[11] = std::min(0.5f, ptWeightedDrIsolation);
302  mvaInput_[12] = std::min(100.f, leadingTrackChi2);
303  mvaInput_[13] = std::min(1.f, eRatio);
304  mvaInput_[14] = std::copysign(+1.f, (float)tauLifetimeInfo.dxy());
305  mvaInput_[15] = std::sqrt(std::min(1.f, std::abs((float)tauLifetimeInfo.dxy())));
306  mvaInput_[16] = std::min(10.f, std::abs((float)tauLifetimeInfo.dxy_Sig()));
307  mvaInput_[17] = std::copysign(+1.f, (float)tauLifetimeInfo.ip3d());
308  mvaInput_[18] = std::sqrt(std::min(1.f, std::abs((float)tauLifetimeInfo.ip3d())));
309  mvaInput_[19] = std::min(10.f, std::abs((float)tauLifetimeInfo.ip3d_Sig()));
310  mvaInput_[20] = ( tauLifetimeInfo.hasSecondaryVertex() ) ? 1. : 0.;
311  mvaInput_[21] = std::sqrt(decayDistMag);
312  mvaInput_[22] = std::min(10.f, (float)tauLifetimeInfo.flightLengthSig());
313  } else if ( mvaOpt_ == kDBoldDMwLTwGJ || mvaOpt_ == kDBnewDMwLTwGJ ) {
314  mvaInput_[0] = std::log(std::max(1.f, (float)tau->pt()));
315  mvaInput_[1] = std::abs((float)tau->eta());
316  mvaInput_[2] = std::log(std::max(1.e-2f, chargedIsoPtSum));
317  mvaInput_[3] = std::log(std::max(1.e-2f, neutralIsoPtSum));
318  mvaInput_[4] = std::log(std::max(1.e-2f, puCorrPtSum));
319  mvaInput_[5] = std::log(std::max(1.e-2f, photonPtSumOutsideSignalCone));
320  mvaInput_[6] = tauDecayMode;
321  mvaInput_[7] = std::min(30.f, nPhoton);
322  mvaInput_[8] = std::min(0.5f, ptWeightedDetaStrip);
323  mvaInput_[9] = std::min(0.5f, ptWeightedDphiStrip);
324  mvaInput_[10] = std::min(0.5f, ptWeightedDrSignal);
325  mvaInput_[11] = std::min(0.5f, ptWeightedDrIsolation);
326  mvaInput_[12] = std::min(1.f, eRatio);
327  mvaInput_[13] = std::copysign(+1.f, (float)tauLifetimeInfo.dxy());
328  mvaInput_[14] = std::sqrt(std::min(1.f, std::abs((float)tauLifetimeInfo.dxy())));
329  mvaInput_[15] = std::min(10.f, std::abs((float)tauLifetimeInfo.dxy_Sig()));
330  mvaInput_[16] = std::copysign(+1.f, (float)tauLifetimeInfo.ip3d());
331  mvaInput_[17] = std::sqrt(std::min(1.f, std::abs((float)tauLifetimeInfo.ip3d())));
332  mvaInput_[18] = std::min(10.f, std::abs((float)tauLifetimeInfo.ip3d_Sig()));
333  mvaInput_[19] = ( tauLifetimeInfo.hasSecondaryVertex() ) ? 1. : 0.;
334  mvaInput_[20] = std::sqrt(decayDistMag);
335  mvaInput_[21] = std::min(10.f, (float)tauLifetimeInfo.flightLengthSig());
336  mvaInput_[22] = std::max(-1.f, gjAngleDiff);
337  }
338 
339  double mvaValue = mvaReader_->GetClassifier(mvaInput_);
340  if ( verbosity_ ) {
341  edm::LogPrint("PFTauDiscByMVAIsol2") << "<PFRecoTauDiscriminationByMVAIsolationRun2::discriminate>:";
342  edm::LogPrint("PFTauDiscByMVAIsol2") << " tau: Pt = " << tau->pt() << ", eta = " << tau->eta();
343  edm::LogPrint("PFTauDiscByMVAIsol2") << " isolation: charged = " << chargedIsoPtSum << ", neutral = " << neutralIsoPtSum << ", PUcorr = " << puCorrPtSum;
344  edm::LogPrint("PFTauDiscByMVAIsol2") << " decay mode = " << tauDecayMode;
345  edm::LogPrint("PFTauDiscByMVAIsol2") << " impact parameter: distance = " << tauLifetimeInfo.dxy() << ", significance = " << tauLifetimeInfo.dxy_Sig();
346  edm::LogPrint("PFTauDiscByMVAIsol2") << " has decay vertex = " << tauLifetimeInfo.hasSecondaryVertex() << ":"
347  << " distance = " << decayDistMag << ", significance = " << tauLifetimeInfo.flightLengthSig();
348  edm::LogPrint("PFTauDiscByMVAIsol2") << "--> mvaValue = " << mvaValue;
349  }
350  return mvaValue;
351  } else {
352  return -1.;
353  }
354 }
355 
357 {
358  // add all category indices to event
359  evt.put(std::move(category_output_), "category");
360 }
361 
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:137
edm::RefProd< TauCollection > TauRefProd
Definition: Tau.h:39
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
edm::AssociationVector< reco::PFTauRefProd, std::vector< reco::PFTauTransverseImpactParameterRef > > PFTauTIPAssociationByRef
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
edm::EDGetTokenT< reco::PFTauDiscriminator > NeutralIsoPtSum_token
bool exists(std::string const &parameterName) const
checks if a parameter exists
#define nullptr
edm::EDGetTokenT< reco::PFTauDiscriminator > PhotonPtSumOutsideSignalCone_token
edm::EDGetTokenT< reco::PFTauDiscriminator > FootprintCorrection_token
edm::EDGetTokenT< PFTauTIPAssociationByRef > TauTransverseImpactParameters_token
T sqrt(T t)
Definition: SSEVec.h:18
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
T min(T a, T b)
Definition: MathUtil.h:58
LocationCode location() const
Where was the file found?
Definition: FileInPath.cc:191
bool isNull() const
Checks for null.
Definition: Ref.h:250
edm::EDGetTokenT< reco::PFTauDiscriminator > ChargedIsoPtSum_token
fixed size matrix
T get() const
Definition: EventSetup.h:63
void beginEvent(const edm::Event &, const edm::EventSetup &) override
std::string fullPath() const
Definition: FileInPath.cc:197
edm::Handle< reco::PFTauDiscriminator > photonPtSumOutsideSignalCone_
T const * product() const
Definition: ESHandle.h:86
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
def move(src, dest)
Definition: eostools.py:510
edm::EDGetTokenT< reco::PFTauDiscriminator > PUcorrPtSum_token