File indexing completed on 2025-04-19 09:09:57
0001 #ifndef ATOOLS_Phys_Event_Weights_H
0002 #define ATOOLS_Phys_Event_Weights_H
0003
0004 #include "ATOOLS/Org/My_MPI.H"
0005 #include "ATOOLS/Org/MyStrStream.H"
0006 #include "ATOOLS/Phys/Variations.H"
0007
0008 #include <algorithm>
0009 #include <cassert>
0010 #include <functional>
0011
0012 namespace ATOOLS {
0013
0014 class Weights_Map;
0015
0016 class Weights {
0017
0018 public:
0019
0020 Weights(double w = 1.0) : type {Variations_Type::custom}, weights {w} {};
0021 Weights(Variations_Type t, double w=1.0);
0022
0023 explicit operator double() const { return Nominal(); }
0024
0025
0026 Variations_Type Type() const { return type; }
0027 size_t Size() const { return weights.size(); }
0028 bool HasVariations() const { return weights.size() > 1; }
0029 bool IsZero() const;
0030
0031
0032 std::string Name(size_t, Variations_Source source = Variations_Source::all,
0033 Variations_Name_Type name_type =
0034 Variations_Name_Type::weight_name_convention) const;
0035 double& Nominal();
0036 double Nominal() const;
0037 double& Variation(size_t i);
0038 double& operator[](size_t i) { return weights[i]; }
0039 double operator[](size_t i) const { return weights[i]; }
0040 double& operator[](const std::string& name);
0041
0042
0043 Weights& operator=(double);
0044
0045
0046 Weights& operator*=(double);
0047 friend Weights operator*(Weights, double);
0048 Weights& operator/=(double rhs) { return operator*=(1.0 / rhs); }
0049 friend Weights operator/(Weights, double);
0050
0051
0052
0053
0054 Weights& operator*=(const Weights&);
0055 friend Weights operator*(Weights, Weights);
0056
0057
0058
0059
0060
0061
0062
0063 template <class T> Weights& operator*=(const std::vector<T>&);
0064
0065
0066
0067
0068 Weights& operator+=(const Weights&);
0069 friend Weights operator+(Weights, Weights);
0070 Weights& operator-=(const Weights&);
0071 friend Weights operator-(Weights, Weights);
0072
0073
0074 Weights operator-() const;
0075
0076
0077
0078
0079
0080
0081
0082
0083 friend void Reweight(
0084 Weights&,
0085 std::function<double(double, QCD_Variation_Params&)>);
0086 friend void Reweight(
0087 Weights&,
0088 std::function<double(double, size_t varindex, QCD_Variation_Params&)>);
0089 friend void ReweightAll(
0090 Weights&,
0091 std::function<double(double, size_t varindex, QCD_Variation_Params*)>);
0092
0093
0094 friend void Reweight(
0095 Weights&,
0096 std::function<double(double, Qcut_Variation_Params&)>);
0097 friend void Reweight(
0098 Weights&,
0099 std::function<double(double, size_t varindex, Qcut_Variation_Params&)>);
0100 friend void ReweightAll(
0101 Weights&,
0102 std::function<double(double, size_t varindex, Qcut_Variation_Params*)>);
0103
0104 friend std::ostream& operator<<(std::ostream&, const Weights&);
0105
0106 friend Weights_Map;
0107
0108 private:
0109
0110
0111 bool IsUnnamedScalar() const;
0112
0113 Variations_Type type;
0114 std::vector<double> weights;
0115 std::vector<std::string> names;
0116 };
0117
0118 class Weights_Map : public std::map<std::string, Weights> {
0119
0120 public:
0121
0122 Weights_Map(double w=1.0) : base_weight{w} {};
0123
0124 explicit operator double() const { return Nominal(); }
0125
0126
0127
0128
0129 void Clear();
0130
0131
0132 double Get(const std::string&, size_t) const;
0133 bool HasVariations() const;
0134 bool IsZero() const;
0135 double BaseWeight() const { return base_weight; }
0136
0137
0138
0139
0140
0141 template <typename T>
0142 void FillVariations(
0143 T &, Variations_Source source = ATOOLS::Variations_Source::all,
0144 Variations_Name_Type name_type =
0145 ATOOLS::Variations_Name_Type::weight_name_convention) const;
0146
0147
0148
0149 double Nominal() const;
0150 double Nominal(const std::string& k) const;
0151 double NominalIgnoringVariationType(Variations_Type) const;
0152
0153
0154 Weights& RelativeValues(const std::string& k) { return (*this)[k]; }
0155 Weights RelativeValues(const std::string& k) const;
0156
0157
0158
0159
0160
0161 Weights Combine(Variations_Type type) const;
0162
0163
0164
0165
0166 void SetZeroIfCloseToZero(double tolerance);
0167
0168
0169 Weights_Map& operator=(double w) { base_weight = w; return *this; }
0170
0171
0172 Weights_Map& operator*=(double w) { base_weight *= w; return *this; }
0173 friend Weights_Map operator*(Weights_Map, double);
0174 Weights_Map& operator/=(double w) { base_weight /= w; return *this; }
0175 friend Weights_Map operator/(Weights_Map, double);
0176
0177
0178
0179
0180
0181
0182
0183 Weights_Map& operator*=(const Weights_Map&);
0184 friend Weights_Map operator*(Weights_Map, const Weights_Map&);
0185
0186
0187
0188 Weights_Map& operator+=(const Weights_Map&);
0189 Weights_Map& operator-=(const Weights_Map&);
0190 friend Weights_Map operator+(Weights_Map, const Weights_Map&);
0191 friend Weights_Map operator-(Weights_Map, const Weights_Map&);
0192
0193 friend Weights_Map sqrt(const Weights_Map&);
0194
0195 friend std::ostream& operator<<(std::ostream&, const Weights_Map&);
0196
0197
0198
0199
0200 void MakeRelative();
0201 void MakeAbsolute();
0202
0203 #ifdef USING__MPI
0204
0205
0206
0207
0208 void MPI_Allreduce();
0209 #endif
0210
0211 private:
0212
0213
0214 using std::map<std::string, Weights>::clear;
0215
0216
0217 double NominalIgnoringPrefactor() const;
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 double base_weight;
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237 double nominals_prefactor {1.0};
0238
0239 bool is_absolute {false};
0240 };
0241
0242 template <class T> Weights& Weights::operator*=(const std::vector<T>& rhs)
0243 {
0244 const auto size = weights.size();
0245
0246 assert(rhs.size() == 1 || weights.size() == 1 ||
0247 weights.size() == rhs.size());
0248 if (size == 1) {
0249
0250 assert(type != Variations_Type::custom);
0251 assert(type == Variations_Type::qcd
0252 ? rhs.size() == s_variations->Size(Variations_Type::qcd) + 1
0253 : true);
0254 assert(type == Variations_Type::qcut
0255 ? rhs.size() == s_variations->Size(Variations_Type::qcut) + 1
0256 : true);
0257 const auto weight = Nominal();
0258 weights.clear();
0259 weights.reserve(rhs.size());
0260 std::copy(rhs.begin(), rhs.end(), std::back_inserter(weights));
0261 (*this) *= weight;
0262 } else if (rhs.size() > 1) {
0263
0264 for (int i {0}; i < weights.size(); ++i) {
0265 weights[i] *= rhs[i];
0266 }
0267 } else {
0268
0269 (*this) *= rhs[0];
0270 }
0271 return *this;
0272 }
0273
0274 Weights operator*(Weights, double);
0275 Weights operator/(Weights, double);
0276 Weights operator*(Weights, Weights);
0277 Weights operator+(Weights, Weights);
0278 Weights operator-(Weights, Weights);
0279
0280 std::ostream& operator<<(std::ostream&, const Weights&);
0281
0282 void Reweight(
0283 Weights&,
0284 std::function<double(double, QCD_Variation_Params&)>);
0285 void Reweight(
0286 Weights&,
0287 std::function<double(double, size_t varindex, QCD_Variation_Params&)>);
0288 void ReweightAll(
0289 Weights&,
0290 std::function<double(double, size_t varindex, QCD_Variation_Params*)>);
0291 void Reweight(
0292 Weights&,
0293 std::function<double(double, Qcut_Variation_Params&)>);
0294 void Reweight(
0295 Weights&,
0296 std::function<double(double, size_t varindex, Qcut_Variation_Params&)>);
0297 void ReweightAll(
0298 Weights&,
0299 std::function<double(double, size_t varindex, Qcut_Variation_Params*)>);
0300
0301 template <typename T>
0302 void Weights_Map::FillVariations(T &map, Variations_Source source,
0303 Variations_Name_Type name_type) const {
0304 DEBUG_FUNC(source);
0305
0306
0307
0308
0309 for (const auto type : s_variations->ManagedVariationTypes()) {
0310
0311 Weights weights = Weights {type};
0312 double relfac {1.0};
0313 if (source == Variations_Source::all) {
0314 weights *= Combine(type);
0315 relfac = NominalIgnoringVariationType(type);
0316 } else {
0317
0318 static const std::unordered_set<std::string> shower_keys {
0319 "PS", "PS_QCUT", "MC@NLO_PS", "MC@NLO_QCUT"};
0320 for (const auto& v : *this) {
0321 if (shower_keys.find(v.first) != shower_keys.end())
0322 continue;
0323 if (v.second.Type() == type) {
0324 weights *= v.second;
0325 } else {
0326 relfac *= v.second.Nominal();
0327 }
0328 }
0329 relfac *= base_weight;
0330 }
0331
0332 size_t num_vars = weights.Size() - 1;
0333 for (size_t i(0); i < num_vars; ++i) {
0334 const std::string varname {weights.Name(i + 1, source, name_type)};
0335 map[varname] = weights.Variation(i) * relfac;
0336 msg_Debugging() << varname << " (" << varname
0337 << "): " << weights.Variation(i) * relfac << '\n';
0338 }
0339 }
0340
0341
0342
0343
0344 if (source == Variations_Source::all) {
0345 for (const auto& kv : *this) {
0346 if (kv.second.Type() != Variations_Type::custom)
0347 continue;
0348 const auto size = kv.second.Size();
0349
0350 for (size_t i {1}; i < size; ++i) {
0351 map[kv.first + "." + kv.second.Name(i)] =
0352 Nominal() / kv.second.Nominal() * kv.second[i];
0353 }
0354 }
0355 }
0356 }
0357
0358 std::ostream& operator<<(std::ostream& out, const Weights_Map& w);
0359 Weights_Map operator+(Weights_Map lhs, const Weights_Map& rhs);
0360 Weights_Map operator-(Weights_Map lhs, const Weights_Map& rhs);
0361 Weights_Map operator*(Weights_Map lhs, const Weights_Map& rhs);
0362 Weights_Map operator*(Weights_Map lhs, double rhs);
0363 Weights_Map operator/(Weights_Map lhs, const Weights_Map& rhs);
0364 Weights_Map operator/(Weights_Map lhs, double rhs);
0365
0366 }
0367
0368 #endif