Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-04-02 22:48:08

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 
0018 #include <memory>
0019 #include <vector>
0020 
0021 // Base class for dumped variables
0022 class VariableBase {
0023 public:
0024   VariableBase(const std::string &aname, const edm::ParameterSet &cfg)
0025       : name_(aname),
0026         doc_(cfg.getParameter<std::string>("doc")),
0027         precision_(cfg.existsAs<int>("precision") ? cfg.getParameter<int>("precision")
0028                                                   : (cfg.existsAs<std::string>("precision") ? -2 : -1)) {}
0029   virtual ~VariableBase() {}
0030   const std::string &name() const { return name_; }
0031 
0032 protected:
0033   std::string name_, doc_;
0034   int precision_;
0035 };
0036 
0037 // Object member variables and methods
0038 template <typename ObjType>
0039 class Variable : public VariableBase {
0040 public:
0041   Variable(const std::string &aname, const edm::ParameterSet &cfg) : VariableBase(aname, cfg) {}
0042   virtual void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const = 0;
0043 };
0044 
0045 template <typename ObjType, typename StringFunctor, typename ValType>
0046 class FuncVariable : public Variable<ObjType> {
0047 public:
0048   FuncVariable(const std::string &aname, const edm::ParameterSet &cfg)
0049       : Variable<ObjType>(aname, cfg),
0050         func_(cfg.getParameter<std::string>("expr"), true),
0051         precisionFunc_(cfg.existsAs<std::string>("precision") ? cfg.getParameter<std::string>("precision") : "23",
0052                        true) {}
0053   ~FuncVariable() override {}
0054   void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const override {
0055     std::vector<ValType> vals(selobjs.size());
0056     for (unsigned int i = 0, n = vals.size(); i < n; ++i) {
0057       ValType val = func_(*selobjs[i]);
0058       if constexpr (std::is_same<ValType, float>()) {
0059         if (this->precision_ == -2) {
0060           auto prec = precisionFunc_(*selobjs[i]);
0061           vals[i] = prec > 0 ? MiniFloatConverter::reduceMantissaToNbitsRounding(val, prec) : val;
0062         } else
0063           vals[i] = val;
0064       } else {
0065         vals[i] = val;
0066       }
0067     }
0068     out.template addColumn<ValType>(this->name_, vals, this->doc_, this->precision_);
0069   }
0070 
0071 protected:
0072   StringFunctor func_;
0073   StringFunctor precisionFunc_;
0074 };
0075 
0076 // External variables: i.e. variables that are not member or methods of the object
0077 template <typename ObjType>
0078 class ExtVariable : public VariableBase {
0079 public:
0080   ExtVariable(const std::string &aname, const edm::ParameterSet &cfg) : VariableBase(aname, cfg) {}
0081   virtual void fill(const edm::Event &iEvent,
0082                     std::vector<edm::Ptr<ObjType>> selptrs,
0083                     nanoaod::FlatTable &out) const = 0;
0084 };
0085 template <typename ObjType, typename TIn, typename ValType = TIn>
0086 class ValueMapVariable : public ExtVariable<ObjType> {
0087 public:
0088   ValueMapVariable(const std::string &aname,
0089                    const edm::ParameterSet &cfg,
0090                    edm::ConsumesCollector &&cc,
0091                    bool skipNonExistingSrc = false)
0092       : ExtVariable<ObjType>(aname, cfg),
0093         skipNonExistingSrc_(skipNonExistingSrc),
0094         token_(cc.consumes<edm::ValueMap<TIn>>(cfg.getParameter<edm::InputTag>("src"))) {}
0095   void fill(const edm::Event &iEvent, std::vector<edm::Ptr<ObjType>> selptrs, nanoaod::FlatTable &out) const override {
0096     edm::Handle<edm::ValueMap<TIn>> vmap;
0097     iEvent.getByToken(token_, vmap);
0098     std::vector<ValType> vals;
0099     if (vmap.isValid() || !skipNonExistingSrc_) {
0100       vals.resize(selptrs.size());
0101       for (unsigned int i = 0, n = vals.size(); i < n; ++i) {
0102         vals[i] = (*vmap)[selptrs[i]];
0103       }
0104     }
0105     out.template addColumn<ValType>(this->name_, vals, this->doc_, this->precision_);
0106   }
0107 
0108 protected:
0109   const bool skipNonExistingSrc_;
0110   edm::EDGetTokenT<edm::ValueMap<TIn>> token_;
0111 };
0112 
0113 // Event producers
0114 // - ABC
0115 // - Singleton
0116 // - Collection
0117 template <typename T, typename TProd>
0118 class SimpleFlatTableProducerBase : public edm::stream::EDProducer<> {
0119 public:
0120   SimpleFlatTableProducerBase(edm::ParameterSet const &params)
0121       : name_(params.getParameter<std::string>("name")),
0122         doc_(params.getParameter<std::string>("doc")),
0123         extension_(params.getParameter<bool>("extension")),
0124         skipNonExistingSrc_(params.getParameter<bool>("skipNonExistingSrc")),
0125         src_(consumes<TProd>(params.getParameter<edm::InputTag>("src"))) {
0126     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
0127     for (const std::string &vname : varsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0128       const auto &varPSet = varsPSet.getParameter<edm::ParameterSet>(vname);
0129       const std::string &type = varPSet.getParameter<std::string>("type");
0130       if (type == "int")
0131         vars_.push_back(std::make_unique<IntVar>(vname, varPSet));
0132       else if (type == "uint")
0133         vars_.push_back(std::make_unique<UIntVar>(vname, varPSet));
0134       else if (type == "float")
0135         vars_.push_back(std::make_unique<FloatVar>(vname, varPSet));
0136       else if (type == "double")
0137         vars_.push_back(std::make_unique<DoubleVar>(vname, varPSet));
0138       else if (type == "int8")
0139         vars_.push_back(std::make_unique<Int8Var>(vname, varPSet));
0140       else if (type == "uint8")
0141         vars_.push_back(std::make_unique<UInt8Var>(vname, varPSet));
0142       else if (type == "int16")
0143         vars_.push_back(std::make_unique<Int16Var>(vname, varPSet));
0144       else if (type == "uint16")
0145         vars_.push_back(std::make_unique<UInt16Var>(vname, varPSet));
0146       else if (type == "bool")
0147         vars_.push_back(std::make_unique<BoolVar>(vname, varPSet));
0148       else
0149         throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0150     }
0151 
0152     produces<nanoaod::FlatTable>();
0153   }
0154 
0155   ~SimpleFlatTableProducerBase() override {}
0156 
0157   static edm::ParameterSetDescription baseDescriptions() {
0158     edm::ParameterSetDescription desc;
0159     std::string classname = ClassName<T>::name();
0160     desc.add<std::string>("name")->setComment("name of the branch in the flat table output for " + classname);
0161     desc.add<std::string>("doc", "")->setComment("few words of self documentation");
0162     desc.add<bool>("extension", false)->setComment("whether or not to extend an existing same table");
0163     desc.add<bool>("skipNonExistingSrc", false)
0164         ->setComment("whether or not to skip producing the table on absent input product");
0165     desc.add<edm::InputTag>("src")->setComment("input collection to fill the flat table");
0166 
0167     edm::ParameterSetDescription variable;
0168     variable.add<std::string>("expr")->setComment("a function to define the content of the branch in the flat table");
0169     variable.add<std::string>("doc")->setComment("few words description of the branch content");
0170     variable.ifValue(
0171         edm::ParameterDescription<std::string>(
0172             "type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
0173         edm::allowedValues<std::string>("int", "uint", "float", "double", "int8", "uint8", "int16", "uint16", "bool"));
0174     variable.addOptionalNode(
0175         edm::ParameterDescription<int>(
0176             "precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
0177             edm::ParameterDescription<std::string>(
0178                 "precision", true, edm::Comment("the precision with which to store the value in the flat table")),
0179         false);
0180 
0181     edm::ParameterSetDescription variables;
0182     variables.setComment("a parameters set to define all variable to fill the flat table");
0183     variables.addNode(
0184         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, variable));
0185     desc.add<edm::ParameterSetDescription>("variables", variables);
0186 
0187     return desc;
0188   }
0189   // this is to be overriden by the child class
0190   virtual std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0191                                                         const edm::Handle<TProd> &prod) const = 0;
0192 
0193   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
0194     edm::Handle<TProd> src;
0195     iEvent.getByToken(src_, src);
0196 
0197     std::unique_ptr<nanoaod::FlatTable> out = fillTable(iEvent, src);
0198     out->setDoc(doc_);
0199 
0200     iEvent.put(std::move(out));
0201   }
0202 
0203 protected:
0204   const std::string name_;
0205   const std::string doc_;
0206   const bool extension_;
0207   const bool skipNonExistingSrc_;
0208   const edm::EDGetTokenT<TProd> src_;
0209 
0210   typedef FuncVariable<T, StringObjectFunction<T>, int32_t> IntVar;
0211   typedef FuncVariable<T, StringObjectFunction<T>, uint32_t> UIntVar;
0212   typedef FuncVariable<T, StringObjectFunction<T>, float> FloatVar;
0213   typedef FuncVariable<T, StringObjectFunction<T>, double> DoubleVar;
0214   typedef FuncVariable<T, StringObjectFunction<T>, int8_t> Int8Var;
0215   typedef FuncVariable<T, StringObjectFunction<T>, uint8_t> UInt8Var;
0216   typedef FuncVariable<T, StringObjectFunction<T>, int16_t> Int16Var;
0217   typedef FuncVariable<T, StringObjectFunction<T>, uint16_t> UInt16Var;
0218   typedef FuncVariable<T, StringCutObjectSelector<T>, bool> BoolVar;
0219   std::vector<std::unique_ptr<Variable<T>>> vars_;
0220 };
0221 
0222 template <typename T>
0223 class SimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, edm::View<T>> {
0224 public:
0225   SimpleFlatTableProducer(edm::ParameterSet const &params)
0226       : SimpleFlatTableProducerBase<T, edm::View<T>>(params),
0227         singleton_(params.getParameter<bool>("singleton")),
0228         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
0229                                                         : std::numeric_limits<unsigned int>::max()),
0230         cut_(!singleton_ ? params.getParameter<std::string>("cut") : "", true) {
0231     if (params.existsAs<edm::ParameterSet>("externalVariables")) {
0232       edm::ParameterSet const &extvarsPSet = params.getParameter<edm::ParameterSet>("externalVariables");
0233       for (const std::string &vname : extvarsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0234         const auto &varPSet = extvarsPSet.getParameter<edm::ParameterSet>(vname);
0235         const std::string &type = varPSet.getParameter<std::string>("type");
0236         if (type == "int")
0237           extvars_.push_back(
0238               std::make_unique<IntExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0239         else if (type == "uint")
0240           extvars_.push_back(
0241               std::make_unique<UIntExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0242         else if (type == "float")
0243           extvars_.push_back(
0244               std::make_unique<FloatExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0245         else if (type == "double")
0246           extvars_.push_back(
0247               std::make_unique<DoubleExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0248         else if (type == "int8")
0249           extvars_.push_back(
0250               std::make_unique<Int8ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0251         else if (type == "uint8")
0252           extvars_.push_back(
0253               std::make_unique<UInt8ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0254         else if (type == "int16")
0255           extvars_.push_back(
0256               std::make_unique<Int16ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0257         else if (type == "uint16")
0258           extvars_.push_back(
0259               std::make_unique<UInt16ExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0260         else if (type == "bool")
0261           extvars_.push_back(
0262               std::make_unique<BoolExtVar>(vname, varPSet, this->consumesCollector(), this->skipNonExistingSrc_));
0263         else
0264           throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0265       }
0266     }
0267   }
0268 
0269   ~SimpleFlatTableProducer() override {}
0270 
0271   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0272     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, edm::View<T>>::baseDescriptions();
0273 
0274     desc.ifValue(edm::ParameterDescription<bool>(
0275                      "singleton", false, true, edm::Comment("whether or not the input collection is single-element")),
0276                  false >> edm::ParameterDescription<std::string>(
0277                               "cut", "", true, edm::Comment("selection on the main input collection")) or
0278                      true >> edm::EmptyGroupDescription());
0279     desc.addOptional<unsigned int>("maxLen")->setComment(
0280         "define the maximum length of the input collection to put in the branch");
0281 
0282     edm::ParameterSetDescription extvariable;
0283     extvariable.add<edm::InputTag>("src")->setComment("valuemap input collection to fill the flat table");
0284     extvariable.add<std::string>("doc")->setComment("few words description of the branch content");
0285     extvariable.ifValue(
0286         edm::ParameterDescription<std::string>(
0287             "type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
0288         edm::allowedValues<std::string>("int", "uint", "float", "double", "int8", "uint8", "int16", "uint16", "bool"));
0289     extvariable.addOptionalNode(
0290         edm::ParameterDescription<int>(
0291             "precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
0292             edm::ParameterDescription<std::string>(
0293                 "precision", true, edm::Comment("the precision with which to store the value in the flat table")),
0294         false);
0295 
0296     edm::ParameterSetDescription extvariables;
0297     extvariables.setComment("a parameters set to define all variable taken form valuemap to fill the flat table");
0298     extvariables.addOptionalNode(
0299         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, extvariable), false);
0300     desc.addOptional<edm::ParameterSetDescription>("externalVariables", extvariables);
0301 
0302     descriptions.addWithDefaultLabel(desc);
0303   }
0304 
0305   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0306                                                 const edm::Handle<edm::View<T>> &prod) const override {
0307     std::vector<const T *> selobjs;
0308     std::vector<edm::Ptr<T>> selptrs;  // for external variables
0309     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0310       if (singleton_) {
0311         assert(prod->size() == 1);
0312         selobjs.push_back(&(*prod)[0]);
0313         if (!extvars_.empty())
0314           selptrs.emplace_back(prod->ptrAt(0));
0315       } else {
0316         for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0317           const auto &obj = (*prod)[i];
0318           if (cut_(obj)) {
0319             selobjs.push_back(&obj);
0320             if (!extvars_.empty())
0321               selptrs.emplace_back(prod->ptrAt(i));
0322           }
0323           if (selobjs.size() >= maxLen_)
0324             break;
0325         }
0326       }
0327     }
0328     auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, singleton_, this->extension_);
0329     for (const auto &var : this->vars_)
0330       var->fill(selobjs, *out);
0331     for (const auto &var : this->extvars_)
0332       var->fill(iEvent, selptrs, *out);
0333     return out;
0334   }
0335 
0336 protected:
0337   bool singleton_;
0338   const unsigned int maxLen_;
0339   const StringCutObjectSelector<T> cut_;
0340 
0341   typedef ValueMapVariable<T, int32_t> IntExtVar;
0342   typedef ValueMapVariable<T, uint32_t> UIntExtVar;
0343   typedef ValueMapVariable<T, float> FloatExtVar;
0344   typedef ValueMapVariable<T, double, float> DoubleExtVar;
0345   typedef ValueMapVariable<T, bool> BoolExtVar;
0346   typedef ValueMapVariable<T, int, int8_t> Int8ExtVar;
0347   typedef ValueMapVariable<T, int, uint8_t> UInt8ExtVar;
0348   typedef ValueMapVariable<T, int, int16_t> Int16ExtVar;
0349   typedef ValueMapVariable<T, int, uint16_t> UInt16ExtVar;
0350   std::vector<std::unique_ptr<ExtVariable<T>>> extvars_;
0351 };
0352 
0353 template <typename T>
0354 class BXVectorSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, BXVector<T>> {
0355 public:
0356   BXVectorSimpleFlatTableProducer(edm::ParameterSet const &params)
0357       : SimpleFlatTableProducerBase<T, BXVector<T>>(params),
0358         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
0359                                                         : std::numeric_limits<unsigned int>::max()),
0360         cut_(params.getParameter<std::string>("cut"), true),
0361         minBX_(params.getParameter<int>("minBX")),
0362         maxBX_(params.getParameter<int>("maxBX")),
0363         alwaysWriteBXValue_(params.getParameter<bool>("alwaysWriteBXValue")),
0364         bxVarName_("bx") {
0365     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
0366     auto varNames = varsPSet.getParameterNamesForType<edm::ParameterSet>();
0367     if (std::find(varNames.begin(), varNames.end(), bxVarName_) != varNames.end()) {
0368       throw cms::Exception("Configuration",
0369                            "BXVectorSimpleFlatTableProducer already defines the " + bxVarName_ +
0370                                "internally and thus you should not specify it yourself");
0371     }
0372   }
0373 
0374   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0375     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, BXVector<T>>::baseDescriptions();
0376     desc.add<std::string>("cut", "")->setComment(
0377         "selection on the main input collection (but selection can not be bx based)");
0378     desc.addOptional<unsigned int>("maxLen")->setComment(
0379         "define the maximum length of the input collection to put in the branch");
0380     desc.add<int>("minBX", -2)->setComment("min bx (inclusive) to include");
0381     desc.add<int>("maxBX", 2)->setComment("max bx (inclusive) to include");
0382     desc.add<bool>("alwaysWriteBXValue", true)
0383         ->setComment("always write the bx number (event  when only one bx can be present, ie minBX==maxBX)");
0384     descriptions.addWithDefaultLabel(desc);
0385   }
0386 
0387   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0388                                                 const edm::Handle<BXVector<T>> &prod) const override {
0389     std::vector<const T *> selObjs;
0390     std::vector<int> selObjBXs;
0391 
0392     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0393       const int minBX = std::max(minBX_, prod->getFirstBX());
0394       const int maxBX = std::min(maxBX_, prod->getLastBX());
0395       for (int bx = minBX; bx <= maxBX; bx++) {
0396         for (size_t objNr = 0, nrObjs = prod->size(bx); objNr < nrObjs; ++objNr) {
0397           const auto &obj = prod->at(bx, objNr);
0398           if (cut_(obj)) {
0399             selObjs.push_back(&obj);
0400             selObjBXs.push_back(bx);
0401           }
0402           if (selObjs.size() >= maxLen_)
0403             break;
0404         }
0405       }
0406     }
0407     auto out = std::make_unique<nanoaod::FlatTable>(selObjs.size(), this->name_, false, this->extension_);
0408     for (const auto &var : this->vars_)
0409       var->fill(selObjs, *out);
0410     if (alwaysWriteBXValue_ || minBX_ != maxBX_) {
0411       out->template addColumn<int16_t>(bxVarName_, selObjBXs, "BX of the L1 candidate");
0412     }
0413     return out;
0414   }
0415 
0416 protected:
0417   const unsigned int maxLen_;
0418   const StringCutObjectSelector<T> cut_;
0419   const int minBX_;
0420   const int maxBX_;
0421   const bool alwaysWriteBXValue_;
0422   const std::string bxVarName_;
0423 };
0424 
0425 template <typename T>
0426 class EventSingletonSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, T> {
0427 public:
0428   EventSingletonSimpleFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducerBase<T, T>(params) {}
0429 
0430   ~EventSingletonSimpleFlatTableProducer() override {}
0431 
0432   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0433     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, T>::baseDescriptions();
0434     descriptions.addWithDefaultLabel(desc);
0435   }
0436 
0437   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &, const edm::Handle<T> &prod) const override {
0438     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
0439     std::vector<const T *> selobjs(1, prod.product());
0440     for (const auto &var : this->vars_)
0441       var->fill(selobjs, *out);
0442     return out;
0443   }
0444 };
0445 
0446 template <typename T>
0447 class FirstObjectSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, edm::View<T>> {
0448 public:
0449   FirstObjectSimpleFlatTableProducer(edm::ParameterSet const &params)
0450       : SimpleFlatTableProducerBase<T, edm::View<T>>(params) {}
0451 
0452   ~FirstObjectSimpleFlatTableProducer() override {}
0453 
0454   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0455     edm::ParameterSetDescription desc = desc = SimpleFlatTableProducerBase<T, edm::View<T>>::baseDescriptions();
0456     descriptions.addWithDefaultLabel(desc);
0457   }
0458 
0459   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent,
0460                                                 const edm::Handle<edm::View<T>> &prod) const override {
0461     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
0462     std::vector<const T *> selobjs(1, &(*prod)[0]);
0463     for (const auto &var : this->vars_)
0464       var->fill(selobjs, *out);
0465     return out;
0466   }
0467 };
0468 
0469 // LuminosityBlock producers
0470 // - ABC
0471 // - Singleton
0472 // - Collection
0473 template <typename T, typename TProd>
0474 class SimpleFlatTableProducerBaseLumi
0475     : public edm::one::EDProducer<edm::EndLuminosityBlockProducer, edm::LuminosityBlockCache<int>> {
0476 public:
0477   SimpleFlatTableProducerBaseLumi(edm::ParameterSet const &params)
0478       : name_(params.getParameter<std::string>("name")),
0479         doc_(params.existsAs<std::string>("doc") ? params.getParameter<std::string>("doc") : ""),
0480         extension_(params.existsAs<bool>("extension") ? params.getParameter<bool>("extension") : false),
0481         skipNonExistingSrc_(
0482 
0483             params.existsAs<bool>("skipNonExistingSrc") ? params.getParameter<bool>("skipNonExistingSrc") : false),
0484         src_(consumes<TProd, edm::InLumi>(params.getParameter<edm::InputTag>("src"))) {
0485     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
0486     for (const std::string &vname : varsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0487       const auto &varPSet = varsPSet.getParameter<edm::ParameterSet>(vname);
0488       const std::string &type = varPSet.getParameter<std::string>("type");
0489       if (type == "int")
0490         vars_.push_back(std::make_unique<IntVar>(vname, varPSet));
0491       else if (type == "float")
0492         vars_.push_back(std::make_unique<FloatVar>(vname, varPSet));
0493       else if (type == "uint8")
0494         vars_.push_back(std::make_unique<UInt8Var>(vname, varPSet));
0495       else if (type == "bool")
0496         vars_.push_back(std::make_unique<BoolVar>(vname, varPSet));
0497       else
0498         throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0499     }
0500 
0501     produces<nanoaod::FlatTable, edm::Transition::EndLuminosityBlock>();
0502   }
0503 
0504   ~SimpleFlatTableProducerBaseLumi() override {}
0505 
0506   std::shared_ptr<int> globalBeginLuminosityBlock(edm::LuminosityBlock const &,
0507                                                   edm::EventSetup const &) const override {
0508     return nullptr;
0509   }
0510 
0511   void globalEndLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) override {}
0512 
0513   // this is to be overriden by the child class
0514   virtual std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::LuminosityBlock &iLumi,
0515                                                         const edm::Handle<TProd> &prod) const = 0;
0516 
0517   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
0518     // do nothing
0519   }
0520 
0521   void endLuminosityBlockProduce(edm::LuminosityBlock &iLumi, const edm::EventSetup &iSetup) final {
0522     edm::Handle<TProd> src;
0523     iLumi.getByToken(src_, src);
0524 
0525     std::unique_ptr<nanoaod::FlatTable> out = fillTable(iLumi, src);
0526     out->setDoc(doc_);
0527 
0528     iLumi.put(std::move(out));
0529   }
0530 
0531 protected:
0532   const std::string name_;
0533   const std::string doc_;
0534   const bool extension_;
0535   const bool skipNonExistingSrc_;
0536   const edm::EDGetTokenT<TProd> src_;
0537 
0538   typedef FuncVariable<T, StringObjectFunction<T>, int> IntVar;
0539   typedef FuncVariable<T, StringObjectFunction<T>, float> FloatVar;
0540   typedef FuncVariable<T, StringObjectFunction<T>, uint8_t> UInt8Var;
0541   typedef FuncVariable<T, StringCutObjectSelector<T>, bool> BoolVar;
0542   std::vector<std::unique_ptr<Variable<T>>> vars_;
0543 };
0544 
0545 // Class for singletons like GenFilterInfo
0546 template <typename T>
0547 class LumiSingletonSimpleFlatTableProducer : public SimpleFlatTableProducerBaseLumi<T, T> {
0548 public:
0549   LumiSingletonSimpleFlatTableProducer(edm::ParameterSet const &params)
0550       : SimpleFlatTableProducerBaseLumi<T, T>(params) {}
0551 
0552   ~LumiSingletonSimpleFlatTableProducer() override {}
0553 
0554   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0555     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, T>::baseDescriptions();
0556     descriptions.addWithDefaultLabel(desc);
0557   }
0558 
0559   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::LuminosityBlock &,
0560                                                 const edm::Handle<T> &prod) const override {
0561     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
0562     std::vector<const T *> selobjs(1, prod.product());
0563     for (const auto &var : this->vars_)
0564       var->fill(selobjs, *out);
0565     return out;
0566   }
0567 };
0568 
0569 // Class for generic collections
0570 template <typename T, typename TProd>
0571 class LumiSimpleFlatTableProducer : public SimpleFlatTableProducerBaseLumi<T, TProd> {
0572 public:
0573   LumiSimpleFlatTableProducer(edm::ParameterSet const &params)
0574       : SimpleFlatTableProducerBaseLumi<T, TProd>(params),
0575         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
0576                                                         : std::numeric_limits<unsigned int>::max()),
0577         cut_(params.existsAs<std::string>("cut") ? params.getParameter<std::string>("cut") : "", true) {}
0578 
0579   ~LumiSimpleFlatTableProducer() override {}
0580 
0581   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0582     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, TProd>::baseDescriptions();
0583     desc.addOptional<unsigned int>("maxLen")->setComment(
0584         "define the maximum length of the input collection to put in the branch");
0585     descriptions.addWithDefaultLabel(desc);
0586   }
0587 
0588   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::LuminosityBlock &iLumi,
0589                                                 const edm::Handle<TProd> &prod) const override {
0590     std::vector<const T *> selobjs;
0591     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0592       for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0593         const auto &obj = (*prod)[i];
0594         if (cut_(obj)) {
0595           selobjs.push_back(&obj);
0596         }
0597         if (selobjs.size() >= maxLen_)
0598           break;
0599       }
0600     }
0601     auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, false, this->extension_);
0602     for (const auto &var : this->vars_)
0603       var->fill(selobjs, *out);
0604     return out;
0605   }
0606 
0607 protected:
0608   const unsigned int maxLen_;
0609   const StringCutObjectSelector<T> cut_;
0610 };
0611 
0612 // Run producers
0613 // - ABC
0614 // - Singleton
0615 // - Collection
0616 template <typename T, typename TProd>
0617 class SimpleFlatTableProducerBaseRun : public edm::one::EDProducer<edm::EndRunProducer, edm::RunCache<int>> {
0618 public:
0619   SimpleFlatTableProducerBaseRun(edm::ParameterSet const &params)
0620       : name_(params.getParameter<std::string>("name")),
0621         doc_(params.existsAs<std::string>("doc") ? params.getParameter<std::string>("doc") : ""),
0622         extension_(params.existsAs<bool>("extension") ? params.getParameter<bool>("extension") : false),
0623         skipNonExistingSrc_(
0624 
0625             params.existsAs<bool>("skipNonExistingSrc") ? params.getParameter<bool>("skipNonExistingSrc") : false),
0626         src_(consumes<TProd, edm::InRun>(params.getParameter<edm::InputTag>("src"))) {
0627     edm::ParameterSet const &varsPSet = params.getParameter<edm::ParameterSet>("variables");
0628     for (const std::string &vname : varsPSet.getParameterNamesForType<edm::ParameterSet>()) {
0629       const auto &varPSet = varsPSet.getParameter<edm::ParameterSet>(vname);
0630       const std::string &type = varPSet.getParameter<std::string>("type");
0631       if (type == "int")
0632         vars_.push_back(std::make_unique<IntVar>(vname, varPSet));
0633       else if (type == "float")
0634         vars_.push_back(std::make_unique<FloatVar>(vname, varPSet));
0635       else if (type == "uint8")
0636         vars_.push_back(std::make_unique<UInt8Var>(vname, varPSet));
0637       else if (type == "bool")
0638         vars_.push_back(std::make_unique<BoolVar>(vname, varPSet));
0639       else
0640         throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + vname);
0641     }
0642 
0643     produces<nanoaod::FlatTable, edm::Transition::EndRun>();
0644   }
0645 
0646   ~SimpleFlatTableProducerBaseRun() override {}
0647 
0648   std::shared_ptr<int> globalBeginRun(edm::Run const &, edm::EventSetup const &) const override { return nullptr; }
0649 
0650   void globalEndRun(edm::Run const &, edm::EventSetup const &) override {}
0651 
0652   // this is to be overriden by the child class
0653   virtual std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Run &iRun, const edm::Handle<TProd> &prod) const = 0;
0654 
0655   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
0656     // do nothing
0657   }
0658 
0659   void endRunProduce(edm::Run &iRun, const edm::EventSetup &iSetup) final {
0660     edm::Handle<TProd> src;
0661     iRun.getByToken(src_, src);
0662 
0663     std::unique_ptr<nanoaod::FlatTable> out = fillTable(iRun, src);
0664     out->setDoc(doc_);
0665 
0666     iRun.put(std::move(out));
0667   }
0668 
0669 protected:
0670   const std::string name_;
0671   const std::string doc_;
0672   const bool extension_;
0673   const bool skipNonExistingSrc_;
0674   const edm::EDGetTokenT<TProd> src_;
0675 
0676   typedef FuncVariable<T, StringObjectFunction<T>, int> IntVar;
0677   typedef FuncVariable<T, StringObjectFunction<T>, float> FloatVar;
0678   typedef FuncVariable<T, StringObjectFunction<T>, uint8_t> UInt8Var;
0679   typedef FuncVariable<T, StringCutObjectSelector<T>, bool> BoolVar;
0680   std::vector<std::unique_ptr<Variable<T>>> vars_;
0681 };
0682 
0683 // Class for singletons like GenFilterInfo
0684 template <typename T>
0685 class RunSingletonSimpleFlatTableProducer : public SimpleFlatTableProducerBaseRun<T, T> {
0686 public:
0687   RunSingletonSimpleFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducerBaseRun<T, T>(params) {}
0688 
0689   ~RunSingletonSimpleFlatTableProducer() override {}
0690 
0691   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Run &, const edm::Handle<T> &prod) const override {
0692     auto out = std::make_unique<nanoaod::FlatTable>(1, this->name_, true, this->extension_);
0693     std::vector<const T *> selobjs(1, prod.product());
0694     for (const auto &var : this->vars_)
0695       var->fill(selobjs, *out);
0696     return out;
0697   }
0698 };
0699 
0700 // Class for generic collections
0701 template <typename T, typename TProd>
0702 class RunSimpleFlatTableProducer : public SimpleFlatTableProducerBaseRun<T, TProd> {
0703 public:
0704   RunSimpleFlatTableProducer(edm::ParameterSet const &params)
0705       : SimpleFlatTableProducerBaseRun<T, TProd>(params),
0706         maxLen_(params.existsAs<unsigned int>("maxLen") ? params.getParameter<unsigned int>("maxLen")
0707                                                         : std::numeric_limits<unsigned int>::max()),
0708         cut_(params.existsAs<std::string>("cut") ? params.getParameter<std::string>("cut") : "", true) {}
0709 
0710   ~RunSimpleFlatTableProducer() override {}
0711 
0712   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Run &iRun, const edm::Handle<TProd> &prod) const override {
0713     std::vector<const T *> selobjs;
0714     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0715       for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0716         const auto &obj = (*prod)[i];
0717         if (cut_(obj)) {
0718           selobjs.push_back(&obj);
0719         }
0720         if (selobjs.size() >= maxLen_)
0721           break;
0722       }
0723     }
0724     auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, false, this->extension_);
0725     for (const auto &var : this->vars_)
0726       var->fill(selobjs, *out);
0727     return out;
0728   }
0729 
0730 protected:
0731   const unsigned int maxLen_;
0732   const StringCutObjectSelector<T> cut_;
0733 };