Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:24:16

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   //every variable return double values
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   //does the variable computes
0061   bool compute(const edm::Event& iEvent) const { return baseEval(iEvent).first; }
0062 
0063   //accessor to the computed/cached value
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   //cannot be made purely virtual otherwise one cannot have purely CachingVariableObjects
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   //purely virtual here
0188   CachingVariable::evalType eval(const edm::Event& iEvent) const override = 0;
0189 
0190   unsigned int maxIndex() const { return maxSlots() - 1; }
0191 
0192   //maximum NUMBER of slots: counting over/under flows
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     //check consistency
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   //redefine the maximum number of slots
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     //old style constructor
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       //multiple instance constructor
0317       std::map<std::string, edm::Entry> indexEntry;
0318       if (arg.n.find("_N") != std::string::npos) {
0319         //will have to loop over indexes
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           //add +1 0->1, 1->2, ... in the variable label
0326           ss << indexes[iI] + 1;
0327           indexEntry.insert(std::make_pair(ss.str(), e));
0328         }
0329       }  //contains "_N"
0330 
0331       std::map<std::string, edm::Entry> varEntry;
0332       if (arg.n.find("_V") != std::string::npos) {
0333         //do something fancy for multiple variable from one PSet
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       }  //contains "_V"
0344 
0345       std::string radical = arg.n;
0346       //remove the "_V";
0347       if (!varEntry.empty())
0348         radical = radical.substr(0, radical.size() - 2);
0349       //remove the "_N";
0350       if (!indexEntry.empty())
0351         radical = radical.substr(0, radical.size() - 2);
0352 
0353       if (varEntry.empty()) {
0354         //loop only the indexes
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           //      std::cout<<"in the loop, creating variable with name: "<<newVname<<std::endl;
0360           // the constructor auto log the new variable in the map
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             //      std::cout<<"in the loop, creating variable with name: "<<newVname<<std::endl;
0370             // the constructor auto log the new variable in the map
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               //          std::cout<<"in the loop, creating variable with name: "<<newVname<<std::endl;
0379               // the constructor auto log the new variable in the map
0380               new ExpressionVariable(CachingVariable::CachingVariableFactoryArg(newVname, arg.m, toUse), iC);
0381             }
0382           }
0383         }
0384       }
0385       //there is a memory leak here, because the object we are in is not logged in the arg.m, the variable is not valid
0386       // anyways, but reside in memory with no ways of de-allocating it.
0387       // since the caching variables are actually "global" objects, it does not matter.
0388       // we cannot add it to the map, otherwise, it would be considered for eventV ntupler
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     //get the ordering right first. if required
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   //to be overloaded by the user
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   //concrete calculation of the variable
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