File indexing completed on 2024-04-06 12:04:49
0001 #ifndef DataFormats_NanoAOD_MergeableCounterTable_h
0002 #define DataFormats_NanoAOD_MergeableCounterTable_h
0003
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 #include <vector>
0006 #include <string>
0007 #include <algorithm>
0008
0009 namespace nanoaod {
0010
0011 class MergeableCounterTable {
0012 public:
0013 MergeableCounterTable() {}
0014 typedef long long int_accumulator;
0015 typedef double float_accumulator;
0016
0017 template <typename T>
0018 struct SingleColumn {
0019 typedef T value_type;
0020 SingleColumn() {}
0021 SingleColumn(const std::string& aname, const std::string& adoc, T avalue = T())
0022 : name(aname), doc(adoc), value(avalue) {}
0023 std::string name, doc;
0024 T value;
0025 void operator+=(const SingleColumn<T>& other) {
0026 if (!compatible(other))
0027 throw cms::Exception("LogicError",
0028 "Trying to merge " + name + " with " + other.name + " failed compatibility test.\n");
0029 value += other.value;
0030 }
0031 bool compatible(const SingleColumn<T>& other) {
0032 return name == other.name;
0033 }
0034 };
0035 typedef SingleColumn<float_accumulator> FloatColumn;
0036 typedef SingleColumn<int_accumulator> IntColumn;
0037
0038 template <typename T>
0039 struct SingleWithNormColumn : SingleColumn<T> {
0040 SingleWithNormColumn() { norm = 0; }
0041 SingleWithNormColumn(const std::string& aname, const std::string& adoc, T avalue = T(), const double anorm = 0)
0042 : SingleColumn<T>(aname, adoc, avalue), norm(anorm) {}
0043 double norm;
0044 void operator+=(const SingleWithNormColumn<T>& other) {
0045 if (!this->compatible(other))
0046 throw cms::Exception(
0047 "LogicError", "Trying to merge " + this->name + " with " + other.name + " failed compatibility test.\n");
0048 auto newNorm = norm + other.norm;
0049 this->value = (newNorm != 0) ? (this->value * norm + other.value * other.norm) / newNorm : 0;
0050 norm = newNorm;
0051 }
0052 };
0053 typedef SingleWithNormColumn<float_accumulator> FloatWithNormColumn;
0054
0055 template <typename T>
0056 struct VectorColumn {
0057 typedef T element_type;
0058 VectorColumn() {}
0059 VectorColumn(const std::string& aname, const std::string& adoc, unsigned int size)
0060 : name(aname), doc(adoc), values(size, T()) {}
0061 VectorColumn(const std::string& aname, const std::string& adoc, const std::vector<T>& somevalues)
0062 : name(aname), doc(adoc), values(somevalues) {}
0063 std::string name, doc;
0064 std::vector<T> values;
0065 void operator+=(const VectorColumn<T>& other) {
0066 if (!compatible(other))
0067 throw cms::Exception("LogicError",
0068 "Trying to merge " + name + " with " + other.name + " failed compatibility test.\n");
0069 for (unsigned int i = 0, n = values.size(); i < n; ++i) {
0070 values[i] += other.values[i];
0071 }
0072 }
0073 bool compatible(const VectorColumn<T>& other) {
0074 return name == other.name && values.size() == other.values.size();
0075 }
0076 };
0077 typedef VectorColumn<float_accumulator> VFloatColumn;
0078 typedef VectorColumn<int_accumulator> VIntColumn;
0079
0080 template <typename T>
0081 struct VectorWithNormColumn : VectorColumn<T> {
0082 double norm;
0083 VectorWithNormColumn() { norm = 0; }
0084 VectorWithNormColumn(const std::string& aname, const std::string& adoc, unsigned int size, double anorm = 0)
0085 : VectorColumn<T>(aname, adoc, size), norm(anorm) {}
0086 VectorWithNormColumn(const std::string& aname,
0087 const std::string& adoc,
0088 const std::vector<T>& somevalues,
0089 double anorm = 0)
0090 : VectorColumn<T>(aname, adoc, somevalues), norm(anorm) {}
0091 void operator+=(const VectorWithNormColumn<T>& other) {
0092 if (!this->compatible(other))
0093 throw cms::Exception(
0094 "LogicError", "Trying to merge " + this->name + " with " + other.name + " failed compatibility test.\n");
0095 auto newNorm = norm + other.norm;
0096 for (unsigned int i = 0, n = this->values.size(); i < n; ++i) {
0097 this->values[i] =
0098 (newNorm != 0) ? (this->values[i] * norm + other.values[i] * other.norm) / (norm + other.norm) : 0;
0099 }
0100 norm = newNorm;
0101 }
0102 };
0103 typedef VectorWithNormColumn<float_accumulator> VFloatWithNormColumn;
0104
0105 const std::vector<FloatColumn>& floatCols() const { return floatCols_; }
0106 const std::vector<VFloatColumn>& vfloatCols() const { return vfloatCols_; }
0107 const std::vector<FloatWithNormColumn>& floatWithNormCols() const { return floatWithNormCols_; }
0108 const std::vector<VFloatWithNormColumn>& vfloatWithNormCols() const { return vfloatWithNormCols_; }
0109 const std::vector<IntColumn>& intCols() const { return intCols_; }
0110 const std::vector<VIntColumn>& vintCols() const { return vintCols_; }
0111
0112 template <typename F>
0113 void addFloat(const std::string& name, const std::string& doc, F value) {
0114 floatCols_.push_back(FloatColumn(name, doc, value));
0115 }
0116
0117 template <typename F>
0118 void addFloatWithNorm(const std::string& name, const std::string& doc, F value, double norm) {
0119 floatWithNormCols_.push_back(FloatWithNormColumn(name, doc, value, norm));
0120 }
0121
0122 template <typename I>
0123 void addInt(const std::string& name, const std::string& doc, I value) {
0124 intCols_.push_back(IntColumn(name, doc, value));
0125 }
0126
0127 template <typename F>
0128 void addVFloat(const std::string& name, const std::string& doc, const std::vector<F> values) {
0129 vfloatCols_.push_back(VFloatColumn(name, doc, values.size()));
0130 std::copy(values.begin(), values.end(), vfloatCols_.back().values.begin());
0131 }
0132
0133 template <typename F>
0134 void addVFloatWithNorm(const std::string& name, const std::string& doc, const std::vector<F> values, double norm) {
0135 vfloatWithNormCols_.push_back(VFloatWithNormColumn(name, doc, values.size(), norm));
0136 std::copy(values.begin(), values.end(), vfloatWithNormCols_.back().values.begin());
0137 }
0138
0139 template <typename I>
0140 void addVInt(const std::string& name, const std::string& doc, const std::vector<I> values) {
0141 vintCols_.push_back(VIntColumn(name, doc, values.size()));
0142 std::copy(values.begin(), values.end(), vintCols_.back().values.begin());
0143 }
0144
0145 bool mergeProduct(const MergeableCounterTable& other) {
0146 if (!tryMerge(intCols_, other.intCols_))
0147 return false;
0148 if (!tryMerge(vintCols_, other.vintCols_))
0149 return false;
0150 if (!tryMerge(floatCols_, other.floatCols_))
0151 return false;
0152 if (!tryMerge(vfloatCols_, other.vfloatCols_))
0153 return false;
0154 if (!tryMerge(floatWithNormCols_, other.floatWithNormCols_))
0155 return false;
0156 if (!tryMerge(vfloatWithNormCols_, other.vfloatWithNormCols_))
0157 return false;
0158 return true;
0159 }
0160
0161 void swap(MergeableCounterTable& iOther) {
0162 floatCols_.swap(iOther.floatCols_);
0163 vfloatCols_.swap(iOther.vfloatCols_);
0164 floatWithNormCols_.swap(iOther.floatWithNormCols_);
0165 vfloatWithNormCols_.swap(iOther.vfloatWithNormCols_);
0166 intCols_.swap(iOther.intCols_);
0167 vintCols_.swap(iOther.vintCols_);
0168 }
0169
0170 private:
0171 std::vector<FloatColumn> floatCols_;
0172 std::vector<VFloatColumn> vfloatCols_;
0173 std::vector<FloatWithNormColumn> floatWithNormCols_;
0174 std::vector<VFloatWithNormColumn> vfloatWithNormCols_;
0175 std::vector<IntColumn> intCols_;
0176 std::vector<VIntColumn> vintCols_;
0177
0178 template <typename T>
0179 bool tryMerge(std::vector<T>& one, const std::vector<T>& two) {
0180 for (auto y : two) {
0181 auto x = std::find_if(one.begin(), one.end(), [&y](const T& x) { return x.name == y.name; });
0182 if (x == one.end())
0183 one.push_back(y);
0184 else
0185 (*x) += y;
0186 }
0187 return true;
0188 }
0189 };
0190
0191 }
0192
0193 #endif