File indexing completed on 2024-09-07 04:37:24
0001 #ifndef ConfigurableAnalysis_CachingVariable_H
0002 #define ConfigurableAnalysis_CachingVariable_H
0003
0004 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0005 #include "FWCore/Framework/interface/Event.h"
0006 #include "FWCore/Framework/interface/ConsumesCollector.h"
0007 #include "DataFormats/Common/interface/Handle.h"
0008 #include "FWCore/ServiceRegistry/interface/Service.h"
0009 #include "CommonTools/Utils/interface/StringObjectFunction.h"
0010 #include "CommonTools/Utils/interface/StringCutObjectSelector.h"
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012
0013 #include "CommonTools/UtilAlgos/interface/InputTagDistributor.h"
0014
0015 namespace edm {
0016 class EventSetup;
0017 }
0018 #include <vector>
0019 #include "TString.h"
0020
0021 class Description {
0022 public:
0023 Description() {}
0024 Description(std::vector<std::string>& d) : d_(d) {}
0025 std::string text() const {
0026 std::string text;
0027 for (unsigned int i = 0; i != d_.size(); ++i)
0028 text += d_[i] + "\n";
0029 return text;
0030 }
0031 const std::vector<std::string> lines() { return d_; }
0032 void addLine(const std::string& l) { d_.push_back(l); }
0033
0034 private:
0035 std::vector<std::string> d_;
0036 };
0037
0038 class VariableComputer;
0039
0040 class CachingVariable {
0041 public:
0042
0043 typedef double valueType;
0044 typedef std::pair<bool, valueType> evalType;
0045 typedef std::map<std::string, const CachingVariable*> vMap;
0046 struct CachingVariableFactoryArg {
0047 CachingVariableFactoryArg(const CachingVariableFactoryArg& copy) : n(copy.n), m(copy.m), iConfig(copy.iConfig) {}
0048 CachingVariableFactoryArg(std::string& N, CachingVariable::vMap& M, edm::ParameterSet& P)
0049 : n(N), m(M), iConfig(P) {}
0050 std::string& n;
0051 CachingVariable::vMap& m;
0052 edm::ParameterSet& iConfig;
0053 };
0054
0055 CachingVariable(std::string m, std::string n, const edm::ParameterSet& iConfig, edm::ConsumesCollector& iC)
0056 : cache_(std::make_pair(false, 0)), method_(m), name_(n), conf_(iConfig) {}
0057
0058 virtual ~CachingVariable() {}
0059
0060
0061 bool compute(const edm::Event& iEvent) const { return baseEval(iEvent).first; }
0062
0063
0064 valueType operator()(const edm::Event& iEvent) const { return baseEval(iEvent).second; }
0065
0066 const std::string& name() const { return name_; }
0067 const std::string& method() const { return method_; }
0068 const Description& description() const { return d_; }
0069 void addDescriptionLine(const std::string& s) { d_.addLine(s); }
0070 const std::string& holderName() const { return holderName_; }
0071 void setHolder(std::string hn) const { holderName_ = hn; }
0072
0073 void print() const { edm::LogVerbatim("CachingVariable") << name() << "\n" << description().text(); }
0074
0075 protected:
0076 mutable evalType cache_;
0077 mutable edm::Event::CacheIdentifier_t eventCacheID_ = 0;
0078
0079 std::string method_;
0080 std::string name_;
0081 mutable std::string holderName_;
0082 void setCache(valueType& v) const {
0083 cache_.first = true;
0084 cache_.second = v;
0085 }
0086 void setNotCompute() const {
0087 cache_.first = false;
0088 cache_.second = 0;
0089 }
0090 evalType& baseEval(const edm::Event& iEvent) const {
0091 if (notSeenThisEventAlready(iEvent)) {
0092 LogDebug("CachingVariable") << name_ + ":" + holderName_ << " is checking once";
0093 cache_ = eval(iEvent);
0094 }
0095 return cache_;
0096 }
0097 bool notSeenThisEventAlready(const edm::Event& iEvent) const {
0098 bool retValue = (std::numeric_limits<edm::Event::CacheIdentifier_t>::max() != eventCacheID_ and
0099 eventCacheID_ != iEvent.cacheIdentifier());
0100 if (retValue) {
0101 eventCacheID_ = iEvent.cacheIdentifier();
0102 }
0103 return retValue;
0104 }
0105
0106
0107 virtual evalType eval(const edm::Event& iEvent) const { return std::make_pair(false, 0); };
0108
0109 Description d_;
0110 edm::ParameterSet conf_;
0111 friend class VariableComputer;
0112 };
0113
0114 class ComputedVariable;
0115 class VariableComputer {
0116 public:
0117 VariableComputer(const CachingVariable::CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC);
0118 virtual ~VariableComputer() {}
0119
0120 virtual void compute(const edm::Event& iEvent) const = 0;
0121 const std::string& name() const { return name_; }
0122 void declare(std::string var, edm::ConsumesCollector& iC);
0123 void assign(std::string var, double& value) const;
0124 void doesNotCompute() const;
0125 void doesNotCompute(std::string var) const;
0126
0127 bool notSeenThisEventAlready(const edm::Event& iEvent) const {
0128 bool retValue = (std::numeric_limits<edm::Event::CacheIdentifier_t>::max() != eventCacheID_ and
0129 eventCacheID_ != iEvent.cacheIdentifier());
0130 if (retValue) {
0131 eventCacheID_ = iEvent.cacheIdentifier();
0132 }
0133 return retValue;
0134 }
0135
0136 protected:
0137 const CachingVariable::CachingVariableFactoryArg& arg_;
0138 std::string name_;
0139 std::string method_;
0140 mutable std::map<std::string, const ComputedVariable*> iCompute_;
0141 std::string separator_;
0142
0143 mutable edm::Event::CacheIdentifier_t eventCacheID_ = 0;
0144 };
0145
0146 #include "FWCore/PluginManager/interface/PluginFactory.h"
0147 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0148
0149 typedef edmplugin::PluginFactory<CachingVariable*(CachingVariable::CachingVariableFactoryArg,
0150 edm::ConsumesCollector& iC)>
0151 CachingVariableFactory;
0152 typedef edmplugin::PluginFactory<VariableComputer*(CachingVariable::CachingVariableFactoryArg,
0153 edm::ConsumesCollector& iC)>
0154 VariableComputerFactory;
0155
0156 class ComputedVariable : public CachingVariable {
0157 public:
0158 ComputedVariable(const CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC);
0159 ComputedVariable(
0160 const std::string& M, std::string& N, edm::ParameterSet& P, const VariableComputer* c, edm::ConsumesCollector& iC)
0161 : CachingVariable(M, N, P, iC), myComputer(c) {}
0162 ~ComputedVariable() override {}
0163
0164 evalType eval(const edm::Event& iEvent) const override {
0165 if (myComputer->notSeenThisEventAlready(iEvent))
0166 myComputer->compute(iEvent);
0167 return cache_;
0168 }
0169
0170 private:
0171 std::unique_ptr<const VariableComputer> myComputer;
0172 };
0173
0174 class VariableComputerTest : public VariableComputer {
0175 public:
0176 VariableComputerTest(const CachingVariable::CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC);
0177 ~VariableComputerTest() override {}
0178
0179 void compute(const edm::Event& iEvent) const override;
0180 };
0181
0182 class Splitter : public CachingVariable {
0183 public:
0184 Splitter(std::string method, std::string n, const edm::ParameterSet& iConfig, edm::ConsumesCollector& iC)
0185 : CachingVariable(method, n, iConfig, iC) {}
0186
0187
0188 CachingVariable::evalType eval(const edm::Event& iEvent) const override = 0;
0189
0190 unsigned int maxIndex() const { return maxSlots() - 1; }
0191
0192
0193 virtual unsigned int maxSlots() const { return labels_.size(); }
0194
0195 const std::string shortLabel(unsigned int i) const {
0196 if (i >= short_labels_.size()) {
0197 edm::LogError("Splitter") << "trying to access slots short_label at index: " << i
0198 << "while of size: " << short_labels_.size() << "\n"
0199 << conf_.dump();
0200 return short_labels_.back();
0201 } else
0202 return short_labels_[i];
0203 }
0204
0205 const std::string& label(unsigned int i) const {
0206 if (i >= labels_.size()) {
0207 edm::LogError("Splitter") << "trying to access slots label at index: " << i << "while of size: " << labels_.size()
0208 << "\n"
0209 << conf_.dump();
0210 return labels_.back();
0211 } else
0212 return labels_[i];
0213 }
0214
0215 protected:
0216 std::vector<std::string> labels_;
0217 std::vector<std::string> short_labels_;
0218 };
0219
0220 class VarSplitter : public Splitter {
0221 public:
0222 VarSplitter(const CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC)
0223 : Splitter("VarSplitter", arg.n, arg.iConfig, iC) {
0224 var_ = arg.iConfig.getParameter<std::string>("var");
0225 useUnderFlow_ = arg.iConfig.getParameter<bool>("useUnderFlow");
0226 useOverFlow_ = arg.iConfig.getParameter<bool>("useOverFlow");
0227 slots_ = arg.iConfig.getParameter<std::vector<double> >("slots");
0228 if (useUnderFlow_) {
0229 labels_.push_back("underflow");
0230 short_labels_.push_back("_" + arg.n + "_underflow");
0231 }
0232 std::vector<std::string> confLabels;
0233 if (arg.iConfig.exists("labels")) {
0234 confLabels = arg.iConfig.getParameter<std::vector<std::string> >("labels");
0235 } else {
0236 std::string labelFormat = arg.iConfig.getParameter<std::string>("labelsFormat");
0237 for (unsigned int is = 0; is != slots_.size() - 1; ++is) {
0238 std::string l(Form(labelFormat.c_str(), slots_[is], slots_[is + 1]));
0239 confLabels.push_back(l);
0240 }
0241 }
0242 for (unsigned int i = 0; i != confLabels.size(); ++i) {
0243 labels_.push_back(confLabels[i]);
0244 std::stringstream ss;
0245 ss << "_" << arg.n << "_" << i;
0246 short_labels_.push_back(ss.str());
0247 }
0248 if (useOverFlow_) {
0249 labels_.push_back("overFlow");
0250 short_labels_.push_back("_" + arg.n + "_overFlow");
0251 }
0252
0253
0254 if (labels_.size() != maxSlots())
0255 edm::LogError("Splitter") << "splitter with name: " << name() << " has inconsistent configuration\n"
0256 << conf_.dump();
0257
0258 arg.m[arg.n] = this;
0259 }
0260
0261 CachingVariable::evalType eval(const edm::Event& iEvent) const override;
0262
0263
0264 unsigned int maxSlots() const override {
0265 unsigned int s = slots_.size() - 1;
0266 if (useUnderFlow_)
0267 s++;
0268 if (useOverFlow_)
0269 s++;
0270 return s;
0271 }
0272
0273 protected:
0274 std::string var_;
0275 bool useUnderFlow_;
0276 bool useOverFlow_;
0277 std::vector<double> slots_;
0278 };
0279
0280 template <typename Object, const char* label>
0281 class ExpressionVariable : public CachingVariable {
0282 public:
0283 ExpressionVariable(const CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC)
0284 : CachingVariable(std::string(label) + "ExpressionVariable", arg.n, arg.iConfig, iC),
0285 f_(nullptr),
0286 forder_(nullptr) {
0287 srcTag_ = edm::Service<InputTagDistributorService>()->retrieve("src", arg.iConfig);
0288 src_ = iC.consumes<edm::View<Object> >(srcTag_);
0289
0290 if (arg.iConfig.exists("expr") && arg.iConfig.exists("index")) {
0291 std::string expr = arg.iConfig.getParameter<std::string>("expr");
0292 index_ = arg.iConfig.getParameter<unsigned int>("index");
0293 f_ = new StringObjectFunction<Object>(expr);
0294 addDescriptionLine("calculating: " + expr);
0295 std::stringstream ss;
0296 ss << "on object at index: " << index_ << " of: " << srcTag_;
0297
0298 if (arg.iConfig.exists("order")) {
0299 std::string order = arg.iConfig.getParameter<std::string>("order");
0300 forder_ = new StringObjectFunction<Object>(order);
0301 ss << " after sorting according to: " << order;
0302 } else
0303 forder_ = nullptr;
0304
0305 if (arg.iConfig.exists("selection")) {
0306 std::string selection = arg.iConfig.getParameter<std::string>("selection");
0307 selector_ = new StringCutObjectSelector<Object>(selection);
0308 ss << " and selecting only: " << selection;
0309 } else
0310 selector_ = nullptr;
0311
0312 addDescriptionLine(ss.str());
0313 ss.str("");
0314 arg.m[arg.n] = this;
0315 } else {
0316
0317 std::map<std::string, edm::Entry> indexEntry;
0318 if (arg.n.find("_N") != std::string::npos) {
0319
0320 std::vector<unsigned int> indexes = arg.iConfig.getParameter<std::vector<unsigned int> >("indexes");
0321 for (unsigned int iI = 0; iI != indexes.size(); ++iI) {
0322 edm::ParameterSet toUse = arg.iConfig;
0323 edm::Entry e("unsigned int", indexes[iI], true);
0324 std::stringstream ss;
0325
0326 ss << indexes[iI] + 1;
0327 indexEntry.insert(std::make_pair(ss.str(), e));
0328 }
0329 }
0330
0331 std::map<std::string, edm::Entry> varEntry;
0332 if (arg.n.find("_V") != std::string::npos) {
0333
0334 std::vector<std::string> vars = arg.iConfig.getParameter<std::vector<std::string> >("vars");
0335 for (unsigned int v = 0; v != vars.size(); ++v) {
0336 unsigned int sep = vars[v].find(':');
0337 std::string name = vars[v].substr(0, sep);
0338 std::string expr = vars[v].substr(sep + 1);
0339
0340 edm::Entry e("string", expr, true);
0341 varEntry.insert(std::make_pair(name, e));
0342 }
0343 }
0344
0345 std::string radical = arg.n;
0346
0347 if (!varEntry.empty())
0348 radical = radical.substr(0, radical.size() - 2);
0349
0350 if (!indexEntry.empty())
0351 radical = radical.substr(0, radical.size() - 2);
0352
0353 if (varEntry.empty()) {
0354
0355 for (std::map<std::string, edm::Entry>::iterator iIt = indexEntry.begin(); iIt != indexEntry.end(); ++iIt) {
0356 edm::ParameterSet toUse = arg.iConfig;
0357 toUse.insert(true, "index", iIt->second);
0358 std::string newVname = radical + iIt->first;
0359
0360
0361 new ExpressionVariable(CachingVariable::CachingVariableFactoryArg(newVname, arg.m, toUse), iC);
0362 }
0363 } else {
0364 for (std::map<std::string, edm::Entry>::iterator vIt = varEntry.begin(); vIt != varEntry.end(); ++vIt) {
0365 if (indexEntry.empty()) {
0366 edm::ParameterSet toUse = arg.iConfig;
0367 toUse.insert(true, "expr", vIt->second);
0368 std::string newVname = radical + vIt->first;
0369
0370
0371 new ExpressionVariable(CachingVariable::CachingVariableFactoryArg(newVname, arg.m, toUse), iC);
0372 } else {
0373 for (std::map<std::string, edm::Entry>::iterator iIt = indexEntry.begin(); iIt != indexEntry.end(); ++iIt) {
0374 edm::ParameterSet toUse = arg.iConfig;
0375 toUse.insert(true, "expr", vIt->second);
0376 toUse.insert(true, "index", iIt->second);
0377 std::string newVname = radical + iIt->first + vIt->first;
0378
0379
0380 new ExpressionVariable(CachingVariable::CachingVariableFactoryArg(newVname, arg.m, toUse), iC);
0381 }
0382 }
0383 }
0384 }
0385
0386
0387
0388
0389 }
0390 }
0391 ~ExpressionVariable() override {
0392 if (f_)
0393 delete f_;
0394 if (forder_)
0395 delete forder_;
0396 if (selector_)
0397 delete selector_;
0398 }
0399
0400 CachingVariable::evalType eval(const edm::Event& iEvent) const override {
0401 if (!f_) {
0402 edm::LogError(method()) << " no parser attached.";
0403 return std::make_pair(false, 0);
0404 }
0405 edm::Handle<edm::View<Object> > oH;
0406 iEvent.getByToken(src_, oH);
0407 if (index_ >= oH->size()) {
0408 LogDebug(method()) << "fail to get object at index: " << index_ << " in collection: " << srcTag_;
0409 return std::make_pair(false, 0);
0410 }
0411
0412
0413 if (selector_ || forder_) {
0414 std::vector<const Object*> copyToSort(0);
0415 copyToSort.reserve(oH->size());
0416 for (unsigned int i = 0; i != oH->size(); ++i) {
0417 if (selector_ && !((*selector_)((*oH)[i])))
0418 continue;
0419 copyToSort.push_back(&(*oH)[i]);
0420 }
0421 if (index_ >= copyToSort.size())
0422 return std::make_pair(false, 0);
0423 if (forder_)
0424 std::sort(copyToSort.begin(), copyToSort.end(), sortByStringFunction<Object>(forder_));
0425
0426 const Object* o = copyToSort[index_];
0427 return std::make_pair(true, (*f_)(*o));
0428 } else {
0429 const Object& o = (*oH)[index_];
0430 return std::make_pair(true, (*f_)(o));
0431 }
0432 }
0433
0434 private:
0435 edm::InputTag srcTag_;
0436 edm::EDGetTokenT<edm::View<Object> > src_;
0437 unsigned int index_;
0438 StringObjectFunction<Object>* f_;
0439 StringObjectFunction<Object>* forder_;
0440 StringCutObjectSelector<Object>* selector_;
0441 };
0442
0443 template <typename LHS, const char* lLHS, typename RHS, const char* lRHS, typename Calculator>
0444 class TwoObjectVariable : public CachingVariable {
0445 public:
0446 TwoObjectVariable(const CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC)
0447 : CachingVariable(Calculator::calculationType() + std::string(lLHS) + std::string(lRHS), arg.n, arg.iConfig, iC),
0448 srcLhsTag_(edm::Service<InputTagDistributorService>()->retrieve("srcLhs", arg.iConfig)),
0449 srcLhs_(iC.consumes<std::vector<LHS> >(srcLhsTag_)),
0450 indexLhs_(arg.iConfig.getParameter<unsigned int>("indexLhs")),
0451 srcRhsTag_(edm::Service<InputTagDistributorService>()->retrieve("srcRhs", arg.iConfig)),
0452 srcRhs_(iC.consumes<std::vector<RHS> >(srcRhsTag_)),
0453 indexRhs_(arg.iConfig.getParameter<unsigned int>("indexRhs")) {
0454 std::stringstream ss;
0455 addDescriptionLine(Calculator::description());
0456 ss << "with Obj1 at index: " << indexLhs_ << " of: " << srcLhs_;
0457 addDescriptionLine(ss.str());
0458 ss.str("");
0459 ss << "with Obj2 at index: " << indexRhs_ << " of: " << srcRhs_;
0460 addDescriptionLine(ss.str());
0461 ss.str("");
0462 arg.m[arg.n] = this;
0463 }
0464
0465 class getObject {
0466 public:
0467 getObject() : test(false), lhs(0), rhs(0) {}
0468 bool test;
0469 const LHS* lhs;
0470 const RHS* rhs;
0471 };
0472 getObject objects(const edm::Event& iEvent) const {
0473 getObject failed;
0474 edm::Handle<std::vector<LHS> > lhsH;
0475 iEvent.getByToken(srcLhs_, lhsH);
0476 if (lhsH.failedToGet()) {
0477 LogDebug("TwoObjectVariable") << name() << " could not get a collection with label: " << srcLhsTag_;
0478 return failed;
0479 }
0480 if (indexLhs_ >= lhsH->size()) {
0481 LogDebug("TwoObjectVariable") << name() << " tries to access index: " << indexLhs_ << " of: " << srcLhsTag_
0482 << " with: " << lhsH->size() << " entries.";
0483 return failed;
0484 }
0485 const LHS& lhs = (*lhsH)[indexLhs_];
0486
0487 edm::Handle<std::vector<RHS> > rhsH;
0488 iEvent.getByToken(srcRhs_, rhsH);
0489 if (rhsH.failedToGet()) {
0490 LogDebug("TwoObjectVariable") << name() << " could not get a collection with label: " << srcLhsTag_;
0491 return failed;
0492 }
0493
0494 if (indexRhs_ >= rhsH->size()) {
0495 LogDebug("TwoObjectVariable") << name() << " tries to access index: " << indexRhs_ << " of: " << srcRhsTag_
0496 << " with: " << rhsH->size() << " entries.";
0497 return failed;
0498 }
0499 const RHS& rhs = (*rhsH)[indexRhs_];
0500
0501 failed.test = true;
0502 failed.lhs = &lhs;
0503 failed.rhs = &rhs;
0504 return failed;
0505 }
0506
0507
0508 virtual CachingVariable::valueType calculate(getObject& o) const {
0509 Calculator calc;
0510 return calc(*o.lhs, *o.rhs);
0511 }
0512 CachingVariable::evalType eval(const edm::Event& iEvent) const override {
0513 getObject o = objects(iEvent);
0514 if (!o.test)
0515 return std::make_pair(false, 0);
0516 return std::make_pair(true, calculate(o));
0517 }
0518
0519 private:
0520 edm::InputTag srcLhsTag_;
0521 edm::EDGetTokenT<std::vector<LHS> > srcLhs_;
0522 unsigned int indexLhs_;
0523 edm::InputTag srcRhsTag_;
0524 edm::EDGetTokenT<std::vector<RHS> > srcRhs_;
0525 unsigned int indexRhs_;
0526 };
0527
0528 class VariablePower : public CachingVariable {
0529 public:
0530 VariablePower(const CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC)
0531 : CachingVariable("Power", arg.n, arg.iConfig, iC) {
0532 power_ = arg.iConfig.getParameter<double>("power");
0533 var_ = arg.iConfig.getParameter<std::string>("var");
0534 std::stringstream ss("Calculare X^Y, with X=");
0535 ss << var_ << " and Y=" << power_;
0536 addDescriptionLine(ss.str());
0537 arg.m[arg.n] = this;
0538 }
0539 ~VariablePower() override {}
0540
0541
0542 CachingVariable::evalType eval(const edm::Event& iEvent) const override;
0543
0544 private:
0545 double power_;
0546 std::string var_;
0547 };
0548
0549 template <typename TYPE>
0550 class SimpleValueVariable : public CachingVariable {
0551 public:
0552 SimpleValueVariable(const CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC)
0553 : CachingVariable("SimpleValueVariable", arg.n, arg.iConfig, iC),
0554 src_(iC.consumes<TYPE>(edm::Service<InputTagDistributorService>()->retrieve("src", arg.iConfig))) {
0555 arg.m[arg.n] = this;
0556 }
0557 CachingVariable::evalType eval(const edm::Event& iEvent) const override {
0558 edm::Handle<TYPE> value;
0559 iEvent.getByToken(src_, value);
0560 if (value.failedToGet() || !value.isValid())
0561 return std::make_pair(false, 0);
0562 else
0563 return std::make_pair(true, *value);
0564 }
0565
0566 private:
0567 edm::EDGetTokenT<TYPE> src_;
0568 };
0569
0570 template <typename TYPE>
0571 class SimpleValueVectorVariable : public CachingVariable {
0572 public:
0573 SimpleValueVectorVariable(const CachingVariableFactoryArg& arg, edm::ConsumesCollector& iC)
0574 : CachingVariable("SimpleValueVectorVariable", arg.n, arg.iConfig, iC),
0575 src_(iC.consumes<TYPE>(edm::Service<InputTagDistributorService>()->retrieve("src", arg.iConfig))),
0576 index_(arg.iConfig.getParameter<unsigned int>("index")) {
0577 arg.m[arg.n] = this;
0578 }
0579 CachingVariable::evalType eval(const edm::Event& iEvent) const override {
0580 edm::Handle<std::vector<TYPE> > values;
0581 iEvent.getByToken(src_, values);
0582 if (values.failedToGet() || !values.isValid())
0583 return std::make_pair(false, 0);
0584 else if (index_ >= values->size())
0585 return std::make_pair(false, 0);
0586 else
0587 return std::make_pair(true, (*values)[index_]);
0588 }
0589
0590 private:
0591 edm::EDGetTokenT<TYPE> src_;
0592 unsigned int index_;
0593 };
0594
0595 #endif