Skip to content

Commit fad42d6

Browse files
committed
add FuncCollectionVariable for handling collection attributes and SimpleCollectionFlatTableProducer as an extension to SimpleFlatTableProducer to handle collection attributes of objects
1 parent c13d00c commit fad42d6

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed

PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "CommonTools/Utils/interface/StringCutObjectSelector.h"
1616
#include "CommonTools/Utils/interface/StringObjectFunction.h"
17+
#include "CommonTools/Utils/interface/TypedStringObjectMethodCaller.h"
1718

1819
#include <memory>
1920
#include <vector>
@@ -73,6 +74,55 @@ class FuncVariable : public Variable<ObjType> {
7374
StringFunctor precisionFunc_;
7475
};
7576

77+
// Collection variables: i.e. variables that is variable-size collection, e.g. std::vector
78+
template <typename ObjType>
79+
class CollectionVariable : public VariableBase {
80+
public:
81+
CollectionVariable(const std::string &aname, const edm::ParameterSet &cfg) : VariableBase(aname, cfg) {}
82+
virtual std::unique_ptr<std::vector<unsigned int>> getCounts(std::vector<const ObjType *> &selobjs) const = 0;
83+
virtual void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const = 0;
84+
};
85+
86+
template <typename ObjType, typename CollectionStringFunctor, typename PrecisionStringFunctor, typename ValType>
87+
class FuncCollectionVariable : public CollectionVariable<ObjType> {
88+
public:
89+
FuncCollectionVariable(const std::string &aname, const edm::ParameterSet &cfg)
90+
: CollectionVariable<ObjType>(aname, cfg),
91+
func_(cfg.getParameter<std::string>("expr"), cfg.getUntrackedParameter<bool>("lazyEval")),
92+
precisionFunc_(cfg.existsAs<std::string>("precision") ? cfg.getParameter<std::string>("precision") : "23",
93+
cfg.getUntrackedParameter<bool>("lazyEval")) {}
94+
~FuncCollectionVariable() override {}
95+
96+
std::unique_ptr<std::vector<unsigned int>> getCounts(std::vector<const ObjType *> &selobjs) const override{
97+
auto counts = std::make_unique<std::vector<unsigned int>>();
98+
for (auto const &obj : selobjs)
99+
counts->push_back(func_(*obj).size());
100+
return counts;
101+
}
102+
103+
void fill(std::vector<const ObjType *> &selobjs, nanoaod::FlatTable &out) const override {
104+
std::vector<ValType> vals;
105+
for (unsigned int i = 0; i < selobjs.size(); ++i) {
106+
for (ValType val : func_(*selobjs[i])) {
107+
if constexpr (std::is_same<ValType, float>()) {
108+
if (this->precision_ == -2) {
109+
auto prec = precisionFunc_(*selobjs[i]);
110+
if (prec > 0) {
111+
val = MiniFloatConverter::reduceMantissaToNbitsRounding(val, prec);
112+
}
113+
}
114+
}
115+
vals.push_back(val);
116+
}
117+
}
118+
out.template addColumn<ValType>(this->name_, vals, this->doc_, this->precision_);
119+
}
120+
121+
protected:
122+
CollectionStringFunctor func_; // functor to get collection objects
123+
PrecisionStringFunctor precisionFunc_; // functor to get output precision
124+
};
125+
76126
// External variables: i.e. variables that are not member or methods of the object
77127
template <typename ObjType>
78128
class ExtVariable : public VariableBase {
@@ -486,6 +536,176 @@ class SimpleTypedExternalFlatTableProducer : public SimpleFlatTableProducer<T> {
486536
typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, uint16_t> UInt16TypedExtVar;
487537
};
488538

539+
template <typename T>
540+
class SimpleCollectionFlatTableProducer : public SimpleFlatTableProducer<T> {
541+
public:
542+
SimpleCollectionFlatTableProducer(edm::ParameterSet const &params) : SimpleFlatTableProducer<T>(params) {
543+
if (params.existsAs<edm::ParameterSet>("collectionVariables")) {
544+
edm::ParameterSet const &collectionVarsPSet = params.getParameter<edm::ParameterSet>("collectionVariables");
545+
for (const std::string &coltablename : collectionVarsPSet.getParameterNamesForType<edm::ParameterSet>()) { // tables of variables
546+
const auto &coltablePSet = collectionVarsPSet.getParameter<edm::ParameterSet>(coltablename);
547+
CollectionVariableTableInfo coltable;
548+
coltable.name = coltablePSet.existsAs<std::string>("name") ? coltablePSet.getParameter<std::string>("name") : coltablename;
549+
coltable.doc = coltablePSet.getParameter<std::string>("doc");
550+
coltable.useCount = coltablePSet.getParameter<bool>("useCount");
551+
coltable.useOffset = coltablePSet.getParameter<bool>("useOffset");
552+
const auto &colvarsPSet = coltablePSet.getParameter<edm::ParameterSet>("variables");
553+
for (const std::string &colvarname : colvarsPSet.getParameterNamesForType<edm::ParameterSet>()) { // variables
554+
const auto &colvarPSet = colvarsPSet.getParameter<edm::ParameterSet>(colvarname);
555+
const std::string &type = colvarPSet.getParameter<std::string>("type");
556+
if (type == "int")
557+
coltable.colvars.push_back(std::make_unique<IntVectorVar>(colvarname, colvarPSet));
558+
else if (type == "uint")
559+
coltable.colvars.push_back(std::make_unique<UIntVectorVar>(colvarname, colvarPSet));
560+
else if (type == "float")
561+
coltable.colvars.push_back(std::make_unique<FloatVectorVar>(colvarname, colvarPSet));
562+
else if (type == "double")
563+
coltable.colvars.push_back(std::make_unique<DoubleVectorVar>(colvarname, colvarPSet));
564+
else if (type == "uint8")
565+
coltable.colvars.push_back(std::make_unique<UInt8VectorVar>(colvarname, colvarPSet));
566+
else if (type == "int16")
567+
coltable.colvars.push_back(std::make_unique<Int16VectorVar>(colvarname, colvarPSet));
568+
else if (type == "uint16")
569+
coltable.colvars.push_back(std::make_unique<UInt16VectorVar>(colvarname, colvarPSet));
570+
else
571+
throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + colvarname + " in " + coltablename);
572+
}
573+
this->coltables.push_back(std::move(coltable));
574+
edm::stream::EDProducer<>::produces<nanoaod::FlatTable>(coltables.back().name + "Table");
575+
}
576+
}
577+
}
578+
579+
~SimpleCollectionFlatTableProducer() override {}
580+
581+
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
582+
edm::ParameterSetDescription desc = SimpleFlatTableProducer<T>::baseDescriptions();
583+
edm::ParameterSetDescription colvariable;
584+
colvariable.add<std::string>("expr")->setComment("a function to define the content of the branch in the flat table");
585+
colvariable.add<std::string>("doc")->setComment("few words of self documentation");
586+
colvariable.addUntracked<bool>("lazyEval", false)
587+
->setComment("if true, can use methods of inheriting classes in `expr`. Can cause problems with threading.");
588+
colvariable.ifValue(
589+
edm::ParameterDescription<std::string>(
590+
"type", "int", true, edm::Comment("the c++ type of the branch in the flat table")),
591+
edm::allowedValues<std::string>("int", "uint", "float", "double", "uint8", "int16", "uint16"));
592+
colvariable.addOptionalNode(
593+
edm::ParameterDescription<int>(
594+
"precision", true, edm::Comment("the precision with which to store the value in the flat table")) xor
595+
edm::ParameterDescription<std::string>(
596+
"precision", true, edm::Comment("the precision with which to store the value in the flat table")),
597+
false);
598+
edm::ParameterSetDescription colvariables;
599+
colvariables.setComment("a parameters set to define all variable to fill the flat table");
600+
colvariables.addNode(
601+
edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireAtLeastOne, true, colvariable));
602+
603+
edm::ParameterSetDescription coltable;
604+
coltable.addOptional<std::string>("name")->setComment("name of the branch in the flat table containing flatten collections of variables");
605+
coltable.add<std::string>("doc")->setComment("few words description of the table containing flatten collections of variables");
606+
coltable.add<bool>("useCount", true)
607+
->setComment("whether to use count for the main table to index table with flatten collections of variables");
608+
coltable.add<bool>("useOffset", false)
609+
->setComment("whether to use offset for the main table to index table with flatten collections of variables");
610+
coltable.add<edm::ParameterSetDescription>("variables", colvariables);
611+
612+
edm::ParameterSetDescription coltables;
613+
coltables.setComment("a parameters set to define variables to be flatten to fill the table");
614+
coltables.addOptionalNode(
615+
edm::ParameterWildcard<edm::ParameterSetDescription>("*", edm::RequireZeroOrMore, true, coltable), false);
616+
desc.addOptional<edm::ParameterSetDescription>("collectionVariables", coltables);
617+
618+
descriptions.addWithDefaultLabel(desc);
619+
}
620+
621+
void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override {
622+
// same as SimpleFlatTableProducer
623+
edm::Handle<edm::View<T>> prod;
624+
iEvent.getByToken(this->src_, prod);
625+
626+
std::vector<const T *> selobjs;
627+
std::vector<edm::Ptr<T>> selptrs; // for external variables
628+
if (prod.isValid() || !(this->skipNonExistingSrc_)) {
629+
if (this->singleton_) {
630+
assert(prod->size() == 1);
631+
selobjs.push_back(&(*prod)[0]);
632+
if (!this->extvars_.empty() || !this->typedextvars_.empty())
633+
selptrs.emplace_back(prod->ptrAt(0));
634+
} else {
635+
for (unsigned int i = 0, n = prod->size(); i < n; ++i) {
636+
const auto &obj = (*prod)[i];
637+
if (this->cut_(obj)) {
638+
selobjs.push_back(&obj);
639+
if (!this->extvars_.empty() || !this->typedextvars_.empty())
640+
selptrs.emplace_back(prod->ptrAt(i));
641+
}
642+
if (selobjs.size() >= this->maxLen_)
643+
break;
644+
}
645+
}
646+
}
647+
648+
auto out = std::make_unique<nanoaod::FlatTable>(selobjs.size(), this->name_, this->singleton_, this->extension_);
649+
for (const auto &var : this->vars_)
650+
var->fill(selobjs, *out);
651+
for (const auto &var : this->extvars_)
652+
var->fill(iEvent, selptrs, *out);
653+
for (const auto &var : this->typedextvars_)
654+
var->fill(iEvent, selptrs, *out);
655+
656+
// collection variable tables
657+
for (const auto &coltable : this->coltables) {
658+
std::unique_ptr<std::vector<unsigned int>> counts = coltable.colvars[0]->getCounts(selobjs);
659+
// compute size
660+
unsigned int coltablesize = 0;
661+
for (auto const &count : *counts)
662+
coltablesize += count;
663+
// add count branch if requested
664+
if (coltable.useCount)
665+
out->template addColumn<uint16_t>("n" + coltable.name, *counts, "counts for " + coltable.name);
666+
// add offset branch if requested
667+
if (coltable.useOffset) {
668+
unsigned int offset = 0;
669+
std::vector<unsigned int> offsets;
670+
for (auto const &count : *counts) {
671+
offsets.push_back(offset);
672+
offset += count;
673+
}
674+
out->template addColumn<uint16_t>("o" + coltable.name, offsets, "offsets for " + coltable.name);
675+
}
676+
677+
std::unique_ptr<nanoaod::FlatTable> outcoltable = std::make_unique<nanoaod::FlatTable>(coltablesize, coltable.name, false, false);
678+
for (const auto &colvar : coltable.colvars) {
679+
colvar->fill(selobjs, *outcoltable);
680+
}
681+
outcoltable->setDoc(coltable.doc);
682+
iEvent.put(std::move(outcoltable), coltable.name + "Table");
683+
}
684+
685+
// put the main table into the event
686+
out->setDoc(this->doc_);
687+
iEvent.put(std::move(out));
688+
}
689+
690+
protected:
691+
typedef FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<int32_t>>, StringObjectFunction<T>, int32_t> IntVectorVar;
692+
typedef FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<uint32_t>>, StringObjectFunction<T>, uint32_t> UIntVectorVar;
693+
typedef FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<float>>, StringObjectFunction<T>, float> FloatVectorVar;
694+
typedef FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<double>>, StringObjectFunction<T>, double> DoubleVectorVar;
695+
typedef FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<uint8_t>>, StringObjectFunction<T>, uint8_t> UInt8VectorVar;
696+
typedef FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<int16_t>>, StringObjectFunction<T>, int16_t> Int16VectorVar;
697+
typedef FuncCollectionVariable<T, TypedStringObjectMethodCaller<T, std::vector<uint16_t>>, StringObjectFunction<T>, uint16_t> UInt16VectorVar;
698+
699+
struct CollectionVariableTableInfo {
700+
std::string name;
701+
std::string doc;
702+
bool useCount;
703+
bool useOffset;
704+
std::vector<std::unique_ptr<CollectionVariable<T>>> colvars;
705+
};
706+
std::vector<CollectionVariableTableInfo> coltables;
707+
};
708+
489709
template <typename T>
490710
class BXVectorSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, BXVector<T>> {
491711
public:

0 commit comments

Comments
 (0)