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  struct electron_config {
91  };
92 
93  struct photon_config {
96  };
97 
99 
100  void setEvent(const edm::Event&) final;
101 
102  void modifyObject(pat::Electron&) const final;
103  void modifyObject(pat::Photon&) const final;
104 
105 
106 private:
108  photon_config ph_conf;
109  std::vector<edm::Ptr<reco::GsfElectron>> eles_by_oop; // indexed by original object ptr
110  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > > ele_vmaps;
111  std::vector<edm::Ptr<reco::Photon>> phos_by_oop;
112  std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > > pho_vmaps;
113  mutable unsigned ele_idx,pho_idx; // hack here until we figure out why some slimmedPhotons don't have original object ptrs
114  bool overrideExistingValues_;
115 };
116 
117 
118 template<typename MapType,typename OutputType>
119 EGExtraInfoModifierFromValueMaps<MapType,OutputType>::
120 EGExtraInfoModifierFromValueMaps(const edm::ParameterSet& conf, edm::ConsumesCollector& cc) :
121  ModifyObjectValueBase(conf) {
122  constexpr char electronSrc[] = "electronSrc";
123  constexpr char photonSrc[] = "photonSrc";
124  overrideExistingValues_ = conf.exists("overrideExistingValues") ? conf.getParameter<bool>("overrideExistingValues") : false;
125  if( conf.exists("electron_config") ) {
126  const edm::ParameterSet& electrons = conf.getParameter<edm::ParameterSet>("electron_config");
127  if( electrons.exists(electronSrc) ) e_conf.tok_electron_src = cc.consumes<edm::View<pat::Electron>>(electrons.getParameter<edm::InputTag>(electronSrc));
128 
129  const std::vector<std::string> parameters = electrons.getParameterNames();
130  for( const std::string& name : parameters ) {
131  if( std::string(electronSrc) == name ) continue;
132  if( electrons.existsAs<edm::InputTag>(name) ) {
133  e_conf.tok_valuemaps[name] = cc.consumes<edm::ValueMap<MapType>>(electrons.getParameter<edm::InputTag>(name));
134  }
135  }
136  }
137  if( conf.exists("photon_config") ) {
138  const edm::ParameterSet& photons = conf.getParameter<edm::ParameterSet>("photon_config");
139  if( photons.exists(photonSrc) ) ph_conf.tok_photon_src = cc.consumes<edm::View<pat::Photon>>(photons.getParameter<edm::InputTag>(photonSrc));
140  const std::vector<std::string> parameters = photons.getParameterNames();
141  for( const std::string& name : parameters ) {
142  if( std::string(photonSrc) == name ) continue;
143  if( photons.existsAs<edm::InputTag>(name) ) {
144  ph_conf.tok_valuemaps[name] = cc.consumes<edm::ValueMap<MapType>>(photons.getParameter<edm::InputTag>(name));
145  }
146  }
147  }
148  ele_idx = pho_idx = 0;
149 }
150 
151 template<typename MapType,typename OutputType>
153 setEvent(const edm::Event& evt) {
154  eles_by_oop.clear();
155  phos_by_oop.clear();
156  ele_vmaps.clear();
157  pho_vmaps.clear();
158 
159  ele_idx = pho_idx = 0;
160 
161  if( !e_conf.tok_electron_src.isUninitialized() ) {
163  evt.getByToken(e_conf.tok_electron_src,eles);
164 
165  eles_by_oop.resize(eles->size());
166  std::copy(eles->ptrs().begin(), eles->ptrs().end(), eles_by_oop.begin());
167  }
168 
169  for(auto const& itr : e_conf.tok_valuemaps) evt.getByToken(itr.second,ele_vmaps[itr.second.index()]);
170 
171  if( !ph_conf.tok_photon_src.isUninitialized() ) {
173  evt.getByToken(ph_conf.tok_photon_src,phos);
174 
175  phos_by_oop.resize(phos->size());
176  std::copy(phos->ptrs().begin(), phos->ptrs().end(), phos_by_oop.begin());
177  }
178 
179  for(auto const& itr : ph_conf.tok_valuemaps) evt.getByToken(itr.second,pho_vmaps[itr.second.index()]);
180 }
181 
182 namespace {
183  template<typename T, typename U, typename V, typename MapType >
184  inline void assignValue(const T& ptr, const U& tok, const V& map, MapType& value) {
185  if( !tok.isUninitialized() ) value = map.find(tok.index())->second->get(ptr.id(),ptr.key());
186  }
187 }
188 
189 template<typename MapType,typename OutputType>
192  // we encounter two cases here, either we are running AOD -> MINIAOD
193  // and the value maps are to the reducedEG object, can use original object ptr
194  // or we are running MINIAOD->MINIAOD and we need to fetch the pat objects to reference
196  if( !e_conf.tok_electron_src.isUninitialized() ) ptr = eles_by_oop.at(ele_idx);
197  //now we go through and modify the objects using the valuemaps we read in
198  EGXtraModFromVMObjFiller<OutputType>::addValuesToObject(ele,ptr,e_conf.tok_valuemaps,
199  ele_vmaps,overrideExistingValues_);
200  ++ele_idx;
201 }
202 
203 
204 template<typename MapType,typename OutputType>
207  // we encounter two cases here, either we are running AOD -> MINIAOD
208  // and the value maps are to the reducedEG object, can use original object ptr
209  // or we are running MINIAOD->MINIAOD and we need to fetch the pat objects to reference
211  if( !ph_conf.tok_photon_src.isUninitialized() ) ptr = phos_by_oop.at(pho_idx);
212  //now we go through and modify the objects using the valuemaps we read in
213  EGXtraModFromVMObjFiller<OutputType>::addValuesToObject(pho,ptr,ph_conf.tok_valuemaps,
214  pho_vmaps,overrideExistingValues_);
215 
216  ++pho_idx;
217 }
218 
219 
220 template<typename OutputType>
221 template<typename ObjType,typename MapType>
224  const edm::Ptr<reco::Candidate>& ptr,
225  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
226  const std::pair<const std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > > & val_map,
227  bool overrideExistingValues)
228 {
229  MapType value{};
230  assignValue(ptr,val_map.second,vmaps,value);
231  if( overrideExistingValues || !obj.hasUserData(val_map.first) ) {
232  obj.addUserData(val_map.first,value,true);
233  } else {
234  throw cms::Exception("ValueNameAlreadyExists")
235  << "Trying to add new UserData = " << val_map.first
236  << " failed because it already exists and you didnt specify to override it (set in the config overrideExistingValues=cms.bool(True) )";
237  }
238 }
239 
240 template<>
241 template<typename ObjType,typename MapType>
244  const edm::Ptr<reco::Candidate>& ptr,
245  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
246  const std::pair<const std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > >& val_map,
247  bool overrideExistingValues)
248 {
249  float value(0.0);
250  assignValue(ptr,val_map.second,vmaps,value);
251  if( overrideExistingValues || !obj.hasUserFloat(val_map.first) ) {
252  obj.addUserFloat(val_map.first,value,true);
253  } else {
254  throw cms::Exception("ValueNameAlreadyExists")
255  << "Trying to add new UserFloat = " << val_map.first
256  << " failed because it already exists and you didnt specify to override it (set in the config overrideExistingValues=cms.bool(True) )";
257  }
258 }
259 
260 template<>
261 template<typename ObjType,typename MapType>
264  const edm::Ptr<reco::Candidate>& ptr,
265  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<MapType> > >& vmaps,
266  const std::pair<const std::string,edm::EDGetTokenT<edm::ValueMap<MapType> > >& val_map,
267  bool overrideExistingValues)
268 {
269  int value(0);
270  assignValue(ptr,val_map.second,vmaps,value);
271  if( overrideExistingValues || !obj.hasUserInt(val_map.first) ) {
272  obj.addUserInt(val_map.first,value,true);
273  } else {
274  throw cms::Exception("ValueNameAlreadyExists")
275  << "Trying to add new UserInt = " << val_map.first
276  << " failed because it already exists and you didnt specify to override it (set in the config overrideExistingValues=cms.bool(True) )";
277  }
278 }
279 
280 template<>
281 template<>
284  const edm::Ptr<reco::Candidate>& ptr,
285  const std::unordered_map<std::string,edm::EDGetTokenT<edm::ValueMap<float> > > & vmaps_token,
286  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > >& vmaps,
287  bool overrideExistingValues)
288 {
289  std::vector<std::pair<std::string,float >> ids;
290  for( auto itr = vmaps_token.begin(); itr != vmaps_token.end(); ++itr ) {
291  float idVal(0);
292  assignValue(ptr,itr->second,vmaps,idVal);
293  ids.push_back({itr->first,idVal});
294  }
295  std::sort(ids.begin(),ids.end(),[](auto& lhs,auto& rhs){return lhs.first<rhs.first;});
296  obj.setElectronIDs(ids);
297 }
298 
299 template<>
300 template<>
303  const edm::Ptr<reco::Candidate>& ptr,
304  const std::unordered_map<std::string,edm::EDGetTokenT<edm::ValueMap<float> > > & vmaps_token,
305  const std::unordered_map<unsigned,edm::Handle<edm::ValueMap<float> > >& vmaps,
306  bool overrideExistingValues)
307 {
308  //we do a float->bool conversion here to make things easier to be consistent with electrons
309  std::vector<std::pair<std::string,bool> > ids;
310  for( auto itr = vmaps_token.begin(); itr != vmaps_token.end(); ++itr ) {
311  float idVal(0);
312  assignValue(ptr,itr->second,vmaps,idVal);
313  ids.push_back({itr->first,idVal});
314  }
315  std::sort(ids.begin(),ids.end(),[](auto& lhs,auto& rhs){return lhs.first<rhs.first;});
316  obj.setPhotonIDs(ids);
317 }
318 
319 
320 #endif
std::unordered_map< std::string, ValMapToken > ValueMaps
T getParameter(std::string const &) const
Analysis-level Photon class.
Definition: Photon.h:47
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:161
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
def copy(args, dbName)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
bool exists(std::string const &parameterName) const
checks if a parameter exists
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:521
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.
edm::EDGetTokenT< edm::View< pat::Photon > > tok_photon_src
long double T
#define constexpr