Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-25 02:14:03

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