CMS 3D CMS Logo

PhotonMVAEstimatorRun2Spring16NonTrig.cc
Go to the documentation of this file.
3 #include "TMVA/MethodBDT.h"
4 #include <vector>
5 
8  MethodName_("BDTG method"),
9  phoChargedIsolationLabel_(conf.getParameter<edm::InputTag>("phoChargedIsolation")),
10  phoPhotonIsolationLabel_(conf.getParameter<edm::InputTag>("phoPhotonIsolation")),
11  phoWorstChargedIsolationLabel_(conf.getParameter<edm::InputTag>("phoWorstChargedIsolation")),
12  rhoLabel_(conf.getParameter<edm::InputTag>("rho")),
13  effectiveAreas_( (conf.getParameter<edm::FileInPath>("effAreasConfigFile")).fullPath()),
14  phoIsoPtScalingCoeff_(conf.getParameter<std::vector<double >>("phoIsoPtScalingCoeff")),
15  phoIsoCutoff_(conf.getParameter<double>("phoIsoCutoff"))
16 {
17 
18  //
19  // Construct the MVA estimators
20  //
21  tag_ = conf.getParameter<std::string>("mvaTag");
22 
23  const std::vector <std::string> weightFileNames
24  = conf.getParameter<std::vector<std::string> >("weightFileNames");
25 
26  if( weightFileNames.size() != nCategories )
27  throw cms::Exception("MVA config failure: ")
28  << "wrong number of weightfiles" << std::endl;
29 
30  gbrForests_.clear();
31  // The method name is just a key to retrieve this method later, it is not
32  // a control parameter for a reader (the full definition of the MVA type and
33  // everything else comes from the xml weight files).
34 
35  // Create a TMVA reader object for each category
36  for(uint i=0; i<nCategories; i++){
37 
38  // Use unique_ptr so that all readers are properly cleaned up
39  // when the vector clear() is called in the destructor
40 
41  edm::FileInPath weightFile( weightFileNames[i] );
42  gbrForests_.push_back( createSingleReader(i, weightFile ) );
43 
44  }
45 
46 }
47 
50 }
51 
53 mvaValue(const edm::Ptr<reco::Candidate>& particle, const edm::Event& iEvent) const {
54 
55  const int iCategory = findCategory( particle );
56  const std::vector<float> vars = std::move( fillMVAVariables( particle, iEvent ) );
57 
58  const float result = gbrForests_.at(iCategory)->GetClassifier(vars.data());
59 
60  // DEBUG
61  const bool debug = false;
62  // The list of variables here must match EXACTLY the list and order in the
63  // packMVAVariables() call for barrel and endcap in this file.
64  if( debug ){
65  printf("Printout of the photon variable inputs for MVA:\n");
66  printf(" varSCPhi_ %f\n", vars[0] );
67  printf(" varR9_ %f\n", vars[1] );
68  printf(" varSieie_ %f\n", vars[2] );
69  printf(" varSieip_ %f\n", vars[3] );
70  printf(" varE2x2overE5x5_ %f\n", vars[4] );
71  printf(" varSCEta_ %f\n", vars[5] );
72  printf(" varRawE_ %f\n", vars[6] );
73  printf(" varSCEtaWidth_ %f\n", vars[7] );
74  printf(" varSCPhiWidth_ %f\n", vars[8] );
75  printf(" varRho_ %f\n", vars[9] );
76  if( !isEndcapCategory( iCategory ) ) {
77  printf(" varPhoIsoRaw_ %f\n", vars[10] );
78  } else {
79  printf(" varPhoIsoRawCorr_ %f\n", vars[10] ); // for endcap MVA only in 2016
80  }
81  printf(" varChIsoRaw_ %f\n", vars[11] );
82  printf(" varWorstChRaw_ %f\n", vars[12] );
83  if( isEndcapCategory( iCategory ) ) {
84  printf(" varESEnOverRawE_ %f\n", vars[13] ); // for endcap MVA only
85  printf(" varESEffSigmaRR_ %f\n", vars[14] ); // for endcap MVA only
86  }
87  }
88 
89  return result;
90 }
91 
93 
94  // Try to cast the particle into a reco particle.
95  // This should work for both reco and pat.
96  const edm::Ptr<reco::Photon> phoRecoPtr = ( edm::Ptr<reco::Photon> )particle;
97  if( phoRecoPtr.isNull() )
98  throw cms::Exception("MVA failure: ")
99  << " given particle is expected to be reco::Photon or pat::Photon," << std::endl
100  << " but appears to be neither" << std::endl;
101 
102  float eta = phoRecoPtr->superCluster()->eta();
103 
104  //
105  // Determine the category
106  //
107  int iCategory = UNDEFINED;
108  const float ebeeSplit = 1.479; // division between barrel and endcap
109 
110  if ( std::abs(eta) < ebeeSplit)
111  iCategory = CAT_EB;
112  else
113  iCategory = CAT_EE;
114 
115  return iCategory;
116 }
117 
120 
121  // For this specific MVA the function is trivial, but kept for possible
122  // future evolution to an MVA with more categories in eta
123  bool isEndcap = false;
124  if( category == CAT_EE )
125  isEndcap = true;
126 
127  return isEndcap;
128 }
129 
130 
131 std::unique_ptr<const GBRForest> PhotonMVAEstimatorRun2Spring16NonTrig::
132 createSingleReader(const int iCategory, const edm::FileInPath &weightFile){
133 
134  //
135  // Create the reader
136  //
137  TMVA::Reader tmpTMVAReader( "!Color:Silent:Error" );
138 
139  //
140  // Configure all variables and spectators. Note: the order and names
141  // must match what is found in the xml weights file!
142  //
143 
144  tmpTMVAReader.AddVariable("scPhi", &allMVAVars_.scPhi);
145  tmpTMVAReader.AddVariable("r9" , &allMVAVars_.varR9);
146  tmpTMVAReader.AddVariable("sigmaIetaIeta", &allMVAVars_.varSieie);
147  tmpTMVAReader.AddVariable("covIEtaIPhi", &allMVAVars_.varSieip);
148  tmpTMVAReader.AddVariable("s4", &allMVAVars_.varE2x2overE5x5);
149  tmpTMVAReader.AddVariable("scEta" , &allMVAVars_.varSCEta);
150  tmpTMVAReader.AddVariable("SCRawE" , &allMVAVars_.varRawE);
151  tmpTMVAReader.AddVariable("etaWidth", &allMVAVars_.varSCEtaWidth);
152  tmpTMVAReader.AddVariable("phiWidth", &allMVAVars_.varSCPhiWidth);
153  //Pileup
154  tmpTMVAReader.AddVariable("rho" , &allMVAVars_.varRho);
155  //EB only, because of loss of transparency in EE
156  if(!isEndcapCategory(iCategory)){
157  tmpTMVAReader.AddVariable("CITK_isoPhotons" , &allMVAVars_.varPhoIsoRaw);
158  }
159  else{
160  tmpTMVAReader.AddVariable("CITK_isoPhoCorrMax2p5", &allMVAVars_.varPhoIsoCorr);
161  }
162  //isolations in both EB and EE
163  tmpTMVAReader.AddVariable("CITK_isoChargedHad" , &allMVAVars_.varChIsoRaw);
164  tmpTMVAReader.AddVariable("chgIsoWrtWorstVtx", &allMVAVars_.varWorstChRaw);
165 
166  // Endcap only variables
167  if( isEndcapCategory(iCategory) ){
168  tmpTMVAReader.AddVariable("esEffSigmaRR" , &allMVAVars_.varESEffSigmaRR);
169  tmpTMVAReader.AddVariable("esEnergy/SCRawE" , &allMVAVars_.varESEnOverRawE);
170  }
171 
172  //
173  // Book the method and set up the weights file
174  //
175  std::unique_ptr<TMVA::IMethod> temp( tmpTMVAReader.BookMVA(MethodName_ , weightFile.fullPath() ) );
176 
177  return std::unique_ptr<const GBRForest>( new GBRForest( dynamic_cast<TMVA::MethodBDT*>( tmpTMVAReader.FindMVA(MethodName_) ) ) );
178 
179 }
180 
181 // A function that should work on both pat and reco objects
183 
184  //
185  // Declare all value maps corresponding to the above tokens
186  //
192  //
193  edm::Handle<edm::ValueMap<float> > phoChargedIsolationMap;
194  edm::Handle<edm::ValueMap<float> > phoPhotonIsolationMap;
195  edm::Handle<edm::ValueMap<float> > phoWorstChargedIsolationMap;
196 
197  // Rho will be pulled from the event content
199 
200  // Get the isolation maps
201  iEvent.getByLabel(phoChargedIsolationLabel_, phoChargedIsolationMap);
202  iEvent.getByLabel(phoPhotonIsolationLabel_, phoPhotonIsolationMap);
203  iEvent.getByLabel(phoWorstChargedIsolationLabel_, phoWorstChargedIsolationMap);
204 
205  // Get rho
206  iEvent.getByLabel(rhoLabel_,rho);
207 
208  // Make sure everything is retrieved successfully
209  if(! ( phoChargedIsolationMap.isValid()
210  && phoPhotonIsolationMap.isValid()
211  && phoWorstChargedIsolationMap.isValid()
212  && rho.isValid() ) )
213  throw cms::Exception("MVA failure: ")
214  << "Failed to retrieve event content needed for this MVA"
215  << std::endl
216  << "Check python MVA configuration file and make sure all needed"
217  << std::endl
218  << "producers are running upstream" << std::endl;
219 
220  // Try to cast the particle into a reco particle.
221  // This should work for both reco and pat.
222  const edm::Ptr<reco::Photon> phoRecoPtr(particle);
223  if( phoRecoPtr.isNull() )
224  throw cms::Exception("MVA failure: ")
225  << " given particle is expected to be reco::Photon or pat::Photon," << std::endl
226  << " but appears to be neither" << std::endl;
227 
228  // Both pat and reco particles have exactly the same accessors.
229  auto superCluster = phoRecoPtr->superCluster();
230  // Full 5x5 cluster shapes. We could take some of this directly from
231  // the photon object, but some of these are not available.
232  float e2x2 = std::numeric_limits<float>::max();
234  float full5x5_sigmaIetaIeta = std::numeric_limits<float>::max();
235  float full5x5_sigmaIetaIphi = std::numeric_limits<float>::max();
236  float effSigmaRR = std::numeric_limits<float>::max();
237 
238  AllVariables allMVAVars;
239 
240  const auto& full5x5_pss = phoRecoPtr->full5x5_showerShapeVariables();
241  e2x2 = full5x5_pss.e2x2;
242  e5x5 = full5x5_pss.e5x5;
243  full5x5_sigmaIetaIeta = full5x5_pss.sigmaIetaIeta;
244  full5x5_sigmaIetaIphi = full5x5_pss.sigmaIetaIphi;
245  effSigmaRR = full5x5_pss.effSigmaRR;
246 
247  allMVAVars.scPhi = superCluster->phi();
248  allMVAVars.varR9 = phoRecoPtr->r9() ;
249  allMVAVars.varSieie = full5x5_sigmaIetaIeta;
250  allMVAVars.varSieip = full5x5_sigmaIetaIphi;
251  allMVAVars.varE2x2overE5x5 = e2x2/e5x5;
252  allMVAVars.varSCEta = superCluster->eta();
253  allMVAVars.varRawE = superCluster->rawEnergy();
254  allMVAVars.varSCEtaWidth = superCluster->etaWidth();
255  allMVAVars.varSCPhiWidth = superCluster->phiWidth();
256  allMVAVars.varESEnOverRawE = superCluster->preshowerEnergy() / superCluster->rawEnergy();
257  allMVAVars.varESEffSigmaRR = effSigmaRR;
258  allMVAVars.varRho = *rho;
259  allMVAVars.varPhoIsoRaw = (*phoPhotonIsolationMap)[phoRecoPtr];
260  allMVAVars.varChIsoRaw = (*phoChargedIsolationMap)[phoRecoPtr];
261  allMVAVars.varWorstChRaw = (*phoWorstChargedIsolationMap)[phoRecoPtr];
262 
263  //photon iso corrected:
264 
265  double eA = effectiveAreas_.getEffectiveArea( std::abs(superCluster->eta()) );
266  double phoIsoPtScalingCoeffVal = 0;
267  if( !isEndcapCategory( findCategory ( particle ) ) )
268  phoIsoPtScalingCoeffVal = phoIsoPtScalingCoeff_.at(0); // barrel case
269  else
270  phoIsoPtScalingCoeffVal = phoIsoPtScalingCoeff_.at(1); //endcap case
271  double phoIsoCorr = (*phoPhotonIsolationMap)[phoRecoPtr] - eA*(*rho) - phoIsoPtScalingCoeffVal*phoRecoPtr->pt();
272 
273  allMVAVars.varPhoIsoCorr = TMath::Max(phoIsoCorr, phoIsoCutoff_);
274 
275  constrainMVAVariables(allMVAVars);
276  //
277  // Important: the order of variables in the "vars" vector has to be EXACTLY
278  // the same as in the .xml file defining the MVA.
279  //
280  std::vector<float> vars;
281  if( isEndcapCategory( findCategory( particle ) ) ) {
282  vars = std::move( packMVAVariables(
283  allMVAVars.scPhi,
284  allMVAVars.varR9,
285  allMVAVars.varSieie,
286  allMVAVars.varSieip,
287  allMVAVars.varE2x2overE5x5,
288  allMVAVars.varSCEta,
289  allMVAVars.varRawE,
290  allMVAVars.varSCEtaWidth,
291  allMVAVars.varSCPhiWidth,
292  allMVAVars.varRho,
293  allMVAVars.varPhoIsoCorr,
294  allMVAVars.varChIsoRaw,
295  allMVAVars.varWorstChRaw,
296  allMVAVars.varESEffSigmaRR,
297  allMVAVars.varESEnOverRawE
298  )
299  );
300  } else {
301  vars = std::move( packMVAVariables(
302  allMVAVars.scPhi,
303  allMVAVars.varR9,
304  allMVAVars.varSieie,
305  allMVAVars.varSieip,
306  allMVAVars.varE2x2overE5x5,
307  allMVAVars.varSCEta,
308  allMVAVars.varRawE,
309  allMVAVars.varSCEtaWidth,
310  allMVAVars.varSCPhiWidth,
311  allMVAVars.varRho,
312  allMVAVars.varPhoIsoRaw,
313  allMVAVars.varChIsoRaw,
314  allMVAVars.varWorstChRaw
315  )
316  );
317  }
318  return vars;
319 }
320 
322 
323  // Check that variables do not have crazy values
324 
325  // This function is currently empty as this specific MVA was not
326  // developed with restricting variables to specific physical ranges.
327  return;
328 
329 }
330 
335  cc.consumes<double>(rhoLabel_);
336 }
337 
340  "PhotonMVAEstimatorRun2Spring16NonTrig");
341 
T getParameter(std::string const &) const
virtual double pt() const final
transverse momentum
reco::SuperClusterRef superCluster() const
Ref to SuperCluster.
std::unique_ptr< const GBRForest > createSingleReader(const int iCategory, const edm::FileInPath &weightFile)
PhotonMVAEstimatorRun2Spring16NonTrig(const edm::ParameterSet &conf)
const float getEffectiveArea(float eta) const
int findCategory(const edm::Ptr< reco::Candidate > &particle) const override
std::vector< float > packMVAVariables(const Args...args) const
std::vector< float > fillMVAVariables(const edm::Ptr< reco::Candidate > &particle, const edm::Event &iEvent) const override
int iEvent
Definition: GenABIO.cc:230
bool isNull() const
Checks for null.
Definition: Ptr.h:165
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< std::unique_ptr< const GBRForest > > gbrForests_
bool isValid() const
Definition: HandleBase.h:74
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
Definition: Event.h:416
bool isEndcap(GeomDetEnumerators::SubDetector m)
float mvaValue(const edm::Ptr< reco::Candidate > &particle, const edm::Event &) const
T Max(T a, T b)
Definition: MathUtil.h:44
#define debug
Definition: HDRShower.cc:19
void setConsumes(edm::ConsumesCollector &&) const override
HLT enums.
const ShowerShape & full5x5_showerShapeVariables() const
Definition: Photon.h:198
float r9() const
Definition: Photon.h:228
#define DEFINE_EDM_PLUGIN(factory, type, name)
std::string fullPath() const
Definition: FileInPath.cc:184
def move(src, dest)
Definition: eostools.py:510