Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-25 23:31:25

0001 #ifndef HLTrigger_HLTUpgradeNano_AssociationMapFlatTable_h
0002 #define HLTrigger_HLTUpgradeNano_AssociationMapFlatTable_h
0003 
0004 #include <type_traits>
0005 
0006 #include "PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h"
0007 #include "SimDataFormats/Associations/interface/TICLAssociationMap.h"
0008 
0009 // Concept to check if a type is a valid AssociationMap of AssociationElement, both oneToOne and oneToMany.
0010 // For oneToOne pass as Container the type std::vector<T::AssociationElementType>
0011 // For oneToMany pass as Container the type std::vector<std::vector<T::AssociationElementType>>
0012 template <typename T, typename Container>
0013 concept IsValidAssociationMap = requires {
0014   typename T::Traits;
0015   typename T::AssociationElementType;
0016   typename T::V;
0017   typename T::Type;
0018 
0019   requires std::is_same_v<typename T::Type, Container>;
0020 };
0021 
0022 template <typename T>
0023   requires IsValidAssociationMap<T, std::vector<typename T::AssociationElementType>>
0024 class AssociationOneToOneFlatTableProducer : public SimpleFlatTableProducerBase<typename T::AssociationElementType, T> {
0025 public:
0026   using TProd = T::AssociationElementType;
0027   AssociationOneToOneFlatTableProducer(edm::ParameterSet const &params)
0028       : SimpleFlatTableProducerBase<typename T::AssociationElementType, T>(params) {}
0029 
0030   ~AssociationOneToOneFlatTableProducer() override {}
0031 
0032   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent, const edm::Handle<T> &prod) const override {
0033     // First unroll the Container inside the associator map.
0034 
0035     auto table_size = prod->getMap().size();
0036     auto out = std::make_unique<nanoaod::FlatTable>(table_size, this->name_, false);
0037 
0038     std::vector<const TProd *> selobjs;
0039     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0040       for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0041         const auto &obj = (*prod)[i];
0042         selobjs.push_back(&obj);
0043       }
0044     }
0045 
0046     for (const auto &var : this->vars_)
0047       var->fill(selobjs, *out);
0048     return out;
0049   }
0050 
0051   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0052     edm::ParameterSetDescription desc =
0053         SimpleFlatTableProducerBase<typename T::AssociationElementType, T>::baseDescriptions();
0054     descriptions.addWithDefaultLabel(desc);
0055   }
0056 };
0057 
0058 template <typename T>
0059   requires IsValidAssociationMap<T, std::vector<std::vector<typename T::AssociationElementType>>>
0060 class AssociationOneToManyFlatTableProducer : public SimpleFlatTableProducerBase<T, T> {
0061 public:
0062   using TProd = T::AssociationElementType;
0063   AssociationOneToManyFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducerBase<T, T>(params) {
0064     if (params.existsAs<edm::ParameterSet>("collectionVariables")) {
0065       edm::ParameterSet const &collectionVarsPSet = params.getParameter<edm::ParameterSet>("collectionVariables");
0066       for (const std::string &coltablename :
0067            collectionVarsPSet.getParameterNamesForType<edm::ParameterSet>()) {  // tables of variables
0068         const auto &coltablePSet = collectionVarsPSet.getParameter<edm::ParameterSet>(coltablename);
0069         CollectionVariableTableInfo coltable;
0070         coltable.name =
0071             coltablePSet.existsAs<std::string>("name") ? coltablePSet.getParameter<std::string>("name") : coltablename;
0072         coltable.doc = coltablePSet.getParameter<std::string>("doc");
0073         coltable.useCount = coltablePSet.getParameter<bool>("useCount");
0074         coltable.useOffset = coltablePSet.getParameter<bool>("useOffset");
0075         const auto &colvarsPSet = coltablePSet.getParameter<edm::ParameterSet>("variables");
0076         for (const std::string &colvarname : colvarsPSet.getParameterNamesForType<edm::ParameterSet>()) {  // variables
0077           const auto &colvarPSet = colvarsPSet.getParameter<edm::ParameterSet>(colvarname);
0078           const std::string &type = colvarPSet.getParameter<std::string>("type");
0079           if (type == "int")
0080             coltable.colvars.push_back(std::make_unique<IntVectorVar>(colvarname, colvarPSet));
0081           else if (type == "uint")
0082             coltable.colvars.push_back(std::make_unique<UIntVectorVar>(colvarname, colvarPSet));
0083           else if (type == "float")
0084             coltable.colvars.push_back(std::make_unique<FloatVectorVar>(colvarname, colvarPSet));
0085           else if (type == "double")
0086             coltable.colvars.push_back(std::make_unique<DoubleVectorVar>(colvarname, colvarPSet));
0087           else if (type == "uint8")
0088             coltable.colvars.push_back(std::make_unique<UInt8VectorVar>(colvarname, colvarPSet));
0089           else if (type == "int16")
0090             coltable.colvars.push_back(std::make_unique<Int16VectorVar>(colvarname, colvarPSet));
0091           else if (type == "uint16")
0092             coltable.colvars.push_back(std::make_unique<UInt16VectorVar>(colvarname, colvarPSet));
0093           else
0094             throw cms::Exception("Configuration",
0095                                  "unsupported type " + type + " for variable " + colvarname + " in " + coltablename);
0096         }
0097         this->coltables.push_back(std::move(coltable));
0098         edm::stream::EDProducer<>::produces<nanoaod::FlatTable>(coltables.back().name + "Table");
0099         std::cout << "MR OneToMany will produce " << coltables.back().name + "Table" << std::endl;
0100       }
0101     }
0102   }
0103 
0104   ~AssociationOneToManyFlatTableProducer() override {}
0105 
0106   void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
0107     // same as SimpleFlatTableProducer
0108     edm::Handle<T> prod;
0109     iEvent.getByToken(SimpleFlatTableProducerBase<T, T>::src_, prod);
0110 
0111     // First unroll the Container inside the associator map.
0112 
0113     auto table_size = prod->getMap().size();
0114     auto out = std::make_unique<nanoaod::FlatTable>(table_size, this->name_, false);
0115 
0116     // Now proceed with the variable-sized linked objects.
0117     unsigned int coltablesize = 0;
0118     std::vector<unsigned int> counts;
0119     counts.reserve(table_size);
0120     for (auto const &links : prod->getMap()) {
0121       counts.push_back(links.size());
0122       coltablesize += counts.back();
0123     }
0124 
0125     std::vector<const TProd *> selobjs;
0126     selobjs.reserve(coltablesize);
0127     if (prod.isValid() || !(this->skipNonExistingSrc_)) {
0128       for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
0129         const auto &obj = (*prod)[i];
0130         for (auto const &assocElement : obj) {
0131           selobjs.push_back(&assocElement);
0132         }
0133       }
0134     }
0135 
0136     // collection variable tables
0137     for (const auto &coltable : this->coltables) {
0138       // add count branch if requested
0139       if (coltable.useCount)
0140         out->template addColumn<uint16_t>("n" + coltable.name, counts, "counts for " + coltable.name);
0141       // add offset branch if requested
0142       if (coltable.useOffset) {
0143         unsigned int offset = 0;
0144         std::vector<unsigned int> offsets;
0145         offsets.reserve(table_size);
0146         for (auto const &count : counts) {
0147           offsets.push_back(offset);
0148           offset += count;
0149         }
0150         out->template addColumn<uint16_t>("o" + coltable.name, offsets, "offsets for " + coltable.name);
0151       }
0152 
0153       std::unique_ptr<nanoaod::FlatTable> outcoltable =
0154           std::make_unique<nanoaod::FlatTable>(coltablesize, coltable.name, false, false);
0155       for (const auto &colvar : coltable.colvars) {
0156         colvar->fill(selobjs, *outcoltable);
0157       }
0158       outcoltable->setDoc(coltable.doc);
0159       iEvent.put(std::move(outcoltable), coltable.name + "Table");
0160     }
0161 
0162     // put the main table into the event
0163     out->setDoc(this->doc_);
0164     iEvent.put(std::move(out));
0165   }
0166 
0167   // Make compiler happy.
0168   std::unique_ptr<nanoaod::FlatTable> fillTable(const edm::Event &iEvent, const edm::Handle<T> &prod) const override {
0169     // Do nothing here and move all the heavy lifting in the produce method.
0170     auto out = std::make_unique<nanoaod::FlatTable>();
0171     return out;
0172   }
0173 
0174   static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
0175     edm::ParameterSetDescription desc = SimpleFlatTableProducerBase<T, T>::baseDescriptions();
0176     edm::ParameterSetDescription colvariable;
0177     colvariable.add<std::string>("expr")->setComment(
0178         "a function to define the content of the branch in the flat table");
0179     colvariable.add<std::string>("doc")->setComment("few words of self documentation");
0180     colvariable.addUntracked<bool>("lazyEval", false)
0181         ->setComment("if true, can use methods of inheriting classes in `expr`. Can cause problems with threading.");
0182     colvariable.ifValue(edm::ParameterDescription<std::string>(
0183                             "type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
0184                         edm::allowedValues<std::string>("int", "uint", "float", "double", "uint8", "int16", "uint16"));
0185     colvariable.addOptionalNode(
0186         edm::ParameterDescription<int>(
0187             "precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
0188             edm::ParameterDescription<std::string>(
0189                 "precision", true, edm::Comment("the precision with which to store the value in the flat table")),
0190         false);
0191     edm::ParameterSetDescription colvariables;
0192     colvariables.setComment("a parameters set to define all variable to fill the flat table");
0193     colvariables.addNode(
0194         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireAtLeastOne, true, colvariable));
0195 
0196     edm::ParameterSetDescription coltable;
0197     coltable.addOptional<std::string>("name")->setComment(
0198         "name of the branch in the flat table containing flatten collections of variables");
0199     coltable.add<std::string>("doc")->setComment(
0200         "few words description of the table containing flatten collections of variables");
0201     coltable.add<bool>("useCount", true)
0202         ->setComment("whether to use count for the main table to index table with flatten collections of variables");
0203     coltable.add<bool>("useOffset", false)
0204         ->setComment("whether to use offset for the main table to index table with flatten collections of variables");
0205     coltable.add<edm::ParameterSetDescription>("variables", colvariables);
0206 
0207     edm::ParameterSetDescription coltables;
0208     coltables.setComment("a parameters set to define variables to be flatten to fill the table");
0209     coltables.addOptionalNode(
0210         edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, coltable), false);
0211     desc.addOptional<edm::ParameterSetDescription>("collectionVariables", coltables);
0212 
0213     descriptions.addWithDefaultLabel(desc);
0214   }
0215 
0216 protected:
0217   template <typename R>
0218   using VectorVar = FuncVariable<TProd, StringObjectFunction<TProd>, R>;
0219 
0220   using IntVectorVar = VectorVar<int32_t>;
0221   using UIntVectorVar = VectorVar<uint32_t>;
0222   using FloatVectorVar = VectorVar<float>;
0223   using DoubleVectorVar = VectorVar<double>;
0224   using UInt8VectorVar = VectorVar<uint8_t>;
0225   using Int16VectorVar = VectorVar<int16_t>;
0226   using UInt16VectorVar = VectorVar<uint16_t>;
0227 
0228   struct CollectionVariableTableInfo {
0229     std::string name;
0230     std::string doc;
0231     bool useCount;
0232     bool useOffset;
0233     std::vector<std::unique_ptr<Variable<TProd>>> colvars;
0234   };
0235   std::vector<CollectionVariableTableInfo> coltables;
0236 };
0237 
0238 // OneToOne, Fraction and Fraction with Score
0239 template <typename Source, typename Target>
0240 using AssociationMapOneToOneFraction =
0241     ticl::AssociationMap<vector<ticl::AssociationElement<ticl::FractionType>>, std::vector<Source>, std::vector<Target>>;
0242 
0243 template <typename Source, typename Target>
0244 using AssociationMapOneToOneFractionScore =
0245     ticl::AssociationMap<vector<ticl::AssociationElement<std::pair<ticl::FractionType, float>>>,
0246                          std::vector<Source>,
0247                          std::vector<Target>>;
0248 
0249 // OneToOne, SharedEnergy and SharedEnergy with Score
0250 template <typename Source, typename Target>
0251 using AssociationMapOneToOneSharedEnergy = ticl::
0252     AssociationMap<vector<ticl::AssociationElement<ticl::SharedEnergyType>>, std::vector<Source>, std::vector<Target>>;
0253 
0254 template <typename Source, typename Target>
0255 using AssociationMapOneToOneSharedEnergyScore =
0256     ticl::AssociationMap<vector<ticl::AssociationElement<std::pair<ticl::SharedEnergyType, float>>>,
0257                          std::vector<Source>,
0258                          std::vector<Target>>;
0259 
0260 // OneToMany, Fraction and Fraction with Score
0261 template <typename Source, typename Target>
0262 using AssociationMapOneToManyFraction =
0263     ticl::AssociationMap<vector<vector<ticl::AssociationElement<ticl::FractionType>>>, vector<Source>, vector<Target>>;
0264 
0265 template <typename Source, typename Target>
0266 using AssociationMapOneToManyFractionScore =
0267     ticl::AssociationMap<vector<vector<ticl::AssociationElement<pair<ticl::FractionType, float>>>>,
0268                          vector<Source>,
0269                          vector<Target>>;
0270 
0271 // OneToMany, SharedEnergy and SharedEnergy with Score
0272 template <typename Source, typename Target>
0273 using AssociationMapOneToManySharedEnergy = ticl::
0274     AssociationMap<vector<vector<ticl::AssociationElement<ticl::SharedEnergyType>>>, vector<Source>, vector<Target>>;
0275 
0276 template <typename Source, typename Target>
0277 using AssociationMapOneToManySharedEnergyScore =
0278     ticl::AssociationMap<vector<vector<ticl::AssociationElement<pair<ticl::SharedEnergyType, float>>>>,
0279                          vector<Source>,
0280                          vector<Target>>;
0281 
0282 #endif