CMS 3D CMS Logo

MultiToken.h
Go to the documentation of this file.
1 #ifndef RecoEgamma_EgammaTools_MultiToken_H
2 #define RecoEgamma_EgammaTools_MultiToken_H
3 
11 
12 /*
13  * This class is a wrapper around a vector of EDM tokens, of which at least one
14  * is expected to yield a valid handle.
15  *
16  * The first time you call getValidHandle() or getHandle(), it will go over all
17  * tokens and try to get a valid handle. If no token yields a valid handle, it
18  * will either throw and exception or return the last non-valid handle.
19  *
20  * Once it found a valid handle, it will remember which token was used to get
21  * it and therefore doesn't need to loop over all tokens from there on.
22  *
23  * Example use case: auto-detection of AOD vs. MiniAOD.
24  *
25  * Created by Jonas Rembser on August 3, 2018.
26  */
27 
28 #include <memory>
29 
30 template <typename T>
31 class MultiTokenT {
32 
33  using GoodIndexType = std::shared_ptr<std::atomic<int>>;
34 
35  public:
36 
37  template <typename ... Tags>
38  MultiTokenT(edm::ConsumesCollector && cc, Tags ... tags)
39  : isMaster_(true)
40  , tokens_({cc.mayConsume<T>(edm::InputTag(tags))...})
41  , goodIndex_(std::make_shared<std::atomic<int>>(-1))
42  {}
43 
44  // Constructor which gets the input tags from a config to create the tokens plus master token
45  template <typename S, typename ... Tags>
47  : isMaster_(false)
48  , tokens_({cc.mayConsume<T>(edm::InputTag(tags))...})
49  , goodIndex_(master.getGoodTokenIndexPtr())
50  {}
51 
52  // Constructor which gets the input tags from a config to create the tokens
53  template <typename ... Tags>
54  MultiTokenT(edm::ConsumesCollector && cc, const edm::ParameterSet& pset, Tags && ... tags)
55  : isMaster_(true)
56  , tokens_({cc.mayConsume<T>(pset.getParameter<edm::InputTag>(tags))...})
57  , goodIndex_(std::make_shared<std::atomic<int>>(-1))
58  {}
59 
60  // Constructor which gets the input tags from a config to create the tokens plus master token
61  template <typename S, typename ... Tags>
63  : isMaster_(false)
64  , tokens_({cc.mayConsume<T>(pset.getParameter<edm::InputTag>(tags))...})
65  , goodIndex_(master.getGoodTokenIndexPtr())
66  {}
67 
68  // Get a handle on the event data, non-valid handle is allowed
70  {
72 
73  // If we already know which token works, take that one
74  if (*goodIndex_ >= 0) {
75  iEvent.getByToken(tokens_[*goodIndex_], handle);
76  return handle;
77  }
78 
79  if (!isMaster_) {
80  throw cms::Exception("MultiTokenTException") <<
81  "Trying to get a handle from a depending MultiToken before the master!";
82  }
83 
84  // If not, set the good token index parallel to getting the handle
85  handle = getInitialHandle(iEvent);
86 
87  if (*goodIndex_ == -1) {
88  *goodIndex_ = tokens_.size() - 1;
89  }
90  return handle;
91  }
92 
93  // Get a handle on the event data,
94  // throw exception if no token yields a valid handle
96  {
98 
99  // If we already know which token works, take that one
100  if (*goodIndex_ >= 0) {
101  iEvent.getByToken(tokens_[*goodIndex_], handle);
102  if (!handle.isValid())
103  throw cms::Exception("MultiTokenTException") <<
104  "Token gave valid handle previously but not anymore!";
105  return handle;
106  }
107 
108  if (!isMaster_) {
109  throw cms::Exception("MultiTokenTException") <<
110  "Trying to get a handle from a depending MultiToken before the master!";
111  }
112 
113  // If not, set the good token index parallel to getting the handle
114  handle = getInitialHandle(iEvent);
115 
116  if (*goodIndex_ == -1) {
117  throw cms::Exception("MultiTokenTException") << "Neither handle is valid!";
118  }
119  return handle;
120  }
121 
122  // get the good token
124  {
125  // If we already know which token works, take that index
126  if (*goodIndex_ >= 0)
127  return tokens_[*goodIndex_];
128 
129  // If this is not a master MultiToken, just return what it got
130  if (!isMaster_) {
131  throw cms::Exception("MultiTokenTException") <<
132  "Trying to get a handle from a depending MultiToken before the master!";
133  }
134 
135  // Find which token is the good one by trying to get a handle
137  for (auto token:tokens_ ) {
138  iEvent.getByToken(token, handle);
139  if (handle.isValid()) {
140  return token;
141  }
142  }
143 
144  throw cms::Exception("MultiTokenTException") << "Neither token is valid!";
145  }
146 
147  int getGoodTokenIndex() const
148  {
149  return *goodIndex_;
150  }
151 
153  {
154  return goodIndex_;
155  }
156 
157  private:
158 
160  {
161  // Try to retrieve the collection from the event. If we fail to
162  // retrieve the collection with one name, we next look for the one with
163  // the other name and so on.
165  for (size_t i = 0; i < tokens_.size(); ++i) {
166  iEvent.getByToken(tokens_[i], handle);
167  if (handle.isValid()) {
168  *goodIndex_ = i;
169  return handle;
170  }
171  }
172  return handle;
173  }
174 
175  const bool isMaster_;
176  const std::vector<edm::EDGetTokenT<T>> tokens_;
178 };
179 
180 #endif
T getParameter(std::string const &) const
Master< F > master(const F &f)
Definition: FunctClone.h:68
const GoodIndexType goodIndex_
Definition: MultiToken.h:177
const std::vector< edm::EDGetTokenT< T > > tokens_
Definition: MultiToken.h:176
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
std::shared_ptr< std::atomic< int >> GoodIndexType
Definition: MultiToken.h:33
int iEvent
Definition: GenABIO.cc:224
edm::Handle< T > getValidHandle(const edm::Event &iEvent) const
Definition: MultiToken.h:95
const bool isMaster_
Definition: MultiToken.h:175
bool isValid() const
Definition: HandleBase.h:74
GoodIndexType getGoodTokenIndexPtr() const
Definition: MultiToken.h:152
MultiTokenT(edm::ConsumesCollector &&cc, const edm::ParameterSet &pset, Tags &&...tags)
Definition: MultiToken.h:54
double S(const TLorentzVector &, const TLorentzVector &)
Definition: Particle.cc:99
edm::Handle< T > getInitialHandle(const edm::Event &iEvent) const
Definition: MultiToken.h:159
edm::Handle< T > getHandle(const edm::Event &iEvent) const
Definition: MultiToken.h:69
int getGoodTokenIndex() const
Definition: MultiToken.h:147
MultiTokenT(const MultiTokenT< S > &master, edm::ConsumesCollector &&cc, Tags...tags)
Definition: MultiToken.h:46
MultiTokenT(const MultiTokenT< S > &master, edm::ConsumesCollector &&cc, const edm::ParameterSet &pset, Tags &&...tags)
Definition: MultiToken.h:62
long double T
MultiTokenT(edm::ConsumesCollector &&cc, Tags...tags)
Definition: MultiToken.h:38