CMS 3D CMS Logo

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 
26 
31 
32 #include "TMath.h"
33 #include "TGraph.h"
34 #include "TFormula.h"
35 #include "TFile.h"
36 
38 {
39  public:
41 
43  double discriminate(const reco::PFTauRef&) const override;
44  void beginEvent(const edm::Event& event, const edm::EventSetup& eventSetup) override;
45 
46  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
47 
48  private:
50 
53 
55  {
57  : cutVariable_(),
58  cutFunction_(),
60  {}
62  {
63  }
64  double cutValue_;
66  std::unique_ptr<StringObjectFunction<reco::PFTau>> cutVariable_;
67  std::unique_ptr<const TGraph> cutFunction_;
69  int mode_;
70  };
71  typedef std::map<int, std::unique_ptr<DiscriminantCutEntry>> DiscriminantCutMap;
72  DiscriminantCutMap cuts_;
73 
75  std::unique_ptr<const TFormula> mvaOutput_normalization_;
76 
78 
85 
87 };
88 
89 namespace
90 {
91  std::unique_ptr<TFile> openInputFile(const edm::FileInPath& inputFileName) {
92  if ( inputFileName.location() == edm::FileInPath::Unknown){ throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadObjectFromFile")
93  << " Failed to find File = " << inputFileName << " !!\n";
94  }
95  return std::unique_ptr<TFile>{ new TFile(inputFileName.fullPath().data()) };
96  }
97 
98  template <typename T>
99  std::unique_ptr<const T> loadObjectFromFile(TFile& inputFile, const std::string& objectName)
100  {
101  const T* object = dynamic_cast<T*>(inputFile.Get(objectName.data()));
102  if ( !object )
103  throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadObjectFromFile")
104  << " Failed to load Object = " << objectName.data() << " from file = " << inputFile.GetName() << " !!\n";
105  //Need to use TObject::Clone since the type T might be a base class
106  return std::unique_ptr<const T>{ static_cast<T*>(object->Clone()) };
107  }
108 
109  std::unique_ptr<const TGraph> loadTGraphFromDB(const edm::EventSetup& es, const std::string& graphName, const int& verbosity_ = 0)
110  {
111  if(verbosity_){
112  std::cout << "<loadTGraphFromDB>:" << std::endl;
113  std::cout << " graphName = " << graphName << std::endl;
114  }
116  es.get<PhysicsTGraphPayloadRcd>().get(graphName, graphPayload);
117  return std::unique_ptr<const TGraph>{ new TGraph(*graphPayload.product()) };
118  }
119 
120  std::unique_ptr<TFormula> loadTFormulaFromDB(const edm::EventSetup& es, const std::string& formulaName, const TString& newName, const int& verbosity_ = 0)
121  {
122  if(verbosity_){
123  std::cout << "<loadTFormulaFromDB>:" << std::endl;
124  std::cout << " formulaName = " << formulaName << std::endl;
125  }
127  es.get<PhysicsTFormulaPayloadRcd>().get(formulaName, formulaPayload);
128 
129  if ( formulaPayload->formulas().size() == 1 && formulaPayload->limits().size() == 1 ) {
130  return std::unique_ptr<TFormula> {new TFormula(newName, formulaPayload->formulas().at(0).data()) };
131  } else {
132  throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadTFormulaFromDB")
133  << "Failed to load TFormula = " << formulaName << " from Database !!\n";
134  }
135  return std::unique_ptr<TFormula>{};
136  }
137 }
138 
141  moduleLabel_(cfg.getParameter<std::string>("@module_label")),
144 {
145 
146  toMultiplex_ = cfg.getParameter<edm::InputTag>("toMultiplex");
147  toMultiplex_token = consumes<reco::PFTauDiscriminator>(toMultiplex_);
148  key_ = cfg.getParameter<edm::InputTag>("key");
149  key_token = consumes<reco::PFTauDiscriminator>(key_);
150 
151  verbosity_ = cfg.getParameter<int>("verbosity");
152 
153  loadMVAfromDB_ = cfg.getParameter<bool>("loadMVAfromDB");
154  if ( !loadMVAfromDB_ ) {
155  inputFileName_ = cfg.getParameter<edm::FileInPath>("inputFileName");
156  }
157  if(verbosity_) std::cout << moduleLabel_ << " loadMVA = " << loadMVAfromDB_ << std::endl;
158  mvaOutputNormalizationName_ = cfg.getParameter<std::string>("mvaOutput_normalization");
159 
160  // Setup our cut map
161  typedef std::vector<edm::ParameterSet> VPSet;
162  VPSet mapping = cfg.getParameter<VPSet>("mapping");
163  for ( VPSet::const_iterator mappingEntry = mapping.begin();
164  mappingEntry != mapping.end(); ++mappingEntry ) {
165  unsigned category = mappingEntry->getParameter<uint32_t>("category");
166  std::unique_ptr<DiscriminantCutEntry> cut{new DiscriminantCutEntry()};
167  if ( mappingEntry->existsAs<double>("cut") ) {
168  cut->cutValue_ = mappingEntry->getParameter<double>("cut");
170  } else if ( mappingEntry->existsAs<std::string>("cut") ) {
171  cut->cutName_ = mappingEntry->getParameter<std::string>("cut");
172  std::string cutVariable_string = mappingEntry->getParameter<std::string>("variable");
173  cut->cutVariable_.reset( new StringObjectFunction<reco::PFTau>(cutVariable_string) );
175  } else {
176  throw cms::Exception("RecoTauDiscriminantCutMultiplexer")
177  << " Undefined Configuration Parameter 'cut' !!\n";
178  }
180  }
181 
182  verbosity_ = cfg.getParameter<int>("verbosity");
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_.empty() ) {
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_);
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 << "<RecoTauDiscriminantCutMultiplexer::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 
281 void
283  // recoTauDiscriminantCutMultiplexer
285  desc.add<edm::InputTag>("toMultiplex", edm::InputTag("fixme"));
286  desc.add<int>("verbosity", 0);
287 
288  {
289  edm::ParameterSet pset_mapping;
290  pset_mapping.addParameter<unsigned int>("category",0);
291  pset_mapping.addParameter<double>("cut",0.);
292  edm::ParameterSetDescription desc_mapping;
293  desc_mapping.add<unsigned int>("category",0);
294  desc_mapping.addNode(edm::ParameterDescription<std::string>("cut", true) xor
295  edm::ParameterDescription<double>("cut", true));
296  // it seems the parameter string "variable" exists only when "cut" is string
297  // see hpsPFTauDiscriminationByVLooseIsolationMVArun2v1DBdR03oldDMwLT in RecoTauTag/Configuration/python/HPSPFTaus_cff.py
298  desc_mapping.addOptional<std::string>("variable")->setComment("the parameter is required when \"cut\" is string");
299  // desc_mapping.add<double>("cut",0.);
300  std::vector<edm::ParameterSet> vpsd_mapping;
301  vpsd_mapping.push_back(pset_mapping);
302  desc.addVPSet("mapping",desc_mapping,vpsd_mapping);
303  }
304 
305  desc.add<edm::FileInPath>("inputFileName", edm::FileInPath("RecoTauTag/RecoTau/data/emptyMVAinputFile"));
306  desc.add<bool>("loadMVAfromDB", true);
307  fillProducerDescriptions(desc); // inherited from the base
308  desc.add<std::string>("mvaOutput_normalization", "");
309  desc.add<edm::InputTag>("key", edm::InputTag("fixme"));
310  descriptions.add("recoTauDiscriminantCutMultiplexerDefault", desc);
311 }
312 
313 
T getParameter(std::string const &) const
std::unique_ptr< const TFormula > mvaOutput_normalization_
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
ParameterDescriptionBase * addVPSet(U const &iLabel, ParameterSetDescription const &validator, std::vector< ParameterSet > const &defaults)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
edm::Handle< reco::PFTauDiscriminator > keyHandle_
void beginEvent(const edm::Event &event, const edm::EventSetup &eventSetup) override
edm::Handle< reco::PFTauDiscriminator > toMultiplexHandle_
ParameterDescriptionNode * addNode(ParameterDescriptionNode const &node)
string newName
Definition: mps_merge.py:86
std::unique_ptr< StringObjectFunction< reco::PFTau > > cutVariable_
const std::vector< std::string > & formulas() const
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static void fillProducerDescriptions(edm::ParameterSetDescription &desc)
edm::EDGetTokenT< reco::PFTauDiscriminator > toMultiplex_token
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
double discriminate(const reco::PFTauRef &) const override
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:125
edm::EDGetTokenT< reco::PFTauDiscriminator > key_token
LocationCode location() const
Where was the file found?
Definition: FileInPath.cc:161
ParameterDescriptionBase * add(U const &iLabel, T const &value)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
T get() const
Definition: EventSetup.h:71
RecoTauDiscriminantCutMultiplexer(const edm::ParameterSet &pset)
std::string fullPath() const
Definition: FileInPath.cc:163
const std::vector< std::pair< float, float > > & limits() const
std::map< int, std::unique_ptr< DiscriminantCutEntry > > DiscriminantCutMap
long double T
T const * product() const
Definition: ESHandle.h:86
def move(src, dest)
Definition: eostools.py:511
Definition: event.py:1