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 public:
40 
42  double discriminate(const reco::PFTauRef&) const override;
43  void beginEvent(const edm::Event& event, const edm::EventSetup& eventSetup) override;
44 
45  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
46 
47 private:
49 
52 
56  double cutValue_;
58  std::unique_ptr<StringObjectFunction<reco::PFTau>> cutVariable_;
59  std::unique_ptr<const TGraph> cutFunction_;
61  int mode_;
62  };
63  typedef std::map<int, std::unique_ptr<DiscriminantCutEntry>> DiscriminantCutMap;
64  DiscriminantCutMap cuts_;
65 
67  std::unique_ptr<const TFormula> mvaOutput_normalization_;
68 
70 
77 
79 };
80 
81 namespace {
82  std::unique_ptr<TFile> openInputFile(const edm::FileInPath& inputFileName) {
83  if (inputFileName.location() == edm::FileInPath::Unknown) {
84  throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadObjectFromFile")
85  << " Failed to find File = " << inputFileName << " !!\n";
86  }
87  return std::unique_ptr<TFile>{new TFile(inputFileName.fullPath().data())};
88  }
89 
90  template <typename T>
91  std::unique_ptr<const T> loadObjectFromFile(TFile& inputFile, const std::string& objectName) {
92  const T* object = dynamic_cast<T*>(inputFile.Get(objectName.data()));
93  if (!object)
94  throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadObjectFromFile")
95  << " Failed to load Object = " << objectName.data() << " from file = " << inputFile.GetName() << " !!\n";
96  //Need to use TObject::Clone since the type T might be a base class
97  return std::unique_ptr<const T>{static_cast<T*>(object->Clone())};
98  }
99 
100  std::unique_ptr<const TGraph> loadTGraphFromDB(const edm::EventSetup& es,
101  const std::string& graphName,
102  const int& verbosity_ = 0) {
103  if (verbosity_) {
104  std::cout << "<loadTGraphFromDB>:" << std::endl;
105  std::cout << " graphName = " << graphName << std::endl;
106  }
108  es.get<PhysicsTGraphPayloadRcd>().get(graphName, graphPayload);
109  return std::unique_ptr<const TGraph>{new TGraph(*graphPayload.product())};
110  }
111 
112  std::unique_ptr<TFormula> loadTFormulaFromDB(const edm::EventSetup& es,
113  const std::string& formulaName,
114  const TString& newName,
115  const int& verbosity_ = 0) {
116  if (verbosity_) {
117  std::cout << "<loadTFormulaFromDB>:" << std::endl;
118  std::cout << " formulaName = " << formulaName << std::endl;
119  }
121  es.get<PhysicsTFormulaPayloadRcd>().get(formulaName, formulaPayload);
122 
123  if (formulaPayload->formulas().size() == 1 && formulaPayload->limits().size() == 1) {
124  return std::unique_ptr<TFormula>{new TFormula(newName, formulaPayload->formulas().at(0).data())};
125  } else {
126  throw cms::Exception("RecoTauDiscriminantCutMultiplexer::loadTFormulaFromDB")
127  << "Failed to load TFormula = " << formulaName << " from Database !!\n";
128  }
129  return std::unique_ptr<TFormula>{};
130  }
131 } // namespace
132 
135  moduleLabel_(cfg.getParameter<std::string>("@module_label")),
138  toMultiplex_ = cfg.getParameter<edm::InputTag>("toMultiplex");
139  toMultiplex_token = consumes<reco::PFTauDiscriminator>(toMultiplex_);
140  key_ = cfg.getParameter<edm::InputTag>("key");
141  key_token = consumes<reco::PFTauDiscriminator>(key_);
142 
143  verbosity_ = cfg.getParameter<int>("verbosity");
144 
145  loadMVAfromDB_ = cfg.getParameter<bool>("loadMVAfromDB");
146  if (!loadMVAfromDB_) {
147  inputFileName_ = cfg.getParameter<edm::FileInPath>("inputFileName");
148  }
149  if (verbosity_)
150  std::cout << moduleLabel_ << " loadMVA = " << loadMVAfromDB_ << std::endl;
151  mvaOutputNormalizationName_ = cfg.getParameter<std::string>("mvaOutput_normalization");
152 
153  // Setup our cut map
154  typedef std::vector<edm::ParameterSet> VPSet;
155  VPSet mapping = cfg.getParameter<VPSet>("mapping");
156  for (VPSet::const_iterator mappingEntry = mapping.begin(); mappingEntry != mapping.end(); ++mappingEntry) {
157  unsigned category = mappingEntry->getParameter<uint32_t>("category");
158  std::unique_ptr<DiscriminantCutEntry> cut{new DiscriminantCutEntry()};
159  if (mappingEntry->existsAs<double>("cut")) {
160  cut->cutValue_ = mappingEntry->getParameter<double>("cut");
162  } else if (mappingEntry->existsAs<std::string>("cut")) {
163  cut->cutName_ = mappingEntry->getParameter<std::string>("cut");
164  std::string cutVariable_string = mappingEntry->getParameter<std::string>("variable");
165  cut->cutVariable_.reset(new StringObjectFunction<reco::PFTau>(cutVariable_string));
167  } else {
168  throw cms::Exception("RecoTauDiscriminantCutMultiplexer") << " Undefined Configuration Parameter 'cut' !!\n";
169  }
171  }
172 
173  verbosity_ = cfg.getParameter<int>("verbosity");
174  if (verbosity_)
175  std::cout << "constructed " << moduleLabel_ << std::endl;
176 }
177 
179 
181  if (verbosity_)
182  std::cout << " begin! " << moduleLabel_ << " " << isInitialized_ << std::endl;
183  if (!isInitialized_) {
184  //Only open the file once and we can close it when this routine is done
185  // since all objects gotten from the file will have been copied
186  std::unique_ptr<TFile> inputFile;
187  if (!mvaOutputNormalizationName_.empty()) {
188  if (!loadMVAfromDB_) {
189  inputFile = openInputFile(inputFileName_);
190  mvaOutput_normalization_ = loadObjectFromFile<TFormula>(*inputFile, mvaOutputNormalizationName_);
191  } else {
192  auto temp = loadTFormulaFromDB(
193  es, mvaOutputNormalizationName_, Form("%s_mvaOutput_normalization", moduleLabel_.data()), verbosity_);
195  }
196  }
197  for (DiscriminantCutMap::iterator cut = cuts_.begin(); cut != cuts_.end(); ++cut) {
198  if (cut->second->mode_ == DiscriminantCutEntry::kVariableCut) {
199  if (!loadMVAfromDB_) {
200  if (not inputFile) {
201  inputFile = openInputFile(inputFileName_);
202  }
203  if (verbosity_)
204  std::cout << "Loading from file" << inputFileName_ << std::endl;
205  cut->second->cutFunction_ = loadObjectFromFile<TGraph>(*inputFile, cut->second->cutName_);
206  } else {
207  if (verbosity_)
208  std::cout << "Loading from DB" << std::endl;
209  cut->second->cutFunction_ = loadTGraphFromDB(es, cut->second->cutName_, verbosity_);
210  }
211  }
212  }
213  isInitialized_ = true;
214  }
215 
218 }
219 
221  if (verbosity_) {
222  std::cout << "<RecoTauDiscriminantCutMultiplexer::discriminate>:" << std::endl;
223  std::cout << " moduleLabel = " << moduleLabel_ << std::endl;
224  }
225 
226  double disc_result = (*toMultiplexHandle_)[tau];
227  if (verbosity_) {
228  std::cout << "disc_result = " << disc_result << std::endl;
229  }
231  disc_result = mvaOutput_normalization_->Eval(disc_result);
232  //if ( disc_result > 1. ) disc_result = 1.;
233  //if ( disc_result < 0. ) disc_result = 0.;
234  if (verbosity_) {
235  std::cout << "disc_result (normalized) = " << disc_result << std::endl;
236  }
237  }
238  double key_result = (*keyHandle_)[tau];
239  DiscriminantCutMap::const_iterator cutIter = cuts_.find(TMath::Nint(key_result));
240 
241  // Return null if it doesn't exist
242  if (cutIter == cuts_.end()) {
244  }
245  // See if the discriminator passes our cuts
246  bool passesCuts = false;
247  if (cutIter->second->mode_ == DiscriminantCutEntry::kFixedCut) {
248  passesCuts = (disc_result > cutIter->second->cutValue_);
249  if (verbosity_) {
250  std::cout << "cutValue (fixed) = " << cutIter->second->cutValue_ << " --> passesCuts = " << passesCuts
251  << std::endl;
252  }
253  } else if (cutIter->second->mode_ == DiscriminantCutEntry::kVariableCut) {
254  double cutVariable = (*cutIter->second->cutVariable_)(*tau);
255  double xMin, xMax, dummy;
256  cutIter->second->cutFunction_->GetPoint(0, xMin, dummy);
257  cutIter->second->cutFunction_->GetPoint(cutIter->second->cutFunction_->GetN() - 1, xMax, dummy);
258  const double epsilon = 1.e-3;
259  if (cutVariable < (xMin + epsilon))
260  cutVariable = xMin + epsilon;
261  else if (cutVariable > (xMax - epsilon))
262  cutVariable = xMax - epsilon;
263  double cutValue = cutIter->second->cutFunction_->Eval(cutVariable);
264  passesCuts = (disc_result > cutValue);
265  if (verbosity_) {
266  std::cout << "cutValue (@" << cutVariable << ") = " << cutValue << " --> passesCuts = " << passesCuts
267  << std::endl;
268  }
269  } else
270  assert(0);
271 
272  return passesCuts;
273 }
274 
276  // recoTauDiscriminantCutMultiplexer
278  desc.add<edm::InputTag>("toMultiplex", edm::InputTag("fixme"));
279  desc.add<int>("verbosity", 0);
280 
281  {
282  edm::ParameterSet pset_mapping;
283  pset_mapping.addParameter<unsigned int>("category", 0);
284  pset_mapping.addParameter<double>("cut", 0.);
285  edm::ParameterSetDescription desc_mapping;
286  desc_mapping.add<unsigned int>("category", 0);
287  desc_mapping.addNode(edm::ParameterDescription<std::string>("cut", true) xor
288  edm::ParameterDescription<double>("cut", true));
289  // it seems the parameter string "variable" exists only when "cut" is string
290  // see hpsPFTauDiscriminationByVLooseIsolationMVArun2v1DBdR03oldDMwLT in RecoTauTag/Configuration/python/HPSPFTaus_cff.py
291  desc_mapping.addOptional<std::string>("variable")->setComment("the parameter is required when \"cut\" is string");
292  // desc_mapping.add<double>("cut",0.);
293  std::vector<edm::ParameterSet> vpsd_mapping;
294  vpsd_mapping.push_back(pset_mapping);
295  desc.addVPSet("mapping", desc_mapping, vpsd_mapping);
296  }
297 
298  desc.add<edm::FileInPath>("inputFileName", edm::FileInPath("RecoTauTag/RecoTau/data/emptyMVAinputFile"));
299  desc.add<bool>("loadMVAfromDB", true);
300  fillProducerDescriptions(desc); // inherited from the base
301  desc.add<std::string>("mvaOutput_normalization", "");
302  desc.add<edm::InputTag>("key", edm::InputTag("fixme"));
303  descriptions.add("recoTauDiscriminantCutMultiplexerDefault", desc);
304 }
305 
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:525
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)
const std::vector< std::pair< float, float > > & limits() const
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:124
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:73
RecoTauDiscriminantCutMultiplexer(const edm::ParameterSet &pset)
std::string fullPath() const
Definition: FileInPath.cc:163
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