Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-02-12 09:07:27

0001 #ifndef DataFormats_NanoAOD_FlatTable_h
0002 #define DataFormats_NanoAOD_FlatTable_h
0003 
0004 #include "DataFormats/Math/interface/libminifloat.h"
0005 #include "FWCore/Utilities/interface/Exception.h"
0006 #include "FWCore/Utilities/interface/Span.h"
0007 
0008 #include <cstdint>
0009 #include <vector>
0010 #include <string>
0011 #include <type_traits>
0012 
0013 namespace nanoaod {
0014 
0015   namespace flatTableHelper {
0016     template <typename T>
0017     struct MaybeMantissaReduce {
0018       MaybeMantissaReduce(int mantissaBits) {}
0019       inline T one(const T &val) const { return val; }
0020       template <typename Span>
0021       inline void bulk(Span const &data) const {}
0022     };
0023     template <>
0024     struct MaybeMantissaReduce<float> {
0025       int bits_;
0026       MaybeMantissaReduce(int mantissaBits) : bits_(mantissaBits) {}
0027       inline float one(const float &val) const {
0028         return (bits_ > 0 ? MiniFloatConverter::reduceMantissaToNbitsRounding(val, bits_) : val);
0029       }
0030       template <typename Span>
0031       inline void bulk(Span &&data) const {
0032         if (bits_ > 0)
0033           MiniFloatConverter::reduceMantissaToNbitsRounding(bits_, data.begin(), data.end(), data.begin());
0034       }
0035     };
0036   }  // namespace flatTableHelper
0037 
0038   class FlatTable {
0039   public:
0040     enum class ColumnType {
0041       Float,
0042       Int,
0043       UInt8,
0044       Bool,
0045       UInt32,
0046       Double,
0047       Int8
0048     };  // We could have other Float types with reduced mantissa, and similar
0049 
0050     FlatTable() : size_(0) {}
0051     FlatTable(unsigned int size, const std::string &name, bool singleton, bool extension = false)
0052         : size_(size), name_(name), singleton_(singleton), extension_(extension) {}
0053     ~FlatTable() {}
0054 
0055     unsigned int nColumns() const { return columns_.size(); };
0056     unsigned int nRows() const { return size_; };
0057     unsigned int size() const { return size_; }
0058     bool singleton() const { return singleton_; }
0059     bool extension() const { return extension_; }
0060     const std::string &name() const { return name_; }
0061 
0062     const std::string &columnName(unsigned int col) const { return columns_[col].name; }
0063     int columnIndex(const std::string &name) const;
0064 
0065     ColumnType columnType(unsigned int col) const { return columns_[col].type; }
0066 
0067     void setDoc(const std::string &doc) { doc_ = doc; }
0068     const std::string &doc() const { return doc_; }
0069     const std::string &columnDoc(unsigned int col) const { return columns_[col].doc; }
0070 
0071     /// get a column by index (const)
0072     template <typename T>
0073     auto columnData(unsigned int column) const {
0074       auto begin = beginData<T>(column);
0075       return edm::Span(begin, begin + size_);
0076     }
0077 
0078     /// get a column by index (non-const)
0079     template <typename T>
0080     auto columnData(unsigned int column) {
0081       auto begin = beginData<T>(column);
0082       return edm::Span(begin, begin + size_);
0083     }
0084 
0085     /// get a column value for singleton (const)
0086     template <typename T>
0087     const auto &columValue(unsigned int column) const {
0088       if (!singleton())
0089         throw cms::Exception("LogicError", "columnValue works only for singleton tables");
0090       return *beginData<T>(column);
0091     }
0092 
0093     double getAnyValue(unsigned int row, unsigned int column) const;
0094 
0095     class RowView {
0096     public:
0097       RowView() {}
0098       RowView(const FlatTable &table, unsigned int row) : table_(&table), row_(row) {}
0099       double getAnyValue(unsigned int column) const { return table_->getAnyValue(row_, column); }
0100       double getAnyValue(const std::string &column) const {
0101         return table_->getAnyValue(row_, table_->columnIndex(column));
0102       }
0103       const FlatTable &table() const { return *table_; }
0104       unsigned int row() const { return row_; }
0105 
0106     private:
0107       const FlatTable *table_;
0108       unsigned int row_;
0109     };
0110     RowView row(unsigned int row) const { return RowView(*this, row); }
0111 
0112     template <typename T, typename C>
0113     void addColumn(const std::string &name, const C &values, const std::string &docString, int mantissaBits = -1) {
0114       if (columnIndex(name) != -1)
0115         throw cms::Exception("LogicError", "Duplicated column: " + name);
0116       if (values.size() != size())
0117         throw cms::Exception("LogicError", "Mismatched size for " + name);
0118       auto &vec = bigVector<T>();
0119       columns_.emplace_back(name, docString, defaultColumnType<T>(), vec.size());
0120       vec.insert(vec.end(), values.begin(), values.end());
0121       flatTableHelper::MaybeMantissaReduce<T>(mantissaBits).bulk(columnData<T>(columns_.size() - 1));
0122     }
0123 
0124     template <typename T, typename C>
0125     void addColumnValue(const std::string &name, const C &value, const std::string &docString, int mantissaBits = -1) {
0126       if (!singleton())
0127         throw cms::Exception("LogicError", "addColumnValue works only for singleton tables");
0128       if (columnIndex(name) != -1)
0129         throw cms::Exception("LogicError", "Duplicated column: " + name);
0130       auto &vec = bigVector<T>();
0131       columns_.emplace_back(name, docString, defaultColumnType<T>(), vec.size());
0132       vec.push_back(flatTableHelper::MaybeMantissaReduce<T>(mantissaBits).one(value));
0133     }
0134 
0135     void addExtension(const FlatTable &extension);
0136 
0137     template <class T>
0138     struct dependent_false : std::false_type {};
0139     template <typename T>
0140     static ColumnType defaultColumnType() {
0141       if constexpr (std::is_same<T, float>())
0142         return ColumnType::Float;
0143       else if constexpr (std::is_same<T, int>())
0144         return ColumnType::Int;
0145       else if constexpr (std::is_same<T, uint8_t>())
0146         return ColumnType::UInt8;
0147       else if constexpr (std::is_same<T, int8_t>())
0148         return ColumnType::Int8;
0149       else if constexpr (std::is_same<T, bool>())
0150         return ColumnType::Bool;
0151       else if constexpr (std::is_same<T, uint32_t>())
0152         return ColumnType::UInt32;
0153       else if constexpr (std::is_same<T, double>())
0154         return ColumnType::Double;
0155       else
0156         static_assert(dependent_false<T>::value, "unsupported type");
0157     }
0158 
0159     // this below needs to be public for ROOT, but it is to be considered private otherwise
0160     struct Column {
0161       std::string name, doc;
0162       ColumnType type;
0163       unsigned int firstIndex;
0164       Column() {}  // for ROOT
0165       Column(const std::string &aname, const std::string &docString, ColumnType atype, unsigned int anIndex)
0166           : name(aname), doc(docString), type(atype), firstIndex(anIndex) {}
0167     };
0168 
0169   private:
0170     template <typename T>
0171     auto beginData(unsigned int column) const {
0172       return bigVector<T>().cbegin() + columns_[column].firstIndex;
0173     }
0174     template <typename T>
0175     auto beginData(unsigned int column) {
0176       return bigVector<T>().begin() + columns_[column].firstIndex;
0177     }
0178 
0179     template <typename T>
0180     auto const &bigVector() const {
0181       return bigVectorImpl<T>(*this);
0182     }
0183     template <typename T>
0184     auto &bigVector() {
0185       return bigVectorImpl<T>(*this);
0186     }
0187 
0188     template <typename T, class This>
0189     static auto &bigVectorImpl(This &table) {
0190       // helper function to avoid code duplication, for the two accessor functions that differ only in const-ness
0191       if constexpr (std::is_same<T, float>())
0192         return table.floats_;
0193       else if constexpr (std::is_same<T, int>())
0194         return table.ints_;
0195       else if constexpr (std::is_same<T, uint8_t>())
0196         return table.uint8s_;
0197       else if constexpr (std::is_same<T, int8_t>())
0198         return table.int8s_;
0199       else if constexpr (std::is_same<T, bool>())
0200         return table.uint8s_;
0201       else if constexpr (std::is_same<T, uint32_t>())
0202         return table.uint32s_;
0203       else if constexpr (std::is_same<T, double>())
0204         return table.doubles_;
0205       else
0206         static_assert(dependent_false<T>::value, "unsupported type");
0207     }
0208 
0209     unsigned int size_;
0210     std::string name_, doc_;
0211     bool singleton_, extension_;
0212     std::vector<Column> columns_;
0213     std::vector<float> floats_;
0214     std::vector<int> ints_;
0215     std::vector<uint8_t> uint8s_;
0216     std::vector<int8_t> int8s_;
0217     std::vector<uint32_t> uint32s_;
0218     std::vector<double> doubles_;
0219   };
0220 
0221 }  // namespace nanoaod
0222 
0223 #endif