CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PATTauDiscriminantCutMultiplexer.cc
Go to the documentation of this file.
1 /*
2  * \class PATTauDiscriminantCutMultiplexer
3  *
4  * Takes two PFTauDiscriminators.
5  *
6  * The "key" discriminantor is rounded to the nearest integer.
7  *
8  * A set of cuts for different keys on the "toMultiplex" discriminantor is
9  * provided in the config file.
10  *
11  * Both the key and toMultiplex discriminators should map to the same PFTau
12  * collection.
13  *
14  * Adopted from RecoTauTag/RecoTau/plugins/RecoTauDiscriminantCutMultiplexer.cc
15  *
16  * \author Alexander Nehrkorn, RWTH Aachen
17  */
18 
19 #include <boost/foreach.hpp>
25 
30 
31 #include "TMath.h"
32 #include "TGraph.h"
33 #include "TFormula.h"
34 #include "TFile.h"
35 
37 {
38  public:
40 
42  double discriminate(const pat::TauRef&) const override;
43  void beginEvent(const edm::Event& event, const edm::EventSetup& eventSetup) override;
44 
45  private:
47 
50 
52  {
54  : cutVariable_(),
55  cutFunction_(),
57  {}
59  {
60  }
61  double cutValue_;
63  std::unique_ptr<StringObjectFunction<pat::Tau>> cutVariable_;
64  std::unique_ptr<const TGraph> cutFunction_;
66  int mode_;
67  };
68  typedef std::map<int, std::unique_ptr<DiscriminantCutEntry>> DiscriminantCutMap;
70 
72  std::unique_ptr<const TFormula> mvaOutput_normalization_;
73 
75 
82 
84 };
85 
86 namespace
87 {
88  std::unique_ptr<TFile> openInputFile(const edm::FileInPath& inputFileName) {
89  if ( inputFileName.location() == edm::FileInPath::Unknown){ throw cms::Exception("PATTauDiscriminantCutMultiplexer::loadObjectFromFile")
90  << " Failed to find File = " << inputFileName << " !!\n";
91  }
92  return std::unique_ptr<TFile>{ new TFile(inputFileName.fullPath().data()) };
93  }
94 
95  template <typename T>
96  std::unique_ptr<const T> loadObjectFromFile(TFile& inputFile, const std::string& objectName)
97  {
98  const T* object = dynamic_cast<T*>(inputFile.Get(objectName.data()));
99  if ( !object )
100  throw cms::Exception("PATTauDiscriminantCutMultiplexer::loadObjectFromFile")
101  << " Failed to load Object = " << objectName.data() << " from file = " << inputFile.GetName() << " !!\n";
102  //Need to use TObject::Clone since the type T might be a base class
103  std::unique_ptr<const T> copy{ static_cast<T*>(object->Clone()) };
104 
105  return std::move(copy);
106  }
107 
108  std::unique_ptr<const TGraph> loadTGraphFromDB(const edm::EventSetup& es, const std::string& graphName, const int& verbosity_ = 0)
109  {
110  if(verbosity_){
111  std::cout << "<loadTGraphFromDB>:" << std::endl;
112  std::cout << " graphName = " << graphName << std::endl;
113  }
115  es.get<PhysicsTGraphPayloadRcd>().get(graphName, graphPayload);
116  return std::unique_ptr<const TGraph>{ new TGraph(*graphPayload.product()) };
117  }
118 
119  std::unique_ptr<TFormula> loadTFormulaFromDB(const edm::EventSetup& es, const std::string& formulaName, const TString& newName, const int& verbosity_ = 0)
120  {
121  if(verbosity_){
122  std::cout << "<loadTFormulaFromDB>:" << std::endl;
123  std::cout << " formulaName = " << formulaName << std::endl;
124  }
126  es.get<PhysicsTFormulaPayloadRcd>().get(formulaName, formulaPayload);
127 
128  if ( formulaPayload->formulas().size() == 1 && formulaPayload->limits().size() == 1 ) {
129  return std::unique_ptr<TFormula> {new TFormula(newName, formulaPayload->formulas().at(0).data()) };
130  } else {
131  throw cms::Exception("PATTauDiscriminantCutMultiplexer::loadTFormulaFromDB")
132  << "Failed to load TFormula = " << formulaName << " from Database !!\n";
133  }
134  return std::unique_ptr<TFormula>{};
135  }
136 }
137 
140  moduleLabel_(cfg.getParameter<std::string>("@module_label")),
141  mvaOutput_normalization_(),
142  isInitialized_(false)
143 {
144 
145  toMultiplex_ = cfg.getParameter<edm::InputTag>("toMultiplex");
146  toMultiplex_token = consumes<pat::PATTauDiscriminator>(toMultiplex_);
147  key_ = cfg.getParameter<edm::InputTag>("key");
148  key_token = consumes<pat::PATTauDiscriminator>(key_);
149 
150  loadMVAfromDB_ = cfg.exists("loadMVAfromDB") ? cfg.getParameter<bool>("loadMVAfromDB") : false;
151  if ( !loadMVAfromDB_ ) {
152  if(cfg.exists("inputFileName")){
153  inputFileName_ = cfg.getParameter<edm::FileInPath>("inputFileName");
154  }else throw cms::Exception("MVA input not defined") << "Requested to load tau MVA input from ROOT file but no file provided in cfg file";
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<pat::Tau>(cutVariable_string.data()) );
176  } else {
177  throw cms::Exception("PATTauDiscriminantCutMultiplexer")
178  << " Undefined Configuration Parameter 'cut' !!\n";
179  }
181  }
182  verbosity_ = ( cfg.exists("verbosity") ) ? cfg.getParameter<int>("verbosity") : 0;
183  if(verbosity_) std::cout << "constructed " << moduleLabel_ << std::endl;
184 }
185 
187 {
188 }
189 
191 {
192  if(verbosity_) std::cout << " begin! " << moduleLabel_ << " " << isInitialized_ << std::endl;
193  if ( !isInitialized_ ) {
194  //Only open the file once and we can close it when this routine is done
195  // since all objects gotten from the file will have been copied
196  std::unique_ptr<TFile> inputFile;
197  if ( mvaOutputNormalizationName_ != "" ) {
198  if ( !loadMVAfromDB_ ) {
199  inputFile = openInputFile(inputFileName_);
200  mvaOutput_normalization_ = loadObjectFromFile<TFormula>(*inputFile, mvaOutputNormalizationName_);
201  } else {
202  auto temp = loadTFormulaFromDB(es, mvaOutputNormalizationName_, Form("%s_mvaOutput_normalization", moduleLabel_.data()), verbosity_);
203  mvaOutput_normalization_.reset(temp.release());
204  }
205  }
206  for ( DiscriminantCutMap::iterator cut = cuts_.begin();
207  cut != cuts_.end(); ++cut ) {
208  if ( cut->second->mode_ == DiscriminantCutEntry::kVariableCut ) {
209  if ( !loadMVAfromDB_ ) {
210  if(not inputFile) {
211  inputFile = openInputFile(inputFileName_);
212  }
213  if(verbosity_) std::cout << "Loading from file" << inputFileName_ << std::endl;
214  cut->second->cutFunction_ = loadObjectFromFile<TGraph>(*inputFile, cut->second->cutName_);
215  } else {
216  if(verbosity_) std::cout << "Loading from DB" << std::endl;
217  cut->second->cutFunction_ = loadTGraphFromDB(es, cut->second->cutName_, verbosity_);
218  }
219  }
220  }
221  isInitialized_ = true;
222  }
223 
226 }
227 
228 double
230 {
231  if ( verbosity_ ) {
232  std::cout << "<PATTauDiscriminantCutMultiplexer::discriminate>:" << std::endl;
233  std::cout << " moduleLabel = " << moduleLabel_ << std::endl;
234  }
235 
236  double disc_result = (*toMultiplexHandle_)[tau];
237  if ( verbosity_ ) {
238  std::cout << "disc_result = " << disc_result << std::endl;
239  }
240  if ( mvaOutput_normalization_ ) {
241  disc_result = mvaOutput_normalization_->Eval(disc_result);
242  //if ( disc_result > 1. ) disc_result = 1.;
243  //if ( disc_result < 0. ) disc_result = 0.;
244  if ( verbosity_ ) {
245  std::cout << "disc_result (normalized) = " << disc_result << std::endl;
246  }
247  }
248  double key_result = (*keyHandle_)[tau];
249  DiscriminantCutMap::const_iterator cutIter = cuts_.find(TMath::Nint(key_result));
250 
251 
252  // Return null if it doesn't exist
253  if ( cutIter == cuts_.end() ) {
255  }
256  // See if the discriminator passes our cuts
257  bool passesCuts = false;
258  if ( cutIter->second->mode_ == DiscriminantCutEntry::kFixedCut ) {
259  passesCuts = (disc_result > cutIter->second->cutValue_);
260  if ( verbosity_ ) {
261  std::cout << "cutValue (fixed) = " << cutIter->second->cutValue_ << " --> passesCuts = " << passesCuts << std::endl;
262  }
263  } else if ( cutIter->second->mode_ == DiscriminantCutEntry::kVariableCut ) {
264  double cutVariable = (*cutIter->second->cutVariable_)(*tau);
265  double xMin, xMax, dummy;
266  cutIter->second->cutFunction_->GetPoint(0, xMin, dummy);
267  cutIter->second->cutFunction_->GetPoint(cutIter->second->cutFunction_->GetN() - 1, xMax, dummy);
268  const double epsilon = 1.e-3;
269  if ( cutVariable < (xMin + epsilon) ) cutVariable = xMin + epsilon;
270  else if ( cutVariable > (xMax - epsilon) ) cutVariable = xMax - epsilon;
271  double cutValue = cutIter->second->cutFunction_->Eval(cutVariable);
272  passesCuts = (disc_result > cutValue);
273  if ( verbosity_ ) {
274  std::cout << "cutValue (@" << cutVariable << ") = " << cutValue << " --> passesCuts = " << passesCuts << std::endl;
275  }
276  } else assert(0);
277 
278  return passesCuts;
279 }
280 
T getParameter(std::string const &) const
tuple cfg
Definition: looper.py:293
std::unique_ptr< const TFormula > mvaOutput_normalization_
void beginEvent(const edm::Event &event, const edm::EventSetup &eventSetup) override
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:457
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
assert(m_qm.get())
PATTauDiscriminantCutMultiplexer(const edm::ParameterSet &pset)
bool exists(std::string const &parameterName) const
checks if a parameter exists
std::map< int, std::unique_ptr< DiscriminantCutEntry > > DiscriminantCutMap
std::unique_ptr< StringObjectFunction< pat::Tau > > cutVariable_
edm::EDGetTokenT< pat::PATTauDiscriminator > key_token
double discriminate(const pat::TauRef &) const override
edm::EDGetTokenT< pat::PATTauDiscriminator > toMultiplex_token
def move
Definition: eostools.py:510
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
edm::Handle< pat::PATTauDiscriminator > toMultiplexHandle_
edm::Handle< pat::PATTauDiscriminator > keyHandle_
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
tuple cout
Definition: gather_cfg.py:145
volatile std::atomic< bool > shutdown_flag false
std::string fullPath() const
Definition: FileInPath.cc:184
moduleLabel_(iConfig.getParameter< string >("@module_label"))
long double T