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 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("mvaNormalizationFormula", 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  inputFileName_ = cfg.getParameter<edm::FileInPath>("inputFileName");
155  }
156  if(verbosity_) std::cout << moduleLabel_ << " loadMVA = " << loadMVAfromDB_ << std::endl;
157  if ( cfg.exists("mvaOutput_normalization") ) {
158  mvaOutputNormalizationName_ = cfg.getParameter<std::string>("mvaOutput_normalization");
159  }
160 
161  // Setup our cut map
162  typedef std::vector<edm::ParameterSet> VPSet;
163  VPSet mapping = cfg.getParameter<VPSet>("mapping");
164  for ( VPSet::const_iterator mappingEntry = mapping.begin();
165  mappingEntry != mapping.end(); ++mappingEntry ) {
166  unsigned category = mappingEntry->getParameter<uint32_t>("category");
167  std::unique_ptr<DiscriminantCutEntry> cut{new DiscriminantCutEntry()};
168  if ( mappingEntry->existsAs<double>("cut") ) {
169  cut->cutValue_ = mappingEntry->getParameter<double>("cut");
171  } else if ( mappingEntry->existsAs<std::string>("cut") ) {
172  cut->cutName_ = mappingEntry->getParameter<std::string>("cut");
173  std::string cutVariable_string = mappingEntry->getParameter<std::string>("variable");
174  cut->cutVariable_.reset( new StringObjectFunction<reco::PFTau>(cutVariable_string.data()) );
176  } else {
177  throw cms::Exception("RecoTauDiscriminantCutMultiplexer")
178  << " Undefined Configuration Parameter 'cut' !!\n";
179  }
180  cuts_[category] = std::move(cut);
181  }
182 
183  verbosity_ = ( cfg.exists("verbosity") ) ?
184  cfg.getParameter<int>("verbosity") : 0;
185  if(verbosity_) std::cout << "constructed " << moduleLabel_ << std::endl;
186 }
187 
189 {
190 }
191 
193 {
194  if(verbosity_) std::cout << " begin! " << moduleLabel_ << " " << isInitialized_ << std::endl;
195  if ( !isInitialized_ ) {
196  //Only open the file once and we can close it when this routine is done
197  // since all objects gotten from the file will have been copied
198  std::unique_ptr<TFile> inputFile;
199  if ( mvaOutputNormalizationName_ != "" ) {
200  if ( !loadMVAfromDB_ ) {
201  inputFile = openInputFile(inputFileName_);
202  mvaOutput_normalization_ = loadObjectFromFile<TFormula>(*inputFile, mvaOutputNormalizationName_);
203  } else {
204  auto temp = loadTFormulaFromDB(es, mvaOutputNormalizationName_, verbosity_);
205  temp->SetName(Form("%s_mvaOutput_normalization", moduleLabel_.data()));
206  mvaOutput_normalization_.reset(temp.release());
207  }
208  }
209  for ( DiscriminantCutMap::iterator cut = cuts_.begin();
210  cut != cuts_.end(); ++cut ) {
211  if ( cut->second->mode_ == DiscriminantCutEntry::kVariableCut ) {
212  if ( !loadMVAfromDB_ ) {
213  if(not inputFile) {
214  inputFile = openInputFile(inputFileName_);
215  }
216  if(verbosity_) std::cout << "Loading from file" << inputFileName_ << std::endl;
217  cut->second->cutFunction_ = loadObjectFromFile<TGraph>(*inputFile, cut->second->cutName_);
218  } else {
219  if(verbosity_) std::cout << "Loading from DB" << std::endl;
220  cut->second->cutFunction_ = loadTGraphFromDB(es, cut->second->cutName_, verbosity_);
221  }
222  }
223  }
224  isInitialized_ = true;
225  }
226 
229 }
230 
231 double
233 {
234  if ( verbosity_ ) {
235  std::cout << "<RecoTauDiscriminantCutMultiplexer::discriminate>:" << std::endl;
236  std::cout << " moduleLabel = " << moduleLabel_ << std::endl;
237  }
238 
239  double disc_result = (*toMultiplexHandle_)[tau];
240  if ( verbosity_ ) {
241  std::cout << "disc_result = " << disc_result << std::endl;
242  }
243  if ( mvaOutput_normalization_ ) {
244  disc_result = mvaOutput_normalization_->Eval(disc_result);
245  //if ( disc_result > 1. ) disc_result = 1.;
246  //if ( disc_result < 0. ) disc_result = 0.;
247  if ( verbosity_ ) {
248  std::cout << "disc_result (normalized) = " << disc_result << std::endl;
249  }
250  }
251  double key_result = (*keyHandle_)[tau];
252  DiscriminantCutMap::const_iterator cutIter = cuts_.find(TMath::Nint(key_result));
253 
254 
255  // Return null if it doesn't exist
256  if ( cutIter == cuts_.end() ) {
258  }
259  // See if the discriminator passes our cuts
260  bool passesCuts = false;
261  if ( cutIter->second->mode_ == DiscriminantCutEntry::kFixedCut ) {
262  passesCuts = (disc_result > cutIter->second->cutValue_);
263  if ( verbosity_ ) {
264  std::cout << "cutValue (fixed) = " << cutIter->second->cutValue_ << " --> passesCuts = " << passesCuts << std::endl;
265  }
266  } else if ( cutIter->second->mode_ == DiscriminantCutEntry::kVariableCut ) {
267  double cutVariable = (*cutIter->second->cutVariable_)(*tau);
268  double xMin, xMax, dummy;
269  cutIter->second->cutFunction_->GetPoint(0, xMin, dummy);
270  cutIter->second->cutFunction_->GetPoint(cutIter->second->cutFunction_->GetN() - 1, xMax, dummy);
271  const double epsilon = 1.e-3;
272  if ( cutVariable < (xMin + epsilon) ) cutVariable = xMin + epsilon;
273  else if ( cutVariable > (xMax - epsilon) ) cutVariable = xMax - epsilon;
274  double cutValue = cutIter->second->cutFunction_->Eval(cutVariable);
275  passesCuts = (disc_result > cutValue);
276  if ( verbosity_ ) {
277  std::cout << "cutValue (@" << cutVariable << ") = " << cutValue << " --> passesCuts = " << passesCuts << std::endl;
278  }
279  } else assert(0);
280 
281  return passesCuts;
282 }
283 
T getParameter(std::string const &) const
std::unique_ptr< const TFormula > mvaOutput_normalization_
tuple cfg
Definition: looper.py:237
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:446
edm::Handle< reco::PFTauDiscriminator > keyHandle_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
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
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:159
const T & get() const
Definition: EventSetup.h:55
T const * product() const
Definition: ESHandle.h:86
RecoTauDiscriminantCutMultiplexer(const edm::ParameterSet &pset)
tuple cout
Definition: gather_cfg.py:121
volatile std::atomic< bool > shutdown_flag false
std::string fullPath() const
Definition: FileInPath.cc:165
std::map< int, std::unique_ptr< DiscriminantCutEntry > > DiscriminantCutMap
moduleLabel_(iConfig.getParameter< string >("@module_label"))
long double T