Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:39:36

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       Int8,
0042       UInt8,
0043       Int16,
0044       UInt16,
0045       Int32,
0046       UInt32,
0047       Bool,
0048       Float,
0049       Double,
0050     };  // We could have other Float types with reduced mantissa, and similar
0051 
0052     FlatTable() : size_(0) {}
0053     FlatTable(unsigned int size, const std::string &name, bool singleton, bool extension = false)
0054         : size_(size), name_(name), singleton_(singleton), extension_(extension) {}
0055     ~FlatTable() {}
0056 
0057     unsigned int nColumns() const { return columns_.size(); };
0058     unsigned int nRows() const { return size_; };
0059     unsigned int size() const { return size_; }
0060     bool singleton() const { return singleton_; }
0061     bool extension() const { return extension_; }
0062     const std::string &name() const { return name_; }
0063 
0064     const std::string &columnName(unsigned int col) const { return columns_[col].name; }
0065     int columnIndex(const std::string &name) const;
0066 
0067     ColumnType columnType(unsigned int col) const { return columns_[col].type; }
0068 
0069     void setDoc(const std::string &doc) { doc_ = doc; }
0070     const std::string &doc() const { return doc_; }
0071     const std::string &columnDoc(unsigned int col) const { return columns_[col].doc; }
0072 
0073     /// get a column by index (const)
0074     template <typename T>
0075     auto columnData(unsigned int column) const {
0076       auto begin = beginData<T>(column);
0077       return edm::Span(begin, begin + size_);
0078     }
0079 
0080     /// get a column by index (non-const)
0081     template <typename T>
0082     auto columnData(unsigned int column) {
0083       auto begin = beginData<T>(column);
0084       return edm::Span(begin, begin + size_);
0085     }
0086 
0087     /// get a column value for singleton (const)
0088     template <typename T>
0089     const auto &columValue(unsigned int column) const {
0090       if (!singleton())
0091         throw cms::Exception("LogicError", "columnValue works only for singleton tables");
0092       return *beginData<T>(column);
0093     }
0094 
0095     double getAnyValue(unsigned int row, unsigned int column) const;
0096 
0097     class RowView {
0098     public:
0099       RowView() {}
0100       RowView(const FlatTable &table, unsigned int row) : table_(&table), row_(row) {}
0101       double getAnyValue(unsigned int column) const { return table_->getAnyValue(row_, column); }
0102       double getAnyValue(const std::string &column) const {
0103         return table_->getAnyValue(row_, table_->columnIndex(column));
0104       }
0105       const FlatTable &table() const { return *table_; }
0106       unsigned int row() const { return row_; }
0107 
0108     private:
0109       const FlatTable *table_;
0110       unsigned int row_;
0111     };
0112     RowView row(unsigned int row) const { return RowView(*this, row); }
0113 
0114     template <typename T, typename C>
0115     void addColumn(const std::string &name, const C &values, const std::string &docString, int mantissaBits = -1) {
0116       if (columnIndex(name) != -1)
0117         throw cms::Exception("LogicError", "Duplicated column: " + name);
0118       if (values.size() != size())
0119         throw cms::Exception("LogicError", "Mismatched size for " + name);
0120       auto &vec = bigVector<T>();
0121       columns_.emplace_back(name, docString, defaultColumnType<T>(), vec.size());
0122       vec.insert(vec.end(), values.begin(), values.end());
0123       flatTableHelper::MaybeMantissaReduce<T>(mantissaBits).bulk(columnData<T>(columns_.size() - 1));
0124     }
0125 
0126     template <typename T, typename C>
0127     void addColumnValue(const std::string &name, const C &value, const std::string &docString, int mantissaBits = -1) {
0128       if (!singleton())
0129         throw cms::Exception("LogicError", "addColumnValue works only for singleton tables");
0130       if (columnIndex(name) != -1)
0131         throw cms::Exception("LogicError", "Duplicated column: " + name);
0132       auto &vec = bigVector<T>();
0133       columns_.emplace_back(name, docString, defaultColumnType<T>(), vec.size());
0134       vec.push_back(flatTableHelper::MaybeMantissaReduce<T>(mantissaBits).one(value));
0135     }
0136 
0137     void addExtension(const FlatTable &extension);
0138 
0139     template <class T>
0140     struct dependent_false : std::false_type {};
0141     template <typename T>
0142     static ColumnType defaultColumnType() {
0143       if constexpr (std::is_same<T, int8_t>())
0144         return ColumnType::Int8;
0145       else if constexpr (std::is_same<T, uint8_t>())
0146         return ColumnType::UInt8;
0147       else if constexpr (std::is_same<T, int16_t>())
0148         return ColumnType::Int16;
0149       else if constexpr (std::is_same<T, uint16_t>())
0150         return ColumnType::UInt16;
0151       else if constexpr (std::is_same<T, int32_t>())
0152         return ColumnType::Int32;
0153       else if constexpr (std::is_same<T, uint32_t>())
0154         return ColumnType::UInt32;
0155       else if constexpr (std::is_same<T, bool>())
0156         return ColumnType::Bool;
0157       else if constexpr (std::is_same<T, float>())
0158         return ColumnType::Float;
0159       else if constexpr (std::is_same<T, double>())
0160         return ColumnType::Double;
0161       else
0162         static_assert(dependent_false<T>::value, "unsupported type");
0163     }
0164 
0165     // this below needs to be public for ROOT, but it is to be considered private otherwise
0166     struct Column {
0167       std::string name, doc;
0168       ColumnType type;
0169       unsigned int firstIndex;
0170       Column() {}  // for ROOT
0171       Column(const std::string &aname, const std::string &docString, ColumnType atype, unsigned int anIndex)
0172           : name(aname), doc(docString), type(atype), firstIndex(anIndex) {}
0173     };
0174 
0175   private:
0176     template <typename T>
0177     auto beginData(unsigned int column) const {
0178       return bigVector<T>().cbegin() + columns_[column].firstIndex;
0179     }
0180     template <typename T>
0181     auto beginData(unsigned int column) {
0182       return bigVector<T>().begin() + columns_[column].firstIndex;
0183     }
0184 
0185     template <typename T>
0186     auto const &bigVector() const {
0187       return bigVectorImpl<T>(*this);
0188     }
0189     template <typename T>
0190     auto &bigVector() {
0191       return bigVectorImpl<T>(*this);
0192     }
0193 
0194     template <typename T, class This>
0195     static auto &bigVectorImpl(This &table) {
0196       // helper function to avoid code duplication, for the two accessor functions that differ only in const-ness
0197       if constexpr (std::is_same<T, int8_t>())
0198         return table.int8s_;
0199       else if constexpr (std::is_same<T, uint8_t>())
0200         return table.uint8s_;
0201       else if constexpr (std::is_same<T, int16_t>())
0202         return table.int16s_;
0203       else if constexpr (std::is_same<T, uint16_t>())
0204         return table.uint16s_;
0205       else if constexpr (std::is_same<T, int32_t>())
0206         return table.int32s_;
0207       else if constexpr (std::is_same<T, uint32_t>())
0208         return table.uint32s_;
0209       else if constexpr (std::is_same<T, bool>())
0210         return table.uint8s_;  // special case: bool stored as vector of uint8
0211       else if constexpr (std::is_same<T, float>())
0212         return table.floats_;
0213       else if constexpr (std::is_same<T, double>())
0214         return table.doubles_;
0215       else
0216         static_assert(dependent_false<T>::value, "unsupported type");
0217     }
0218 
0219     unsigned int size_;
0220     std::string name_, doc_;
0221     bool singleton_, extension_;
0222     std::vector<Column> columns_;
0223     std::vector<int8_t> int8s_;
0224     std::vector<uint8_t> uint8s_;
0225     std::vector<int16_t> int16s_;
0226     std::vector<uint16_t> uint16s_;
0227     std::vector<int32_t> int32s_;
0228     std::vector<uint32_t> uint32s_;
0229     std::vector<float> floats_;
0230     std::vector<double> doubles_;
0231   };
0232 
0233 }  // namespace nanoaod
0234 
0235 #endif