CMS 3D CMS Logo

EGExtraInfoModifierFromValueMaps.h
Go to the documentation of this file.
1 #ifndef RecoEgamma_EgammaTools_EGExtraInfoModifierFromValueMaps_h
2 #define RecoEgamma_EgammaTools_EGExtraInfoModifierFromValueMaps_h
3 
5 
9 
12 
13 #include <unordered_map>
14 
15 namespace {
16  const edm::InputTag empty_tag;
17 }
18 
19 //class: EGExtraInfoModifierFromValueMaps
20 //
21 //this is a generalisation of EGExtraInfoModiferFromFloatValueMaps
22 //orginal author of EGExtraInfoModiferFromFloatValueMaps : L. Gray (FNAL)
23 //converter to templated version: S. Harper (RAL)
24 //
25 //This class allows an data of an arbitrary type in a ValueMap for pat::Electrons or pat::Photons
26 //to be put in the pat::Electron/Photon as userData, userInt or userFloat
27 //
28 //IMPORTANT INFO:
29 //by default the ValueMap is keyed to the object the pat::Electron/Photon was created from
30 //if you want to use a ValueMap which is keyed to a different collection (ie perhaps the same
31 //as the electrons you are aring, you must set "electronSrc" and "photonSrc" inside the ele/pho configs
32 //so if you are running over slimmedElectrons and want to read a ValueMap keyed to slimmedElectrons
33 //you need to set "electron_config.electronSrc = cms.InputTag("slimmedElectrons")"
34 //
35 //It assumes that the object can be added via pat::PATObject::userData, see pat::PATObject for the
36 //constraints here
37 //
38 //The class has two template arguements:
39 // MapType : c++ type of the object stored in the value mape
40 // OutputType : c++ type of how you want to store it in the pat::PATObject
41 // this exists so you can specialise int and float (and future exceptions) to use
42 // pat::PATObject::userInt and pat::PATObject::userFloat
43 // The specialisations are done by EGXtraModFromVMObjFiller::addValueToObject
44 //
45 // MapType and OutputType do not have to be same (but are by default). This is useful as it allows
46 // things like bools to and unsigned ints to be converted to ints to be stored as a userInt
47 // rather than having to go to the bother of setting up userData hooks for them
48 
49 
50 namespace egmodifier{
51  class EGID{};//dummy class to be used as a template arguement
52 }
53 
54 template<typename OutputType>
56 public:
57  EGXtraModFromVMObjFiller()=delete;
58  ~EGXtraModFromVMObjFiller()=delete;
59 
60  //will do a UserData add but specialisations exist for float and ints
61  template<typename ObjType,typename MapType>
62  static void
63  addValueToObject(ObjType& obj,
64  const edm::Ptr<reco::Candidate>& ptr,
65  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
66  const std::pair<const std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > > & val_map,
67  bool overrideExistingValues);
68 
69  template<typename ObjType,typename MapType>
70  static void
71  addValuesToObject(ObjType& obj,
72  const edm::Ptr<reco::Candidate>& ptr,
73  const std::unordered_map<std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > > & vmaps_token,
74  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
75  bool overrideExistingValues){
76  for( auto itr = vmaps_token.begin(); itr != vmaps_token.end(); ++itr ) {
77  addValueToObject(obj,ptr,vmaps,*itr,overrideExistingValues);
78  }
79  }
80 };
81 
82 
83 template<typename MapType,typename OutputType=MapType>
85 public:
87  using ValueMaps = std::unordered_map<std::string,ValMapToken>;
88  using ValueMapsTags = std::unordered_map<std::string,edm::InputTag>;
89  struct electron_config {
94  };
95 
96  struct photon_config {
101  };
102 
104 
105  void setEvent(const edm::Event&) final;
106  void setEventContent(const edm::EventSetup&) final;
107  void setConsumes(edm::ConsumesCollector&) final;
108 
109  void modifyObject(pat::Electron&) const final;
110  void modifyObject(pat::Photon&) const final;
111 
112 
113 private:
115  photon_config ph_conf;
116  std::unordered_map<unsigned,edm::Ptr<reco::GsfElectron> > eles_by_oop; // indexed by original object ptr
117  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > > ele_vmaps;
118  std::unordered_map<unsigned,edm::Ptr<reco::Photon> > phos_by_oop;
119  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > > pho_vmaps;
120  mutable unsigned ele_idx,pho_idx; // hack here until we figure out why some slimmedPhotons don't have original object ptrs
121  bool overrideExistingValues_;
122 };
123 
124 
125 template<typename MapType,typename OutputType>
126 EGExtraInfoModifierFromValueMaps<MapType,OutputType>::
128  ModifyObjectValueBase(conf) {
129  constexpr char electronSrc[] = "electronSrc";
130  constexpr char photonSrc[] = "photonSrc";
131  overrideExistingValues_ = conf.exists("overrideExistingValues") ? conf.getParameter<bool>("overrideExistingValues") : false;
132  if( conf.exists("electron_config") ) {
133  const edm::ParameterSet& electrons = conf.getParameter<edm::ParameterSet>("electron_config");
134  if( electrons.exists(electronSrc) ) e_conf.electron_src = electrons.getParameter<edm::InputTag>(electronSrc);
135 
136  const std::vector<std::string> parameters = electrons.getParameterNames();
137  for( const std::string& name : parameters ) {
138  if( std::string(electronSrc) == name ) continue;
139  if( electrons.existsAs<edm::InputTag>(name) ) {
140  e_conf.valuemaps[name] = electrons.getParameter<edm::InputTag>(name);
141  }
142  }
143  }
144  if( conf.exists("photon_config") ) {
145  const edm::ParameterSet& photons = conf.getParameter<edm::ParameterSet>("photon_config");
146  if( photons.exists(photonSrc) ) ph_conf.photon_src = photons.getParameter<edm::InputTag>(photonSrc);
147  const std::vector<std::string> parameters = photons.getParameterNames();
148  for( const std::string& name : parameters ) {
149  if( std::string(photonSrc) == name ) continue;
150  if( photons.existsAs<edm::InputTag>(name) ) {
151  ph_conf.valuemaps[name] = photons.getParameter<edm::InputTag>(name);
152  }
153  }
154  }
155  ele_idx = pho_idx = 0;
156 }
157 
158 namespace {
159  template<typename T>
160  inline void get_product(const edm::Event& evt,
161  const edm::EDGetTokenT<edm::ValueMap<T> >& tok,
162  std::unordered_map<unsigned, edm::Handle<edm::ValueMap<T> > >& map) {
163  evt.getByToken(tok,map[tok.index()]);
164  }
165 }
166 
167 template<typename MapType,typename OutputType>
169 setEvent(const edm::Event& evt) {
170  eles_by_oop.clear();
171  phos_by_oop.clear();
172  ele_vmaps.clear();
173  pho_vmaps.clear();
174 
175  ele_idx = pho_idx = 0;
176 
177  if( !e_conf.tok_electron_src.isUninitialized() ) {
179  evt.getByToken(e_conf.tok_electron_src,eles);
180 
181  for( unsigned i = 0; i < eles->size(); ++i ) {
182  edm::Ptr<pat::Electron> ptr = eles->ptrAt(i);
183  eles_by_oop[i] = ptr;
184  }
185  }
186 
187  for( auto itr = e_conf.tok_valuemaps.begin(); itr != e_conf.tok_valuemaps.end(); ++itr ) {
188  get_product(evt,itr->second,ele_vmaps);
189  }
190 
191  if( !ph_conf.tok_photon_src.isUninitialized() ) {
193  evt.getByToken(ph_conf.tok_photon_src,phos);
194 
195  for( unsigned i = 0; i < phos->size(); ++i ) {
196  edm::Ptr<pat::Photon> ptr = phos->ptrAt(i);
197  phos_by_oop[i] = ptr;
198  }
199  }
200 
201  for( auto itr = ph_conf.tok_valuemaps.begin(); itr != ph_conf.tok_valuemaps.end(); ++itr ) {
202  get_product(evt,itr->second,pho_vmaps);
203  }
204 }
205 
206 
207 template<typename MapType,typename OutputType>
210 }
211 
212 namespace {
213  template<typename T>
214  inline void make_consumes(const edm::InputTag& tag,edm::EDGetTokenT<T>& token,
216  { if( !(empty_tag == tag) ) token = cc.consumes<T>(tag); }
217 }
218 
219 template<typename MapType,typename OutputType>
222  //setup electrons
223  if( !(empty_tag == e_conf.electron_src) ) e_conf.tok_electron_src = sumes.consumes<edm::View<pat::Electron> >(e_conf.electron_src);
224 
225  for( auto itr = e_conf.valuemaps.begin(); itr != e_conf.valuemaps.end(); ++itr ) {
226  make_consumes(itr->second,e_conf.tok_valuemaps[itr->first],sumes);
227  }
228 
229  // setup photons
230  if( !(empty_tag == ph_conf.photon_src) ) ph_conf.tok_photon_src = sumes.consumes<edm::View<pat::Photon> >(ph_conf.photon_src);
231 
232  for( auto itr = ph_conf.valuemaps.begin(); itr != ph_conf.valuemaps.end(); ++itr ) {
233  make_consumes(itr->second,ph_conf.tok_valuemaps[itr->first],sumes);
234  }
235 }
236 
237 namespace {
238  template<typename T, typename U, typename V, typename MapType >
239  inline void assignValue(const T& ptr, const U& tok, const V& map, MapType& value) {
240  if( !tok.isUninitialized() ) value = map.find(tok.index())->second->get(ptr.id(),ptr.key());
241  }
242 }
243 
244 template<typename MapType,typename OutputType>
247  // we encounter two cases here, either we are running AOD -> MINIAOD
248  // and the value maps are to the reducedEG object, can use original object ptr
249  // or we are running MINIAOD->MINIAOD and we need to fetch the pat objects to reference
251  if( !e_conf.tok_electron_src.isUninitialized() ) {
252  auto key = eles_by_oop.find(ele_idx);
253  if( key != eles_by_oop.end() ) {
254  ptr = key->second;
255  } else {
256  throw cms::Exception("BadElectronKey")
257  << "Original object pointer with key = " << ele.originalObjectRef().key()
258  << " not found in cache!";
259  }
260  }
261  //now we go through and modify the objects using the valuemaps we read in
262  EGXtraModFromVMObjFiller<OutputType>::addValuesToObject(ele,ptr,e_conf.tok_valuemaps,
263  ele_vmaps,overrideExistingValues_);
264  ++ele_idx;
265 }
266 
267 
268 template<typename MapType,typename OutputType>
271  // we encounter two cases here, either we are running AOD -> MINIAOD
272  // and the value maps are to the reducedEG object, can use original object ptr
273  // or we are running MINIAOD->MINIAOD and we need to fetch the pat objects to reference
275  if( !ph_conf.tok_photon_src.isUninitialized() ) {
276  auto key = phos_by_oop.find(pho_idx);
277  if( key != phos_by_oop.end() ) {
278  ptr = key->second;
279  } else {
280  throw cms::Exception("BadPhotonKey")
281  << "Original object pointer with key = " << pho.originalObjectRef().key() << " not found in cache!";
282  }
283  }
284  //now we go through and modify the objects using the valuemaps we read in
285  EGXtraModFromVMObjFiller<OutputType>::addValuesToObject(pho,ptr,ph_conf.tok_valuemaps,
286  pho_vmaps,overrideExistingValues_);
287 
288  ++pho_idx;
289 }
290 
291 
292 template<typename OutputType>
293 template<typename ObjType,typename MapType>
296  const edm::Ptr<reco::Candidate>& ptr,
297  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
298  const std::pair<const std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > > & val_map,
299  bool overrideExistingValues)
300 {
301  MapType value{};
302  assignValue(ptr,val_map.second,vmaps,value);
303  if( overrideExistingValues || !obj.hasUserData(val_map.first) ) {
304  obj.addUserData(val_map.first,value,true);
305  } else {
306  throw cms::Exception("ValueNameAlreadyExists")
307  << "Trying to add new UserData = " << val_map.first
308  << " failed because it already exists and you didnt specify to override it (set in the config overrideExistingValues=cms.bool(True) )";
309  }
310 }
311 
312 template<>
313 template<typename ObjType,typename MapType>
316  const edm::Ptr<reco::Candidate>& ptr,
317  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
318  const std::pair<const std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > >& val_map,
319  bool overrideExistingValues)
320 {
321  float value(0.0);
322  assignValue(ptr,val_map.second,vmaps,value);
323  if( overrideExistingValues || !obj.hasUserFloat(val_map.first) ) {
324  obj.addUserFloat(val_map.first,value,true);
325  } else {
326  throw cms::Exception("ValueNameAlreadyExists")
327  << "Trying to add new UserFloat = " << val_map.first
328  << " failed because it already exists and you didnt specify to override it (set in the config overrideExistingValues=cms.bool(True) )";
329  }
330 }
331 
332 template<>
333 template<typename ObjType,typename MapType>
336  const edm::Ptr<reco::Candidate>& ptr,
337  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
338  const std::pair<const std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > >& val_map,
339  bool overrideExistingValues)
340 {
341  int value(0);
342  assignValue(ptr,val_map.second,vmaps,value);
343  if( overrideExistingValues || !obj.hasUserInt(val_map.first) ) {
344  obj.addUserInt(val_map.first,value,true);
345  } else {
346  throw cms::Exception("ValueNameAlreadyExists")
347  << "Trying to add new UserInt = " << val_map.first
348  << " failed because it already exists and you didnt specify to override it (set in the config overrideExistingValues=cms.bool(True) )";
349  }
350 }
351 
352 template<>
353 template<>
356  const edm::Ptr<reco::Candidate>& ptr,
357  const std::unordered_map<std::string,edm::EDGetTokenT<edm::ValueMap<float> > > & vmaps_token,
358  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > >& vmaps,
359  bool overrideExistingValues)
360 {
361  std::vector<std::pair<std::string,float >> ids;
362  for( auto itr = vmaps_token.begin(); itr != vmaps_token.end(); ++itr ) {
363  float idVal(0);
364  assignValue(ptr,itr->second,vmaps,idVal);
365  ids.push_back({itr->first,idVal});
366  }
367  std::sort(ids.begin(),ids.end(),[](auto& lhs,auto& rhs){return lhs.first<rhs.first;});
368  obj.setElectronIDs(ids);
369 }
370 
371 template<>
372 template<>
375  const edm::Ptr<reco::Candidate>& ptr,
376  const std::unordered_map<std::string,edm::EDGetTokenT<edm::ValueMap<float> > > & vmaps_token,
377  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > >& vmaps,
378  bool overrideExistingValues)
379 {
380  //we do a float->bool conversion here to make things easier to be consistent with electrons
381  std::vector<std::pair<std::string,bool> > ids;
382  for( auto itr = vmaps_token.begin(); itr != vmaps_token.end(); ++itr ) {
383  float idVal(0);
384  assignValue(ptr,itr->second,vmaps,idVal);
385  ids.push_back({itr->first,idVal});
386  }
387  std::sort(ids.begin(),ids.end(),[](auto& lhs,auto& rhs){return lhs.first<rhs.first;});
388  obj.setPhotonIDs(ids);
389 }
390 
391 
392 #endif
std::unordered_map< std::string, ValMapToken > ValueMaps
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
T getParameter(std::string const &) const
Analysis-level Photon class.
Definition: Photon.h:47
std::unordered_map< std::string, edm::InputTag > ValueMapsTags
Definition: Photon.py:1
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:186
void setElectronIDs(const std::vector< IdPair > &ids)
Store multiple electron ID values, discarding existing ones. The first one in the list becomes the &#39;d...
Definition: Electron.h:146
key_type key() const
Definition: Ptr.h:185
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
bool exists(std::string const &parameterName) const
checks if a parameter exists
#define constexpr
Definition: HeavyIon.h:7
U second(std::pair< T, U > const &p)
static void addValueToObject(ObjType &obj, const edm::Ptr< reco::Candidate > &ptr, const std::unordered_map< unsigned, edm::Handle< edm::ValueMap< MapType > > > &vmaps, const std::pair< const std::string, edm::EDGetTokenT< edm::ValueMap< MapType > > > &val_map, bool overrideExistingValues)
void setPhotonIDs(const std::vector< IdPair > &ids)
Definition: Photon.h:110
static void addValuesToObject(ObjType &obj, const edm::Ptr< reco::Candidate > &ptr, const std::unordered_map< std::string, edm::EDGetTokenT< edm::ValueMap< MapType > > > &vmaps_token, const std::unordered_map< unsigned, edm::Handle< edm::ValueMap< MapType > > > &vmaps, bool overrideExistingValues)
def template(fileName, svg, replaceme="REPLACEME")
Definition: svgfig.py:520
Definition: value.py:1
std::vector< std::string > getParameterNames() const
const edm::Ptr< reco::Candidate > & originalObjectRef() const
reference to original object. Returns a null reference if not available
Definition: PATObject.h:500
Analysis-level electron class.
Definition: Electron.h:52
void modifyObject(pat::Electron &) const final
edm::EDGetTokenT< edm::View< pat::Electron > > tok_electron_src
fixed size matrix
HLT enums.
void setEventContent(const edm::EventSetup &) final
edm::EDGetTokenT< edm::View< pat::Photon > > tok_photon_src
void setConsumes(edm::ConsumesCollector &) final
long double T