|
14 | 14 |
|
15 | 15 | #include "CommonTools/Utils/interface/StringCutObjectSelector.h" |
16 | 16 | #include "CommonTools/Utils/interface/StringObjectFunction.h" |
| 17 | +#include "CommonTools/Utils/interface/TypedStringObjectMethodCaller.h" |
17 | 18 |
|
18 | 19 | #include <memory> |
19 | 20 | #include <vector> |
@@ -73,6 +74,55 @@ class FuncVariable : public Variable<ObjType> { |
73 | 74 | StringFunctor precisionFunc_; |
74 | 75 | }; |
75 | 76 |
|
| 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 | + |
76 | 126 | // External variables: i.e. variables that are not member or methods of the object |
77 | 127 | template <typename ObjType> |
78 | 128 | class ExtVariable : public VariableBase { |
@@ -486,6 +536,176 @@ class SimpleTypedExternalFlatTableProducer : public SimpleFlatTableProducer<T> { |
486 | 536 | typedef TypedValueMapVariable<T, V, StringObjectFunction<V>, uint16_t> UInt16TypedExtVar; |
487 | 537 | }; |
488 | 538 |
|
| 539 | +template <typename T> |
| 540 | +class SimpleCollectionFlatTableProducer : public SimpleFlatTableProducer<T> { |
| 541 | +public: |
| 542 | + SimpleCollectionFlatTableProducer(edm::ParameterSet const ¶ms) : 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 | + |
489 | 709 | template <typename T> |
490 | 710 | class BXVectorSimpleFlatTableProducer : public SimpleFlatTableProducerBase<T, BXVector<T>> { |
491 | 711 | public: |
|
0 commit comments