CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
RecoTauDiscriminantCutMultiplexer.cc
Go to the documentation of this file.
1 /*
2  * RecoTauDiscriminantCutMultiplexer
3  *
4  * Author: Evan K. Friis, UW
5  *
6  * Takes two PFTauDiscriminators.
7  *
8  * The "key" discriminantor is rounded to the nearest integer.
9  *
10  * A set of cuts for different keys on the "toMultiplex" discriminantor is
11  * provided in the config file.
12  *
13  * Both the key and toMultiplex discriminators should map to the same PFTau
14  * collection.
15  *
16  */
17 #include <boost/foreach.hpp>
23 
28 
29 #include "TMath.h"
30 #include "TGraph.h"
31 #include "TFormula.h"
32 #include "TFile.h"
33 
35 {
36  public:
38 
40  double discriminate(const reco::PFTauRef&) const override;
41  void beginEvent(const edm::Event& event, const edm::EventSetup& eventSetup) override;
42 
43  private:
45 
48 
50  {
52  : cutVariable_(),
53  cutFunction_(),
55  {}
57  {
58  }
59  double cutValue_;
61  std::unique_ptr<StringObjectFunction<reco::PFTau>> cutVariable_;
62  std::unique_ptr<const TGraph> cutFunction_;
64  int mode_;
65  };
66  typedef std::map<int, std::unique_ptr<DiscriminantCutEntry>> DiscriminantCutMap;
68 
70  std::unique_ptr<const TFormula> mvaOutput_normalization_;
71 
73 
80 
82 };
83 
84 namespace
85 {
86  std::unique_ptr<TFile> openInputFile(const edm::FileInPath& inputFileName) {
87  if ( inputFileName.location() == edm::FileInPath::Unknown){ throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadObjectFromFile")
88  << " Failed to find File = " << inputFileName << " !!\n";
89  }
90  return std::unique_ptr<TFile>{ new TFile(inputFileName.fullPath().data()) };
91  }
92 
93  template <typename T>
94  std::unique_ptr<const T> loadObjectFromFile(TFile& inputFile, const std::string& objectName)
95  {
96  const T* object = dynamic_cast<T*>(inputFile.Get(objectName.data()));
97  if ( !object )
98  throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadObjectFromFile")
99  << " Failed to load Object = " << objectName.data() << " from file = " << inputFile.GetName() << " !!\n";
100  //Need to use TObject::Clone since the type T might be a base class
101  std::unique_ptr<const T> copy{ static_cast<T*>(object->Clone()) };
102 
103  return std::move(copy);
104  }
105 
106  std::unique_ptr<const TGraph> loadTGraphFromDB(const edm::EventSetup& es, const std::string& graphName, const int& verbosity_ = 0)
107  {
108  if(verbosity_){
109  std::cout << "<loadTGraphFromDB>:" << std::endl;
110  std::cout << " graphName = " << graphName << std::endl;
111  }
113  es.get<PhysicsTGraphPayloadRcd>().get(graphName, graphPayload);
114  return std::unique_ptr<const TGraph>{ new TGraph(*graphPayload.product()) };
115  }
116 
117  std::unique_ptr<TFormula> loadTFormulaFromDB(const edm::EventSetup& es, const std::string& formulaName, const TString& newName, const int& verbosity_ = 0)
118  {
119  if(verbosity_){
120  std::cout << "<loadTFormulaFromDB>:" << std::endl;
121  std::cout << " formulaName = " << formulaName << std::endl;
122  }
124  es.get<PhysicsTFormulaPayloadRcd>().get(formulaName, formulaPayload);
125 
126  if ( formulaPayload->formulas().size() == 1 && formulaPayload->limits().size() == 1 ) {
127  return std::unique_ptr<TFormula> {new TFormula(newName, formulaPayload->formulas().at(0).data()) };
128  } else {
129  throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadTFormulaFromDB")
130  << "Failed to load TFormula = " << formulaName << " from Database !!\n";
131  }
132  return std::unique_ptr<TFormula>{};
133  }
134 }
135 
138  moduleLabel_(cfg.getParameter<std::string>("@module_label")),
139  mvaOutput_normalization_(),
140  isInitialized_(false)
141 {
142 
143  toMultiplex_ = cfg.getParameter<edm::InputTag>("toMultiplex");
144  toMultiplex_token = consumes<reco::PFTauDiscriminator>(toMultiplex_);
145  key_ = cfg.getParameter<edm::InputTag>("key");
146  key_token = consumes<reco::PFTauDiscriminator>(key_);
147 
148  verbosity_ = ( cfg.exists("verbosity") ) ?
149  cfg.getParameter<int>("verbosity") : 0;
150 
151 
152  loadMVAfromDB_ = cfg.exists("loadMVAfromDB") ? cfg.getParameter<bool>("loadMVAfromDB") : false;
153  if ( !loadMVAfromDB_ ) {
154  if(cfg.exists("inputFileName")){
155  inputFileName_ = cfg.getParameter<edm::FileInPath>("inputFileName");
156  }else throw cms::Exception("MVA input not defined") << "Requested to load tau MVA input from ROOT file but no file provided in cfg file";
157  }
158  if(verbosity_) std::cout << moduleLabel_ << " loadMVA = " << loadMVAfromDB_ << std::endl;
159  if ( cfg.exists("mvaOutput_normalization") ) {
160  mvaOutputNormalizationName_ = cfg.getParameter<std::string>("mvaOutput_normalization");
161  }
162 
163  // Setup our cut map
164  typedef std::vector<edm::ParameterSet> VPSet;
165  VPSet mapping = cfg.getParameter<VPSet>("mapping");
166  for ( VPSet::const_iterator mappingEntry = mapping.begin();
167  mappingEntry != mapping.end(); ++mappingEntry ) {
168  unsigned category = mappingEntry->getParameter<uint32_t>("category");
169  std::unique_ptr<DiscriminantCutEntry> cut{new DiscriminantCutEntry()};
170  if ( mappingEntry->existsAs<double>("cut") ) {
171  cut->cutValue_ = mappingEntry->getParameter<double>("cut");
173  } else if ( mappingEntry->existsAs<std::string>("cut") ) {
174  cut->cutName_ = mappingEntry->getParameter<std::string>("cut");
175  std::string cutVariable_string = mappingEntry->getParameter<std::string>("variable");
176  cut->cutVariable_.reset( new StringObjectFunction<reco::PFTau>(cutVariable_string.data()) );
178  } else {
179  throw cms::Exception("RecoTauDiscriminantCutMultiplexer")
180  << " Undefined Configuration Parameter 'cut' !!\n";
181  }
183  }
184 
185  verbosity_ = ( cfg.exists("verbosity") ) ?
186  cfg.getParameter<int>("verbosity") : 0;
187  if(verbosity_) std::cout << "constructed " << moduleLabel_ << std::endl;
188 }
189 
191 {
192 }
193 
195 {
196  if(verbosity_) std::cout << " begin! " << moduleLabel_ << " " << isInitialized_ << std::endl;
197  if ( !isInitialized_ ) {
198  //Only open the file once and we can close it when this routine is done
199  // since all objects gotten from the file will have been copied
200  std::unique_ptr<TFile> inputFile;
201  if ( mvaOutputNormalizationName_ != "" ) {
202  if ( !loadMVAfromDB_ ) {
203  inputFile = openInputFile(inputFileName_);
204  mvaOutput_normalization_ = loadObjectFromFile<TFormula>(*inputFile, mvaOutputNormalizationName_);
205  } else {
206  auto temp = loadTFormulaFromDB(es, mvaOutputNormalizationName_, Form("%s_mvaOutput_normalization", moduleLabel_.data()), verbosity_);
207  mvaOutput_normalization_.reset(temp.release());
208  }
209  }
210  for ( DiscriminantCutMap::iterator cut = cuts_.begin();
211  cut != cuts_.end(); ++cut ) {
212  if ( cut->second->mode_ == DiscriminantCutEntry::kVariableCut ) {
213  if ( !loadMVAfromDB_ ) {
214  if(not inputFile) {
215  inputFile = openInputFile(inputFileName_);
216  }
217  if(verbosity_) std::cout << "Loading from file" << inputFileName_ << std::endl;
218  cut->second->cutFunction_ = loadObjectFromFile<TGraph>(*inputFile, cut->second->cutName_);
219  } else {
220  if(verbosity_) std::cout << "Loading from DB" << std::endl;
221  cut->second->cutFunction_ = loadTGraphFromDB(es, cut->second->cutName_, verbosity_);
222  }
223  }
224  }
225  isInitialized_ = true;
226  }
227 
230 }
231 
232 double
234 {
235  if ( verbosity_ ) {
236  std::cout << "<RecoTauDiscriminantCutMultiplexer::discriminate>:" << std::endl;
237  std::cout << " moduleLabel = " << moduleLabel_ << std::endl;
238  }
239 
240  double disc_result = (*toMultiplexHandle_)[tau];
241  if ( verbosity_ ) {
242  std::cout << "disc_result = " << disc_result << std::endl;
243  }
244  if ( mvaOutput_normalization_ ) {
245  disc_result = mvaOutput_normalization_->Eval(disc_result);
246  //if ( disc_result > 1. ) disc_result = 1.;
247  //if ( disc_result < 0. ) disc_result = 0.;
248  if ( verbosity_ ) {
249  std::cout << "disc_result (normalized) = " << disc_result << std::endl;
250  }
251  }
252  double key_result = (*keyHandle_)[tau];
253  DiscriminantCutMap::const_iterator cutIter = cuts_.find(TMath::Nint(key_result));
254 
255 
256  // Return null if it doesn't exist
257  if ( cutIter == cuts_.end() ) {
259  }
260  // See if the discriminator passes our cuts
261  bool passesCuts = false;
262  if ( cutIter->second->mode_ == DiscriminantCutEntry::kFixedCut ) {
263  passesCuts = (disc_result > cutIter->second->cutValue_);
264  if ( verbosity_ ) {
265  std::cout << "cutValue (fixed) = " << cutIter->second->cutValue_ << " --> passesCuts = " << passesCuts << std::endl;
266  }
267  } else if ( cutIter->second->mode_ == DiscriminantCutEntry::kVariableCut ) {
268  double cutVariable = (*cutIter->second->cutVariable_)(*tau);
269  double xMin, xMax, dummy;
270  cutIter->second->cutFunction_->GetPoint(0, xMin, dummy);
271  cutIter->second->cutFunction_->GetPoint(cutIter->second->cutFunction_->GetN() - 1, xMax, dummy);
272  const double epsilon = 1.e-3;
273  if ( cutVariable < (xMin + epsilon) ) cutVariable = xMin + epsilon;
274  else if ( cutVariable > (xMax - epsilon) ) cutVariable = xMax - epsilon;
275  double cutValue = cutIter->second->cutFunction_->Eval(cutVariable);
276  passesCuts = (disc_result > cutValue);
277  if ( verbosity_ ) {
278  std::cout << "cutValue (@" << cutVariable << ") = " << cutValue << " --> passesCuts = " << passesCuts << std::endl;
279  }
280  } else assert(0);
281 
282  return passesCuts;
283 }
284 
T getParameter(std::string const &) const
std::unique_ptr< const TFormula > mvaOutput_normalization_
tuple cfg
Definition: looper.py:293
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:462
edm::Handle< reco::PFTauDiscriminator > keyHandle_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
assert(m_qm.get())
void beginEvent(const edm::Event &event, const edm::EventSetup &eventSetup) override
bool exists(std::string const &parameterName) const
checks if a parameter exists
edm::Handle< reco::PFTauDiscriminator > toMultiplexHandle_
std::unique_ptr< StringObjectFunction< reco::PFTau > > cutVariable_
double discriminate(const reco::PFTauRef &) const override
edm::EDGetTokenT< reco::PFTauDiscriminator > toMultiplex_token
def move
Definition: eostools.py:510
edm::EDGetTokenT< reco::PFTauDiscriminator > key_token
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
LocationCode location() const
Where was the file found?
Definition: FileInPath.cc:178
const T & get() const
Definition: EventSetup.h:56
T const * product() const
Definition: ESHandle.h:86
RecoTauDiscriminantCutMultiplexer(const edm::ParameterSet &pset)
tuple cout
Definition: gather_cfg.py:145
volatile std::atomic< bool > shutdown_flag false
std::string fullPath() const
Definition: FileInPath.cc:184
std::map< int, std::unique_ptr< DiscriminantCutEntry > > DiscriminantCutMap
moduleLabel_(iConfig.getParameter< string >("@module_label"))
long double T