Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-03-23 16:00:20

0001 #include "FWCore/Framework/interface/stream/EDProducer.h"
0002 #include "FWCore/Framework/interface/one/EDProducer.h"
0003 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0004 #include "FWCore/Framework/interface/ConsumesCollector.h"
0005 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0006 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0007 #include "FWCore/ParameterSet/interface/EmptyGroupDescription.h"
0008 #include "FWCore/ParameterSet/interface/allowedValues.h"
0009 #include "DataFormats/Common/interface/View.h"
0010 #include "DataFormats/Common/interface/ValueMap.h"
0011 #include "DataFormats/NanoAOD/interface/FlatTable.h"
0012 #include "Utilities/General/interface/ClassName.h"
0013 #include "DataFormats/L1Trigger/interface/BXVector.h"
0014 
0015 #include "CommonTools/Utils/interface/StringCutObjectSelector.h"
0016 #include "CommonTools/Utils/interface/StringObjectFunction.h"
0017 #include "CommonTools/Utils/interface/TypedStringObjectMethodCaller.h"
0018 
0019 #include <memory>
0020 #include <vector>
0021 
0022 // Base class for dumped variables
0023 class VariableBase {
0024 public:
0025   VariableBase(const std::string &aname, const edm::ParameterSet &cfg)
0026       : name_(aname),
0027         doc_(cfg.getParameter<std::string>("doc")),
0028         precision_(cfg.existsAs<int>("precision") ? cfg.getParameter<int>("precision")
0029                                                   : (cfg.existsAs<std::string>("precision") ? -2 : -1)) {}
0030   virtual ~VariableBase() {}
0031   const std::string &name() const { return name_; }
0032 
0033 protected:
0034   std::string name_, doc_;
0035   int precision_;
0036 };
0037 
0038 // Object member variables and methods
0039 template <typename ObjType>
0040 class Variable : public VariableBase {
0041 public:
0042   Variable(const std::string &aname, const edm::ParameterSet &cfg) : VariableBase(aname, cfg) {}
0043   virtual void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const = 0;
0044 };
0045 
0046 template <typename ObjType, typename StringFunctor, typename ValType>
0047 class FuncVariable : public Variable<ObjType> {
0048 public:
0049   FuncVariable(const std::string &aname, const edm::ParameterSet &cfg)
0050       : Variable<ObjType>(aname, cfg),
0051         func_(cfg.getParameter<std::string>("expr"), cfg.getUntrackedParameter<bool>("lazyEval")),
0052         precisionFunc_(cfg.existsAs<std::string>("precision") ? cfg.getParameter<std::string>("precision") : "23",
0053                        cfg.getUntrackedParameter<bool>("lazyEval")) {}
0054   ~FuncVariable() override {}
0055 
0056   void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const override {
0057     std::vector<ValType> vals(selobjs.size());
0058     for (unsigned int i = 0, n = vals.size(); i < n; ++i) {
0059       vals[i] = func_(*selobjs[i]);
0060       if constexpr (std::is_same<ValType, float>()) {
0061         if (this->precision_ == -2) {
0062           auto prec = precisionFunc_(*selobjs[i]);
0063           if (prec > 0) {
0064             vals[i] = MiniFloatConverter::reduceMantissaToNbitsRounding(vals[i], prec);
0065           }
0066         }
0067       }
0068     }
0069     out.template addColumn<ValType>(this->name_, vals, this->doc_, this->precision_);
0070   }
0071 
0072 protected:
0073   StringFunctor func_;
0074   StringFunctor precisionFunc_;
0075 };
0076 
0077 // Collection variables: i.e. variables that is variable-size collection, e.g. std::vector
0078 template <typename ObjType>
0079 class CollectionVariable : public VariableBase {
0080 public:
0081   CollectionVariable(const std::string &aname, const edm::ParameterSet &cfg) : VariableBase(aname, cfg) {}
0082   virtual std::unique_ptr<std::vector<unsigned int>> getCounts(std::vector<const ObjType *> &selobjs) const = 0;
0083   virtual void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const = 0;
0084 };
0085 
0086 template <typename ObjType, typename CollectionStringFunctor, typename PrecisionStringFunctor, typename ValType>
0087 class FuncCollectionVariable : public CollectionVariable<ObjType> {
0088 public:
0089   FuncCollectionVariable(const std::string &aname, const edm::ParameterSet &cfg)
0090       : CollectionVariable<ObjType>(aname, cfg),
0091         func_(cfg.getParameter<std::string>("expr"), cfg.getUntrackedParameter<bool>("lazyEval")),
0092         precisionFunc_(cfg.existsAs<std::string>("precision") ? cfg.getParameter<std::string>("precision") : "23",
0093                        cfg.getUntrackedParameter<bool>("lazyEval")) {}
0094   ~FuncCollectionVariable() override {}
0095 
0096   std::unique_ptr<std::vector<unsigned int>> getCounts(std::vector<const ObjType *> &selobjs) const override {
0097     auto counts = std::make_unique<std::vector<unsigned int>>();
0098     for (auto const &obj : selobjs)
0099       counts->push_back(func_(*obj).size());
0100     return counts;
0101   }
0102 
0103   void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const override {
0104     std::vector<ValType> vals;
0105     for (unsigned int i = 0; i < selobjs.size(); ++i) {
0106       for (ValType val : func_(*selobjs[i])) {
0107         if constexpr (std::is_same<ValType, float>()) {
0108           if (this->precision_ == -2) {
0109             auto prec = precisionFunc_(*selobjs[i]);
0110             if (prec > 0) {
0111               val = MiniFloatConverter::reduceMantissaToNbitsRounding(val, prec);
0112             }
0113           }
0114         }
0115         vals.push_back(val);
0116       }
0117     }
0118     out.template addColumn<ValType>(this->name_, vals, this->doc_, this->precision_);
0119   }
0120 
0121 protected:
0122   CollectionStringFunctor func_;          // functor to get collection objects
0123   PrecisionStringFunctor precisionFunc_;  // functor to get output precision
0124 };
0125 
0126 // External variables: i.e. variables that are not member or methods of the object
0127 template <typename ObjType>
0128 class ExtVariable : public VariableBase {
0129 public:
0130   ExtVariable(const std::string &aname, const edm::ParameterSet &cfg) : VariableBase(aname, cfg) {}
0131   virtual void fill(const edm::Event &iEvent,
0132                     std::vector<edm::Ptr<ObjType>> selptrs,
0133                     nanoaod::FlatTable &out) const = 0;
0134 };
0135 
0136 template <typename ObjType, typename TIn, typename ValType = TIn>
0137 class ValueMapVariableBase : public ExtVariable<ObjType> {
0138 public:
0139   ValueMapVariableBase(const std::string &aname,
0140                        const edm::ParameterSet &cfg,
0141                        edm::ConsumesCollector &&cc,
0142                        bool skipNonExistingSrc = false)
0143       : ExtVariable<ObjType>(aname, cfg),
0144         skipNonExistingSrc_(skipNonExistingSrc),
0145         token_(cc.consumes<edm::ValueMap<TIn>>(cfg.getParameter<edm::InputTag>("src"))) {}
0146   virtual ValType eval(const edm::Handle<edm::ValueMap<TIn>> &vmap, const edm::Ptr<ObjType> &op) const = 0;
0147   void fill(const edm::Event &iEvent, std::vector<edm::Ptr<ObjType>> selptrs, nanoaod::FlatTable &out) const override {
0148     edm::Handle<edm::ValueMap<TIn>> vmap;
0149     iEvent.getByToken(token_, vmap);
0150     std::vector<ValType> vals;
0151     if (vmap.isValid() || !skipNonExistingSrc_) {
0152       vals.resize(selptrs.size());
0153       for (unsigned int i = 0, n = vals.size(); i < n; ++i) {
0154         // calls the overloaded method to either get the valuemap value directly, or a function of the object value.
0155         vals[i] = this->eval(vmap, selptrs[i]);
0156       }
0157     }
0158     out.template addColumn<ValType>(this->name_, vals, this->doc_, this->precision_);
0159   }
0160 
0161 protected:
0162   const bool skipNonExistingSrc_;
0163   edm::EDGetTokenT<edm::ValueMap<TIn>> token_;
0164 };
0165 
0166 template <typename ObjType, typename TIn, typename ValType = TIn>
0167 class ValueMapVariable : public ValueMapVariableBase<ObjType, TIn, ValType> {
0168 public:
0169   ValueMapVariable(const std::string &aname,
0170                    const edm::ParameterSet &cfg,
0171                    edm::ConsumesCollector &&cc,
0172                    bool skipNonExistingSrc = false)
0173       : ValueMapVariableBase<ObjType, TIn, ValType>(aname, cfg, std::move(cc), skipNonExistingSrc) {}
0174   ValType eval(const edm::Handle<edm::ValueMap<TIn>> &vmap, const edm::Ptr<ObjType> &op) const override {
0175     ValType val = (*vmap)[op];
0176     return val;
0177   }
0178 };
0179 
0180 template <typename ObjType, typename TIn, typename StringFunctor, typename ValType>
0181 class TypedValueMapVariable : public ValueMapVariableBase<ObjType, TIn, ValType> {
0182 public:
0183   TypedValueMapVariable(const std::string &aname,
0184                         const edm::ParameterSet &cfg,
0185                         edm::ConsumesCollector &&cc,
0186                         bool skipNonExistingSrc = false)
0187       : ValueMapVariableBase<ObjType, TIn, ValType>(aname, cfg, std::move(cc), skipNonExistingSrc),
0188         func_(cfg.getParameter<std::string>("expr"), true),
0189         precisionFunc_(cfg.existsAs<std::string>("precision") ? cfg.getParameter<std::string>("precision") : "23",
0190                        true) {}
0191 
0192   ValType eval(const edm::Handle<edm::ValueMap<TIn>> &vmap, const edm::Ptr<ObjType> &op) const override {
0193     ValType val = func_((*vmap)[op]);
0194     if constexpr (std::is_same<ValType, float>()) {
0195       if (this->precision_ == -2) {
0196         auto prec = precisionFunc_(*op);
0197         if (prec > 0) {
0198           val = MiniFloatConverter::reduceMantissaToNbitsRounding(val, prec);
0199         }
0200       }
0201     }
0202     return val;
0203   }
0204 
0205 protected:
0206   StringFunctor func_;
0207   StringObjectFunction<ObjType> precisionFunc_;
0208 };
0209 
0210 // Event producers
0211 // - ABC
0212 // - Singleton
0213 // - Collection
0214 template <typename T, typename TProd>
0215 class SimpleFlatTableProducerBase : public edm::stream::EDProducer<> {
0216 public:
0217   SimpleFlatTableProducerBase(edm::ParameterSet const &params)
0218       : name_(params.getParameter<std::string>("name")),
0219         doc_(params.getParameter<std::string>("doc")),
0220         extension_(params.getParameter<bool>("extension")),
0221         skipNonExistingSrc_(params.getParameter<bool>("skipNonExistingSrc")),
0222         src_(consumes<TProd>(params.getParameter<edm::InputTag>("src"))) {
0223     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
0224     for (const std::string &vname : varsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0225       const auto &varPSet = varsPSet.getParameter<edm::ParameterSet>(vname);
0226       const std::string &type = varPSet.getParameter<std::string>("type");
0227       if (type == "int")
0228         vars_.push_back(std::make_unique<IntVar>(vname, varPSet));
0229       else if (type == "uint")
0230         vars_.push_back(std::make_unique<UIntVar>(vname, varPSet));
0231       else if (type == "int64")
0232         vars_.push_back(std::make_unique<Int64Var>(vname, varPSet));
0233       else if (type == "uint64")
0234         vars_.push_back(std::make_unique<UInt64Var>(vname, varPSet));
0235       else if (type == "float")
0236         vars_.push_back(std::make_unique<FloatVar>(vname, varPSet));
0237       else if (type == "double")
0238         vars_.push_back(std::make_unique<DoubleVar>(vname, varPSet));
0239       else if (type == "uint8")
0240         vars_.push_back(std::make_unique<UInt8Var>(vname, varPSet));
0241       else if (type == "int16")
0242         vars_.push_back(std::make_unique<Int16Var>(vname, varPSet));
0243       else if (type == "uint16")
0244         vars_.push_back(std::make_unique<UInt16Var>(vname, varPSet));
0245       else if (type == "bool")
0246         vars_.push_back(std::make_unique<BoolVar>(vname, varPSet));
0247       else
0248         throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0249     }
0250 
0251     produces<nanoaod::FlatTable>();
0252   }
0253 
0254   ~SimpleFlatTableProducerBase() override {}
0255 
0256   static edm::ParameterSetDescription baseDescriptions() {
0257     edm::ParameterSetDescription desc;
0258     std::string classname = ClassName<T>::name();
0259     desc.add<std::string>("name")->setComment("name of the branch in the flat table output for " + classname);
0260     desc.add<std::string>("doc", "")->setComment("few words of self documentation");
0261     desc.add<bool>("extension", false)->setComment("whether or not to extend an existing same table");
0262     desc.add<bool>("skipNonExistingSrc", false)
0263         ->setComment("whether or not to skip producing the table on absent input product");
0264     desc.add<edm::InputTag>("src")->setComment("input collection to fill the flat table");
0265 
0266     edm::ParameterSetDescription variable;
0267     variable.add<std::string>("expr")->setComment("a function to define the content of the branch in the flat table");
0268     variable.add<std::string>("doc")->setComment("few words description of the branch content");
0269     variable.addUntracked<bool>("lazyEval", false)
0270         ->setComment("if true, can use methods of inheriting classes in `expr`. Can cause problems with threading.");
0271     variable.ifValue(edm::ParameterDescription<std::string>(
0272                          "type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
0273                      edm::allowedValues<std::string>(
0274                          "int", "uint", "int64", "uint64", "float", "double", "uint8", "int16", "uint16", "bool"));
0275     variable.addOptionalNode(
0276         edm::ParameterDescription<int>(
0277             "precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
0278             edm::ParameterDescription<std::string>(
0279                 "precision", true, edm::Comment("the precision with which to store the value in the flat table")),
0280         false);
0281 
0282     edm::ParameterSetDescription variables;
0283     variables.setComment("a parameters set to define all variable to fill the flat table");
0284     variables.addNode(
0285         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, variable));
0286     desc.add<edm::ParameterSetDescription>("variables", variables);
0287 
0288     return desc;
0289   }
0290   // this is to be overriden by the child class
0291   virtual std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0292                                                         const edm::Handle<TProd> &prod) const = 0;
0293 
0294   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
0295     edm::Handle<TProd> src;
0296     iEvent.getByToken(src_, src);
0297 
0298     std::unique_ptr<nanoaod::FlatTable> out = fillTable(iEvent, src);
0299     out->setDoc(doc_);
0300 
0301     iEvent.put(std::move(out));
0302   }
0303 
0304 protected:
0305   const std::string name_;
0306   const std::string doc_;
0307   const bool extension_;
0308   const bool skipNonExistingSrc_;
0309   const edm::EDGetTokenT<TProd> src_;
0310 
0311   typedef FuncVariable<T, StringObjectFunction<T>, int32_t> IntVar;
0312   typedef FuncVariable<T, StringObjectFunction<T>, uint32_t> UIntVar;
0313   typedef FuncVariable<T, StringObjectFunction<T>, int64_t> Int64Var;
0314   typedef FuncVariable<T, StringObjectFunction<T>, uint64_t> UInt64Var;
0315   typedef FuncVariable<T, StringObjectFunction<T>, float> FloatVar;
0316   typedef FuncVariable<T, StringObjectFunction<T>, double> DoubleVar;
0317   typedef FuncVariable<T, StringObjectFunction<T>, uint8_t> UInt8Var;
0318   typedef FuncVariable<T, StringObjectFunction<T>, int16_t> Int16Var;
0319   typedef FuncVariable<T, StringObjectFunction<T>, uint16_t> UInt16Var;
0320   typedef FuncVariable<T, StringCutObjectSelector<T>, bool> BoolVar;
0321   std::vector<std::unique_ptr<Variable<T>>> vars_;
0322 };
0323 
0324 template <typename T>
0325 class SimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, edm::View<T>> {
0326 public:
0327   SimpleFlatTableProducer(edm::ParameterSet const &params)
0328       : SimpleFlatTableProducerBase<T, edm::View<T>>(params),
0329         singleton_(params.getParameter<bool>("singleton")),
0330         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
0331                                                         : std::numeric_limits<unsigned int>::max()),
0332         cut_(!singleton_ ? params.getParameter<std::string>("cut") : "",
0333              !singleton_ ? params.getUntrackedParameter<bool>("lazyEval") : false) {
0334     if (params.existsAs<edm::ParameterSet>("externalVariables")) {
0335       edm::ParameterSet const &extvarsPSet = params.getParameter<edm::ParameterSet>("externalVariables");
0336       for (const std::string &vname : extvarsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0337         const auto &varPSet = extvarsPSet.getParameter<edm::ParameterSet>(vname);
0338         const std::string &type = varPSet.getParameter<std::string>("type");
0339         if (type == "int")
0340           extvars_.push_back(
0341               std::make_unique<IntExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0342         else if (type == "uint")
0343           extvars_.push_back(
0344               std::make_unique<UIntExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0345         else if (type == "int64")
0346           extvars_.push_back(
0347               std::make_unique<Int64ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0348         else if (type == "uint64")
0349           extvars_.push_back(
0350               std::make_unique<UInt64ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0351         else if (type == "float")
0352           extvars_.push_back(
0353               std::make_unique<FloatExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0354         else if (type == "double")
0355           extvars_.push_back(
0356               std::make_unique<DoubleExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0357         else if (type == "uint8")
0358           extvars_.push_back(
0359               std::make_unique<UInt8ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0360         else if (type == "int16")
0361           extvars_.push_back(
0362               std::make_unique<Int16ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0363         else if (type == "uint16")
0364           extvars_.push_back(
0365               std::make_unique<UInt16ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0366         else if (type == "bool")
0367           extvars_.push_back(
0368               std::make_unique<BoolExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0369         else
0370           throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0371       }
0372     }
0373   }
0374 
0375   ~SimpleFlatTableProducer() override {}
0376 
0377   static edm::ParameterSetDescription baseDescriptions() {
0378     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, edm::View<T>>::baseDescriptions();
0379 
0380     desc.ifValue(
0381         edm::ParameterDescription<bool>(
0382             "singleton", false, true, edm::Comment("whether or not the input collection is single-element")),
0383         false >> (edm::ParameterDescription<std::string>(
0384                       "cut", "", true, edm::Comment("selection on the main input collection")) and
0385                   edm::ParameterDescription<bool>("lazyEval",
0386                                                   false,
0387                                                   false,
0388                                                   edm::Comment("if true, can use methods of inheriting classes. Can "
0389                                                                "cause problems when multi-threading."))) or
0390             true >> edm::EmptyGroupDescription());
0391     desc.addOptional<unsigned int>("maxLen")->setComment(
0392         "define the maximum length of the input collection to put in the branch");
0393 
0394     edm::ParameterSetDescription extvariable;
0395     extvariable.add<edm::InputTag>("src")->setComment("valuemap input collection to fill the flat table");
0396     extvariable.add<std::string>("doc")->setComment("few words description of the branch content");
0397     extvariable.ifValue(edm::ParameterDescription<std::string>(
0398                             "type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
0399                         edm::allowedValues<std::string>(
0400                             "int", "uint", "int64", "uint64", "float", "double", "uint8", "int16", "uint16", "bool"));
0401     extvariable.addOptionalNode(
0402         edm::ParameterDescription<int>(
0403             "precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
0404             edm::ParameterDescription<std::string>("precision",
0405                                                    true,
0406                                                    edm::Comment("the precision with which to store the value in the "
0407                                                                 "flat table, as a function of the object evaluated")),
0408         false);
0409 
0410     edm::ParameterSetDescription extvariables;
0411     extvariables.setComment("a parameters set to define all variable taken form valuemap to fill the flat table");
0412     extvariables.addOptionalNode(
0413         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, extvariable), false);
0414     desc.addOptional<edm::ParameterSetDescription>("externalVariables", extvariables);
0415 
0416     return desc;
0417   }
0418   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0419     edm::ParameterSetDescription desc = SimpleFlatTableProducer<T>::baseDescriptions();
0420     descriptions.addWithDefaultLabel(desc);
0421   }
0422   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0423                                                 const edm::Handle<edm::View<T>> &prod) const override {
0424     std::vector<const T *> selobjs;
0425     std::vector<edm::Ptr<T>> selptrs;  // for external variables
0426     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0427       if (singleton_) {
0428         assert(prod->size() == 1);
0429         selobjs.push_back(&(*prod)[0]);
0430         if (!extvars_.empty() || !typedextvars_.empty())
0431           selptrs.emplace_back(prod->ptrAt(0));
0432       } else {
0433         for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0434           const auto &obj = (*prod)[i];
0435           if (cut_(obj)) {
0436             selobjs.push_back(&obj);
0437             if (!extvars_.empty() || !typedextvars_.empty())
0438               selptrs.emplace_back(prod->ptrAt(i));
0439           }
0440           if (selobjs.size() >= maxLen_)
0441             break;
0442         }
0443       }
0444     }
0445     auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, singleton_, this->extension_);
0446     for (const auto &var : this->vars_)
0447       var->fill(selobjs, *out);
0448     for (const auto &var : this->extvars_)
0449       var->fill(iEvent, selptrs, *out);
0450     for (const auto &var : this->typedextvars_)
0451       var->fill(iEvent, selptrs, *out);
0452     return out;
0453   }
0454 
0455 protected:
0456   bool singleton_;
0457   const unsigned int maxLen_;
0458   const StringCutObjectSelector<T> cut_;
0459 
0460   typedef ValueMapVariable<T, int32_t> IntExtVar;
0461   typedef ValueMapVariable<T, uint32_t> UIntExtVar;
0462   typedef ValueMapVariable<T, int64_t> Int64ExtVar;
0463   typedef ValueMapVariable<T, uint64_t> UInt64ExtVar;
0464   typedef ValueMapVariable<T, float> FloatExtVar;
0465   typedef ValueMapVariable<T, double, float> DoubleExtVar;
0466   typedef ValueMapVariable<T, bool> BoolExtVar;
0467   typedef ValueMapVariable<T, int, uint8_t> UInt8ExtVar;
0468   typedef ValueMapVariable<T, int, int16_t> Int16ExtVar;
0469   typedef ValueMapVariable<T, int, uint16_t> UInt16ExtVar;
0470   std::vector<std::unique_ptr<ExtVariable<T>>> extvars_;
0471   std::vector<std::unique_ptr<ExtVariable<T>>> typedextvars_;
0472 };
0473 
0474 template <typename T, typename V>
0475 class SimpleTypedExternalFlatTableProducer : public SimpleFlatTableProducer<T> {
0476 public:
0477   SimpleTypedExternalFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducer<T>(params) {
0478     edm::ParameterSet const &extvarsPSet = params.getParameter<edm::ParameterSet>("externalTypedVariables");
0479     for (const std::string &vname : extvarsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0480       const auto &varPSet = extvarsPSet.getParameter<edm::ParameterSet>(vname);
0481       const std::string &type = varPSet.getParameter<std::string>("type");
0482       if (type == "int")
0483         this->typedextvars_.push_back(
0484             std::make_unique<IntTypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0485       else if (type == "uint")
0486         this->typedextvars_.push_back(
0487             std::make_unique<UIntTypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0488       else if (type == "int64")
0489         this->typedextvars_.push_back(
0490             std::make_unique<Int64TypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0491       else if (type == "uint64")
0492         this->typedextvars_.push_back(
0493             std::make_unique<UInt64TypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0494       else if (type == "float")
0495         this->typedextvars_.push_back(
0496             std::make_unique<FloatTypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0497       else if (type == "double")
0498         this->typedextvars_.push_back(
0499             std::make_unique<DoubleTypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0500       else if (type == "uint8")
0501         this->typedextvars_.push_back(
0502             std::make_unique<UInt8TypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0503       else if (type == "int16")
0504         this->typedextvars_.push_back(
0505             std::make_unique<Int16TypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0506       else if (type == "uint16")
0507         this->typedextvars_.push_back(
0508             std::make_unique<UInt16TypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0509       else if (type == "bool")
0510         this->typedextvars_.push_back(
0511             std::make_unique<BoolTypedExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0512       else
0513         throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0514     }
0515   }
0516   ~SimpleTypedExternalFlatTableProducer() override {}
0517   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0518     edm::ParameterSetDescription desc = SimpleFlatTableProducer<T>::baseDescriptions();
0519     edm::ParameterSetDescription extvariable;
0520     extvariable.add<edm::InputTag>("src")->setComment("valuemap input collection to fill the flat table");
0521     extvariable.add<std::string>("expr")->setComment(
0522         "a function to define the content of the branch in the flat table");
0523     extvariable.add<std::string>("doc")->setComment("few words description of the branch content");
0524     extvariable.addUntracked<bool>("lazyEval", false)
0525         ->setComment("if true, can use methods of inheriting classes in `expr`. Can cause problems with threading.");
0526     extvariable.ifValue(
0527         edm::ParameterDescription<std::string>(
0528             "type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
0529         edm::allowedValues<std::string>("int", "uint", "float", "double", "uint8", "int16", "uint16", "bool"));
0530     extvariable.addOptionalNode(
0531         edm::ParameterDescription<int>(
0532             "precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
0533             edm::ParameterDescription<std::string>("precision",
0534                                                    true,
0535                                                    edm::Comment("the precision with which to store the value in the "
0536                                                                 "flat table, as a function of the object evaluated")),
0537         false);
0538 
0539     edm::ParameterSetDescription extvariables;
0540     extvariables.setComment("a parameters set to define all variable taken form valuemap to fill the flat table");
0541     extvariables.addOptionalNode(
0542         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, extvariable), false);
0543     desc.addOptional<edm::ParameterSetDescription>("externalTypedVariables", extvariables);
0544 
0545     descriptions.addWithDefaultLabel(desc);
0546   }
0547 
0548 protected:
0549   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, int32_t> IntTypedExtVar;
0550   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, uint32_t> UIntTypedExtVar;
0551   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, int64_t> Int64TypedExtVar;
0552   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, uint64_t> UInt64TypedExtVar;
0553   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, float> FloatTypedExtVar;
0554   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, double> DoubleTypedExtVar;
0555   typedef TypedValueMapVariable<T, V, StringCutObjectSelector<V>, bool> BoolTypedExtVar;
0556   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, uint8_t> UInt8TypedExtVar;
0557   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, int16_t> Int16TypedExtVar;
0558   typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, uint16_t> UInt16TypedExtVar;
0559 };
0560 
0561 template <typename T>
0562 class SimpleCollectionFlatTableProducer : public SimpleFlatTableProducer<T> {
0563 public:
0564   SimpleCollectionFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducer<T>(params) {
0565     if (params.existsAs<edm::ParameterSet>("collectionVariables")) {
0566       edm::ParameterSet const &collectionVarsPSet = params.getParameter<edm::ParameterSet>("collectionVariables");
0567       for (const std::string &coltablename :
0568            collectionVarsPSet.getParameterNamesForType<edm::ParameterSet>()) {  // tables of variables
0569         const auto &coltablePSet = collectionVarsPSet.getParameter<edm::ParameterSet>(coltablename);
0570         CollectionVariableTableInfo coltable;
0571         coltable.name =
0572             coltablePSet.existsAs<std::string>("name") ? coltablePSet.getParameter<std::string>("name") : coltablename;
0573         coltable.doc = coltablePSet.getParameter<std::string>("doc");
0574         coltable.useCount = coltablePSet.getParameter<bool>("useCount");
0575         coltable.useOffset = coltablePSet.getParameter<bool>("useOffset");
0576         const auto &colvarsPSet = coltablePSet.getParameter<edm::ParameterSet>("variables");
0577         for (const std::string &colvarname : colvarsPSet.getParameterNamesForType<edm::ParameterSet>()) {  // variables
0578           const auto &colvarPSet = colvarsPSet.getParameter<edm::ParameterSet>(colvarname);
0579           const std::string &type = colvarPSet.getParameter<std::string>("type");
0580           if (type == "int")
0581             coltable.colvars.push_back(std::make_unique<IntVectorVar>(colvarname, colvarPSet));
0582           else if (type == "uint")
0583             coltable.colvars.push_back(std::make_unique<UIntVectorVar>(colvarname, colvarPSet));
0584           else if (type == "int64")
0585             coltable.colvars.push_back(std::make_unique<Int64VectorVar>(colvarname, colvarPSet));
0586           else if (type == "uint64")
0587             coltable.colvars.push_back(std::make_unique<UInt64VectorVar>(colvarname, colvarPSet));
0588           else if (type == "float")
0589             coltable.colvars.push_back(std::make_unique<FloatVectorVar>(colvarname, colvarPSet));
0590           else if (type == "double")
0591             coltable.colvars.push_back(std::make_unique<DoubleVectorVar>(colvarname, colvarPSet));
0592           else if (type == "uint8")
0593             coltable.colvars.push_back(std::make_unique<UInt8VectorVar>(colvarname, colvarPSet));
0594           else if (type == "int16")
0595             coltable.colvars.push_back(std::make_unique<Int16VectorVar>(colvarname, colvarPSet));
0596           else if (type == "uint16")
0597             coltable.colvars.push_back(std::make_unique<UInt16VectorVar>(colvarname, colvarPSet));
0598           else
0599             throw cms::Exception("Configuration",
0600                                  "unsupported type " + type + " for variable " + colvarname + " in " + coltablename);
0601         }
0602         this->coltables.push_back(std::move(coltable));
0603         edm::stream::EDProducer<>::produces<nanoaod::FlatTable>(coltables.back().name + "Table");
0604       }
0605     }
0606   }
0607 
0608   ~SimpleCollectionFlatTableProducer() override {}
0609 
0610   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0611     edm::ParameterSetDescription desc = SimpleFlatTableProducer<T>::baseDescriptions();
0612     edm::ParameterSetDescription colvariable;
0613     colvariable.add<std::string>("expr")->setComment(
0614         "a function to define the content of the branch in the flat table");
0615     colvariable.add<std::string>("doc")->setComment("few words of self documentation");
0616     colvariable.addUntracked<bool>("lazyEval", false)
0617         ->setComment("if true, can use methods of inheriting classes in `expr`. Can cause problems with threading.");
0618     colvariable.ifValue(edm::ParameterDescription<std::string>(
0619                             "type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
0620                         edm::allowedValues<std::string>("int", "uint", "float", "double", "uint8", "int16", "uint16"));
0621     colvariable.addOptionalNode(
0622         edm::ParameterDescription<int>(
0623             "precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
0624             edm::ParameterDescription<std::string>(
0625                 "precision", true, edm::Comment("the precision with which to store the value in the flat table")),
0626         false);
0627     edm::ParameterSetDescription colvariables;
0628     colvariables.setComment("a parameters set to define all variable to fill the flat table");
0629     colvariables.addNode(
0630         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireAtLeastOne, true, colvariable));
0631 
0632     edm::ParameterSetDescription coltable;
0633     coltable.addOptional<std::string>("name")->setComment(
0634         "name of the branch in the flat table containing flatten collections of variables");
0635     coltable.add<std::string>("doc")->setComment(
0636         "few words description of the table containing flatten collections of variables");
0637     coltable.add<bool>("useCount", true)
0638         ->setComment("whether to use count for the main table to index table with flatten collections of variables");
0639     coltable.add<bool>("useOffset", false)
0640         ->setComment("whether to use offset for the main table to index table with flatten collections of variables");
0641     coltable.add<edm::ParameterSetDescription>("variables", colvariables);
0642 
0643     edm::ParameterSetDescription coltables;
0644     coltables.setComment("a parameters set to define variables to be flatten to fill the table");
0645     coltables.addOptionalNode(
0646         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, coltable), false);
0647     desc.addOptional<edm::ParameterSetDescription>("collectionVariables", coltables);
0648 
0649     descriptions.addWithDefaultLabel(desc);
0650   }
0651 
0652   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
0653     // same as SimpleFlatTableProducer
0654     edm::Handle<edm::View<T>> prod;
0655     iEvent.getByToken(this->src_, prod);
0656 
0657     std::vector<const T *> selobjs;
0658     std::vector<edm::Ptr<T>> selptrs;  // for external variables
0659     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0660       if (this->singleton_) {
0661         assert(prod->size() == 1);
0662         selobjs.push_back(&(*prod)[0]);
0663         if (!this->extvars_.empty() || !this->typedextvars_.empty())
0664           selptrs.emplace_back(prod->ptrAt(0));
0665       } else {
0666         for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0667           const auto &obj = (*prod)[i];
0668           if (this->cut_(obj)) {
0669             selobjs.push_back(&obj);
0670             if (!this->extvars_.empty() || !this->typedextvars_.empty())
0671               selptrs.emplace_back(prod->ptrAt(i));
0672           }
0673           if (selobjs.size() >= this->maxLen_)
0674             break;
0675         }
0676       }
0677     }
0678 
0679     auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, this->singleton_, this->extension_);
0680     for (const auto &var : this->vars_)
0681       var->fill(selobjs, *out);
0682     for (const auto &var : this->extvars_)
0683       var->fill(iEvent, selptrs, *out);
0684     for (const auto &var : this->typedextvars_)
0685       var->fill(iEvent, selptrs, *out);
0686 
0687     // collection variable tables
0688     for (const auto &coltable : this->coltables) {
0689       std::unique_ptr<std::vector<unsigned int>> counts = coltable.colvars[0]->getCounts(selobjs);
0690       // compute size
0691       unsigned int coltablesize = 0;
0692       for (auto const &count : *counts)
0693         coltablesize += count;
0694       // add count branch if requested
0695       if (coltable.useCount)
0696         out->template addColumn<uint16_t>("n" + coltable.name, *counts, "counts for " + coltable.name);
0697       // add offset branch if requested
0698       if (coltable.useOffset) {
0699         unsigned int offset = 0;
0700         std::vector<unsigned int> offsets;
0701         for (auto const &count : *counts) {
0702           offsets.push_back(offset);
0703           offset += count;
0704         }
0705         out->template addColumn<uint16_t>("o" + coltable.name, offsets, "offsets for " + coltable.name);
0706       }
0707 
0708       std::unique_ptr<nanoaod::FlatTable> outcoltable =
0709           std::make_unique<nanoaod::FlatTable>(coltablesize, coltable.name, false, false);
0710       for (const auto &colvar : coltable.colvars) {
0711         colvar->fill(selobjs, *outcoltable);
0712       }
0713       outcoltable->setDoc(coltable.doc);
0714       iEvent.put(std::move(outcoltable), coltable.name + "Table");
0715     }
0716 
0717     // put the main table into the event
0718     out->setDoc(this->doc_);
0719     iEvent.put(std::move(out));
0720   }
0721 
0722 protected:
0723   template <typename R>
0724   using VectorVar =
0725       FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<R>>, StringObjectFunction<T>, R>;
0726 
0727   using IntVectorVar = VectorVar<int32_t>;
0728   using UIntVectorVar = VectorVar<uint32_t>;
0729   using Int64VectorVar = VectorVar<int64_t>;
0730   using UInt64VectorVar = VectorVar<uint64_t>;
0731   using FloatVectorVar = VectorVar<float>;
0732   using DoubleVectorVar = VectorVar<double>;
0733   using UInt8VectorVar = VectorVar<uint8_t>;
0734   using Int16VectorVar = VectorVar<int16_t>;
0735   using UInt16VectorVar = VectorVar<uint16_t>;
0736 
0737   struct CollectionVariableTableInfo {
0738     std::string name;
0739     std::string doc;
0740     bool useCount;
0741     bool useOffset;
0742     std::vector<std::unique_ptr<CollectionVariable<T>>> colvars;
0743   };
0744   std::vector<CollectionVariableTableInfo> coltables;
0745 };
0746 
0747 template <typename T>
0748 class BXVectorSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, BXVector<T>> {
0749 public:
0750   BXVectorSimpleFlatTableProducer(edm::ParameterSet const &params)
0751       : SimpleFlatTableProducerBase<T, BXVector<T>>(params),
0752         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
0753                                                         : std::numeric_limits<unsigned int>::max()),
0754         cut_(params.getParameter<std::string>("cut"), false),
0755         minBX_(params.getParameter<int>("minBX")),
0756         maxBX_(params.getParameter<int>("maxBX")),
0757         alwaysWriteBXValue_(params.getParameter<bool>("alwaysWriteBXValue")),
0758         bxVarName_("bx") {
0759     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
0760     auto varNames = varsPSet.getParameterNamesForType<edm::ParameterSet>();
0761     if (std::find(varNames.begin(), varNames.end(), bxVarName_) != varNames.end()) {
0762       throw cms::Exception("Configuration",
0763                            "BXVectorSimpleFlatTableProducer already defines the " + bxVarName_ +
0764                                "internally and thus you should not specify it yourself");
0765     }
0766   }
0767 
0768   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0769     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, BXVector<T>>::baseDescriptions();
0770     desc.add<std::string>("cut", "")->setComment(
0771         "selection on the main input collection (but selection can not be bx based)");
0772     desc.addOptional<unsigned int>("maxLen")->setComment(
0773         "define the maximum length of the input collection to put in the branch");
0774     desc.add<int>("minBX", -2)->setComment("min bx (inclusive) to include");
0775     desc.add<int>("maxBX", 2)->setComment("max bx (inclusive) to include");
0776     desc.add<bool>("alwaysWriteBXValue", true)
0777         ->setComment("always write the bx number (event  when only one bx can be present, ie minBX==maxBX)");
0778     descriptions.addWithDefaultLabel(desc);
0779   }
0780 
0781   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0782                                                 const edm::Handle<BXVector<T>> &prod) const override {
0783     std::vector<const T *> selObjs;
0784     std::vector<int> selObjBXs;
0785 
0786     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0787       const int minBX = std::max(minBX_, prod->getFirstBX());
0788       const int maxBX = std::min(maxBX_, prod->getLastBX());
0789       for (int bx = minBX; bx <= maxBX; bx++) {
0790         for (size_t objNr = 0, nrObjs = prod->size(bx); objNr < nrObjs; ++objNr) {
0791           const auto &obj = prod->at(bx, objNr);
0792           if (cut_(obj)) {
0793             selObjs.push_back(&obj);
0794             selObjBXs.push_back(bx);
0795           }
0796           if (selObjs.size() >= maxLen_)
0797             break;
0798         }
0799       }
0800     }
0801     auto out = std::make_unique<nanoaod::FlatTable>(selObjs.size(), this->name_, false, this->extension_);
0802     for (const auto &var : this->vars_)
0803       var->fill(selObjs, *out);
0804     if (alwaysWriteBXValue_ || minBX_ != maxBX_) {
0805       out->template addColumn<int16_t>(bxVarName_, selObjBXs, "BX of the L1 candidate");
0806     }
0807     return out;
0808   }
0809 
0810 protected:
0811   const unsigned int maxLen_;
0812   const StringCutObjectSelector<T> cut_;
0813   const int minBX_;
0814   const int maxBX_;
0815   const bool alwaysWriteBXValue_;
0816   const std::string bxVarName_;
0817 };
0818 
0819 template <typename T>
0820 class EventSingletonSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, T> {
0821 public:
0822   EventSingletonSimpleFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducerBase<T, T>(params) {}
0823 
0824   ~EventSingletonSimpleFlatTableProducer() override {}
0825 
0826   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0827     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, T>::baseDescriptions();
0828     descriptions.addWithDefaultLabel(desc);
0829   }
0830 
0831   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &, const edm::Handle<T> &prod) const override {
0832     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
0833     std::vector<const T *> selobjs(1, prod.product());
0834     for (const auto &var : this->vars_)
0835       var->fill(selobjs, *out);
0836     return out;
0837   }
0838 };
0839 
0840 template <typename T>
0841 class FirstObjectSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, edm::View<T>> {
0842 public:
0843   FirstObjectSimpleFlatTableProducer(edm::ParameterSet const &params)
0844       : SimpleFlatTableProducerBase<T, edm::View<T>>(params) {}
0845 
0846   ~FirstObjectSimpleFlatTableProducer() override {}
0847 
0848   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0849     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, edm::View<T>>::baseDescriptions();
0850     descriptions.addWithDefaultLabel(desc);
0851   }
0852 
0853   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0854                                                 const edm::Handle<edm::View<T>> &prod) const override {
0855     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
0856     std::vector<const T *> selobjs(1, &(*prod)[0]);
0857     for (const auto &var : this->vars_)
0858       var->fill(selobjs, *out);
0859     return out;
0860   }
0861 };
0862 
0863 // LuminosityBlock producers
0864 // - ABC
0865 // - Singleton
0866 // - Collection
0867 template <typename T, typename TProd>
0868 class SimpleFlatTableProducerBaseLumi
0869     : public edm::one::EDProducer<edm::EndLuminosityBlockProducer, edm::LuminosityBlockCache<int>> {
0870 public:
0871   SimpleFlatTableProducerBaseLumi(edm::ParameterSet const &params)
0872       : name_(params.getParameter<std::string>("name")),
0873         doc_(params.existsAs<std::string>("doc") ? params.getParameter<std::string>("doc") : ""),
0874         extension_(params.existsAs<bool>("extension") ? params.getParameter<bool>("extension") : false),
0875         skipNonExistingSrc_(
0876 
0877             params.existsAs<bool>("skipNonExistingSrc") ? params.getParameter<bool>("skipNonExistingSrc") : false),
0878         src_(consumes<TProd, edm::InLumi>(params.getParameter<edm::InputTag>("src"))) {
0879     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
0880     for (const std::string &vname : varsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0881       const auto &varPSet = varsPSet.getParameter<edm::ParameterSet>(vname);
0882       const std::string &type = varPSet.getParameter<std::string>("type");
0883       if (type == "int")
0884         vars_.push_back(std::make_unique<IntVar>(vname, varPSet));
0885       else if (type == "float")
0886         vars_.push_back(std::make_unique<FloatVar>(vname, varPSet));
0887       else if (type == "uint8")
0888         vars_.push_back(std::make_unique<UInt8Var>(vname, varPSet));
0889       else if (type == "bool")
0890         vars_.push_back(std::make_unique<BoolVar>(vname, varPSet));
0891       else
0892         throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0893     }
0894 
0895     produces<nanoaod::FlatTable, edm::Transition::EndLuminosityBlock>();
0896   }
0897 
0898   ~SimpleFlatTableProducerBaseLumi() override {}
0899 
0900   std::shared_ptr<int> globalBeginLuminosityBlock(edm::LuminosityBlock const &,
0901                                                   edm::EventSetup const &) const override {
0902     return nullptr;
0903   }
0904 
0905   void globalEndLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) override {}
0906 
0907   // this is to be overriden by the child class
0908   virtual std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::LuminosityBlock &iLumi,
0909                                                         const edm::Handle<TProd> &prod) const = 0;
0910 
0911   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
0912     // do nothing
0913   }
0914 
0915   void endLuminosityBlockProduce(edm::LuminosityBlock &iLumi, const edm::EventSetup &iSetup) final {
0916     edm::Handle<TProd> src;
0917     iLumi.getByToken(src_, src);
0918 
0919     std::unique_ptr<nanoaod::FlatTable> out = fillTable(iLumi, src);
0920     out->setDoc(doc_);
0921 
0922     iLumi.put(std::move(out));
0923   }
0924 
0925 protected:
0926   const std::string name_;
0927   const std::string doc_;
0928   const bool extension_;
0929   const bool skipNonExistingSrc_;
0930   const edm::EDGetTokenT<TProd> src_;
0931 
0932   typedef FuncVariable<T, StringObjectFunction<T>, int> IntVar;
0933   typedef FuncVariable<T, StringObjectFunction<T>, float> FloatVar;
0934   typedef FuncVariable<T, StringObjectFunction<T>, uint8_t> UInt8Var;
0935   typedef FuncVariable<T, StringCutObjectSelector<T>, bool> BoolVar;
0936   std::vector<std::unique_ptr<Variable<T>>> vars_;
0937 };
0938 
0939 // Class for singletons like GenFilterInfo
0940 template <typename T>
0941 class LumiSingletonSimpleFlatTableProducer : public SimpleFlatTableProducerBaseLumi<T, T> {
0942 public:
0943   LumiSingletonSimpleFlatTableProducer(edm::ParameterSet const &params)
0944       : SimpleFlatTableProducerBaseLumi<T, T>(params) {}
0945 
0946   ~LumiSingletonSimpleFlatTableProducer() override {}
0947 
0948   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0949     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, T>::baseDescriptions();
0950     descriptions.addWithDefaultLabel(desc);
0951   }
0952 
0953   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::LuminosityBlock &,
0954                                                 const edm::Handle<T> &prod) const override {
0955     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
0956     std::vector<const T *> selobjs(1, prod.product());
0957     for (const auto &var : this->vars_)
0958       var->fill(selobjs, *out);
0959     return out;
0960   }
0961 };
0962 
0963 // Class for generic collections
0964 template <typename T, typename TProd>
0965 class LumiSimpleFlatTableProducer : public SimpleFlatTableProducerBaseLumi<T, TProd> {
0966 public:
0967   LumiSimpleFlatTableProducer(edm::ParameterSet const &params)
0968       : SimpleFlatTableProducerBaseLumi<T, TProd>(params),
0969         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
0970                                                         : std::numeric_limits<unsigned int>::max()),
0971         cut_(params.existsAs<std::string>("cut") ? params.getParameter<std::string>("cut") : "", true) {}
0972 
0973   ~LumiSimpleFlatTableProducer() override {}
0974 
0975   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0976     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, TProd>::baseDescriptions();
0977     desc.addOptional<unsigned int>("maxLen")->setComment(
0978         "define the maximum length of the input collection to put in the branch");
0979     descriptions.addWithDefaultLabel(desc);
0980   }
0981 
0982   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::LuminosityBlock &iLumi,
0983                                                 const edm::Handle<TProd> &prod) const override {
0984     std::vector<const T *> selobjs;
0985     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0986       for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0987         const auto &obj = (*prod)[i];
0988         if (cut_(obj)) {
0989           selobjs.push_back(&obj);
0990         }
0991         if (selobjs.size() >= maxLen_)
0992           break;
0993       }
0994     }
0995     auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, false, this->extension_);
0996     for (const auto &var : this->vars_)
0997       var->fill(selobjs, *out);
0998     return out;
0999   }
1000 
1001 protected:
1002   const unsigned int maxLen_;
1003   const StringCutObjectSelector<T> cut_;
1004 };
1005 
1006 // Run producers
1007 // - ABC
1008 // - Singleton
1009 // - Collection
1010 template <typename T, typename TProd>
1011 class SimpleFlatTableProducerBaseRun : public edm::one::EDProducer<edm::EndRunProducer, edm::RunCache<int>> {
1012 public:
1013   SimpleFlatTableProducerBaseRun(edm::ParameterSet const &params)
1014       : name_(params.getParameter<std::string>("name")),
1015         doc_(params.existsAs<std::string>("doc") ? params.getParameter<std::string>("doc") : ""),
1016         extension_(params.existsAs<bool>("extension") ? params.getParameter<bool>("extension") : false),
1017         skipNonExistingSrc_(
1018 
1019             params.existsAs<bool>("skipNonExistingSrc") ? params.getParameter<bool>("skipNonExistingSrc") : false),
1020         src_(consumes<TProd, edm::InRun>(params.getParameter<edm::InputTag>("src"))) {
1021     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
1022     for (const std::string &vname : varsPSet.getParameterNamesForType<edm::ParameterSet>()) {
1023       const auto &varPSet = varsPSet.getParameter<edm::ParameterSet>(vname);
1024       const std::string &type = varPSet.getParameter<std::string>("type");
1025       if (type == "int")
1026         vars_.push_back(std::make_unique<IntVar>(vname, varPSet));
1027       else if (type == "float")
1028         vars_.push_back(std::make_unique<FloatVar>(vname, varPSet));
1029       else if (type == "uint8")
1030         vars_.push_back(std::make_unique<UInt8Var>(vname, varPSet));
1031       else if (type == "bool")
1032         vars_.push_back(std::make_unique<BoolVar>(vname, varPSet));
1033       else
1034         throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
1035     }
1036 
1037     produces<nanoaod::FlatTable, edm::Transition::EndRun>();
1038   }
1039 
1040   ~SimpleFlatTableProducerBaseRun() override {}
1041 
1042   std::shared_ptr<int> globalBeginRun(edm::Run const &, edm::EventSetup const &) const override { return nullptr; }
1043 
1044   void globalEndRun(edm::Run const &, edm::EventSetup const &) override {}
1045 
1046   // this is to be overriden by the child class
1047   virtual std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Run &iRun, const edm::Handle<TProd> &prod) const = 0;
1048 
1049   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
1050     // do nothing
1051   }
1052 
1053   void endRunProduce(edm::Run &iRun, const edm::EventSetup &iSetup) final {
1054     edm::Handle<TProd> src;
1055     iRun.getByToken(src_, src);
1056 
1057     std::unique_ptr<nanoaod::FlatTable> out = fillTable(iRun, src);
1058     out->setDoc(doc_);
1059 
1060     iRun.put(std::move(out));
1061   }
1062 
1063 protected:
1064   const std::string name_;
1065   const std::string doc_;
1066   const bool extension_;
1067   const bool skipNonExistingSrc_;
1068   const edm::EDGetTokenT<TProd> src_;
1069 
1070   typedef FuncVariable<T, StringObjectFunction<T>, int> IntVar;
1071   typedef FuncVariable<T, StringObjectFunction<T>, float> FloatVar;
1072   typedef FuncVariable<T, StringObjectFunction<T>, uint8_t> UInt8Var;
1073   typedef FuncVariable<T, StringCutObjectSelector<T>, bool> BoolVar;
1074   std::vector<std::unique_ptr<Variable<T>>> vars_;
1075 };
1076 
1077 // Class for singletons like GenFilterInfo
1078 template <typename T>
1079 class RunSingletonSimpleFlatTableProducer : public SimpleFlatTableProducerBaseRun<T, T> {
1080 public:
1081   RunSingletonSimpleFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducerBaseRun<T, T>(params) {}
1082 
1083   ~RunSingletonSimpleFlatTableProducer() override {}
1084 
1085   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Run &, const edm::Handle<T> &prod) const override {
1086     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
1087     std::vector<const T *> selobjs(1, prod.product());
1088     for (const auto &var : this->vars_)
1089       var->fill(selobjs, *out);
1090     return out;
1091   }
1092 };
1093 
1094 // Class for generic collections
1095 template <typename T, typename TProd>
1096 class RunSimpleFlatTableProducer : public SimpleFlatTableProducerBaseRun<T, TProd> {
1097 public:
1098   RunSimpleFlatTableProducer(edm::ParameterSet const &params)
1099       : SimpleFlatTableProducerBaseRun<T, TProd>(params),
1100         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
1101                                                         : std::numeric_limits<unsigned int>::max()),
1102         cut_(params.existsAs<std::string>("cut") ? params.getParameter<std::string>("cut") : "", true) {}
1103 
1104   ~RunSimpleFlatTableProducer() override {}
1105 
1106   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Run &iRun, const edm::Handle<TProd> &prod) const override {
1107     std::vector<const T *> selobjs;
1108     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
1109       for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
1110         const auto &obj = (*prod)[i];
1111         if (cut_(obj)) {
1112           selobjs.push_back(&obj);
1113         }
1114         if (selobjs.size() >= maxLen_)
1115           break;
1116       }
1117     }
1118     auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, false, this->extension_);
1119     for (const auto &var : this->vars_)
1120       var->fill(selobjs, *out);
1121     return out;
1122   }
1123 
1124 protected:
1125   const unsigned int maxLen_;
1126   const StringCutObjectSelector<T> cut_;
1127 };