2#ifndef RIVET_CENTRALITYBINNER_HH
3#define RIVET_CENTRALITYBINNER_HH
4#include "Rivet/Config/RivetCommon.hh"
5#include "Rivet/Projections/HepMCHeavyIon.hh"
6#include "Rivet/Tools/RivetYODA.hh"
53 if (imp < 0.0)
return;
54 _estimate = imp > 0.0 ? 1.0 / imp : numeric_limits<double>::max();
82 struct CentralityBinTraits {
85 static T clone(
const T& t) {
86 return T(t->newclone());
90 static void add(T& t,
const T& o) {
95 static void scale(T& t,
double f) {
101 static void normalize(T& t,
double sumw) {
102 if (t->sumW() > 0.0) t->normalize(t->sumW() / sumw);
106 static string path(T t) {
114 struct MergeDistance {
125 static double dist(
double cestLo,
double cestHi,
double weight,
double clo,
double chi,
double,
double) {
126 return (cestHi - cestLo) * weight / (cestHi * (chi - clo));
138 template <
typename T = Histo1DPtr,
typename MDist = MergeDistance>
147 : _currentCEst(-1.0), _maxBins(maxbins), _warnlimit(wlim), _weightsum(0.0) {
148 _percentiles.insert(0.0);
149 _percentiles.insert(1.0);
160 virtual std::string
name()
const {
161 return "Rivet::CentralityBinner";
176 void add(T t,
double cmin,
double cmax,
double cestmin = -1.0,
double cestmax = -1.0) {
177 _percentiles.insert(
max(1.0 - cmax / 100.0, 0.0));
178 _percentiles.insert(
min(1.0 - cmin / 100.0, 1.0));
179 if (_unfilled.empty() && _ready.empty()) _devnull = CentralityBinTraits<T>::clone(t);
181 _unfilled.push_back(Bin(t, 1.0 - cmax / 100.0, 1.0 - cmin / 100.0));
183 _ready[t] = Bin(t, 1.0 - cmax / 100.0, 1.0 - cmin / 100.0, cestmin, cestmax);
195 return select(applyProjection<CentralityEstimator>(event, _estimator).estimate(), weight);
204 T
select(
double cest,
double weight = 1.0);
217 for (
auto& b : _ready) b.second.normalizePerEvent();
223 map<double, double> ret;
224 for (
auto& b : _ready) {
225 ret[1.0 - b.second._centLo] = b.second._cestLo;
226 ret[1.0 - b.second._centHi] = b.second._cestHi;
242 vector<T> allObjects() {
244 for (
auto& fb : _flexiBins) ret.push_back(fb._t);
245 if (!ret.empty())
return ret;
246 for (
auto b : _ready) ret.push_back(b.second._t);
257 FlexiBin(T& t,
double cest = 0.0,
double weight = 0.0)
258 : _t(t), _cestLo(cest), _cestHi(cest), _weightsum(weight), _n(1), _m(0) { }
261 FlexiBin(
double cest)
262 : _cestLo(cest), _cestHi(cest), _weightsum(0.0), _n(0), _m(0) { }
265 void merge(
const FlexiBin& fb) {
266 _cestLo =
min(_cestLo, fb._cestLo);
267 _cestHi =
max(_cestHi, fb._cestHi);
268 _weightsum += fb._weightsum;
269 CentralityBinTraits<T>::add(_t, fb._t);
275 bool operator<(
const FlexiBin& fb)
const {
276 return _cestLo < fb._cestLo;
281 bool inRange(
double cest)
const {
282 return cest == _cestLo || (_cestLo < cest && cest < _cestHi);
290 double _cestLo, _cestHi;
294 mutable double _weightsum;
321 Bin(T t,
double centLo,
double centHi,
double cestLo = -1.0,
double cestHi = -1.0)
335 bool inRange(
double cest)
const {
336 return _cestLo >= 0 && _cestLo <= cest && (_cestHi < 0.0 || cest <= _cestHi);
341 CentralityBinTraits<T>::normalize(_t, _weightsum);
348 double _centLo, _centHi;
351 double _cestLo, _cestHi;
378 typename FlexiBinSet::iterator _findBin(
double cest) {
379 if (_flexiBins.empty())
return _flexiBins.end();
380 auto it = _flexiBins.lower_bound(FlexiBin(cest));
381 if (it->_cestLo == cest)
return it;
382 if (it != _flexiBins.begin()) --it;
383 if (it->_cestLo < cest && cest < it->_cestHi)
return it;
384 return _flexiBins.end();
407 vector<Bin> _unfilled;
416 set<double> _percentiles;
435 struct CentralityBinTraits<Profile1DPtr> {
437 typedef Profile1DPtr T;
440 static T clone(
const T& t) {
441 return Profile1DPtr(t->newclone());
445 static void add(T& t,
const T& o) {
450 static void scale(T& t,
double f) {
454 static void normalize(T& t,
double sumw) { }
457 static string path(T t) {
465 struct CentralityBinTraits<Profile2DPtr> {
467 typedef Profile2DPtr T;
470 static T clone(
const T& t) {
471 return Profile2DPtr(t->newclone());
475 static void add(T& t,
const T& o) {
480 static void scale(T& t,
double f) {
484 static void normalize(T& t,
double sumw) { }
487 static string path(T t) {
492 template <
typename T>
493 struct CentralityBinTraits<vector<T>> {
496 static vector<T> clone(
const vector<T>& tv) {
498 for (
auto t : tv) rtv.push_back(CentralityBinTraits<T>::clone(t));
503 static void add(vector<T>& tv,
const vector<T>& ov) {
504 for (
int i = 0, N = tv.size(); i < N; ++i) CentralityBinTraits::add(tv[i], ov[i]);
508 static void scale(vector<T>& tv,
double f) {
509 for (
auto t : tv) CentralityBinTraits<T>::scale(t, f);
512 static void normalize(vector<T>& tv,
double sumw) {
513 for (
auto t : tv) CentralityBinTraits<T>::normalize(t, sumw);
517 static string path(
const vector<T>& tv) {
518 string ret =
"(vector:";
521 ret += CentralityBinTraits<T>::path(t);
528 template <
size_t I,
typename... Types>
529 struct TupleCentralityBinTraitsHelper {
531 typedef tuple<Types...> Tuple;
532 typedef typename tuple_element<I - 1, Tuple>::type T;
534 static void clone(Tuple& ret,
const Tuple& tup) {
535 get<I - 1>(ret) = CentralityBinTraits<T>::clone(get<I - 1>(tup));
536 TupleCentralityBinTraitsHelper<I - 1, Types...>::clone(ret, tup);
539 static void add(Tuple& tup,
const Tuple& otup) {
540 CentralityBinTraits<T>::add(get<I - 1>(tup), get<I - 1>(otup));
541 TupleCentralityBinTraitsHelper<I - 1, Types...>::add(tup, otup);
544 static void scale(Tuple& tup,
double f) {
545 CentralityBinTraits<T>::scale(get<I - 1>(tup), f);
546 TupleCentralityBinTraitsHelper<I - 1, Types...>::scale(tup, f);
549 static void normalize(Tuple& tup,
double sumw) {
550 CentralityBinTraits<T>::normalize(get<I - 1>(tup), sumw);
551 TupleCentralityBinTraitsHelper<I - 1, Types...>::normalize(tup, sumw);
554 static string path(
const Tuple& tup) {
555 return " " + CentralityBinTraits<T>::path(get<I - 1>(tup))
556 + TupleCentralityBinTraitsHelper<I - 1, Types...>::path(tup);
560 template <
typename... Types>
561 struct TupleCentralityBinTraitsHelper<0, Types...> {
563 typedef tuple<Types...> Tuple;
565 static void clone(Tuple&,
const Tuple&) { }
566 static void add(Tuple& tup,
const Tuple& otup) { }
567 static void scale(Tuple& tup,
double f) { }
568 static void normalize(Tuple& tup,
double sumw) { }
569 static string path(
const Tuple& tup) {
574 template <
typename... Types>
575 struct CentralityBinTraits<tuple<Types...>> {
577 typedef tuple<Types...> Tuple;
578 static const size_t N = tuple_size<Tuple>::value;
581 static Tuple clone(
const Tuple& tup) {
583 TupleCentralityBinTraitsHelper<N, Types...>::clone(ret, tup);
588 static void add(Tuple& tup,
const Tuple& otup) {
589 TupleCentralityBinTraitsHelper<N, Types...>::add(tup, otup);
593 static void scale(Tuple& tup,
double f) {
594 TupleCentralityBinTraitsHelper<N, Types...>::scale(tup, f);
597 static void normalize(Tuple& tup,
double sumw) {
598 TupleCentralityBinTraitsHelper<N, Types...>::normalize(tup, sumw);
602 static string path(
const Tuple& tup) {
603 string ret =
"(tuple:";
604 ret += TupleCentralityBinTraitsHelper<N, Types...>::path(tup);
610 template <
typename T,
typename MDist>
614 _weightsum += weight;
617 if (_currentCEst < 0.0)
return _currenT;
622 if (_unfilled.empty()) {
623 for (
auto& b : _ready)
624 if (b.second.inRange(_currentCEst)) {
625 b.second._weightsum += weight;
631 auto it = _findBin(cest);
632 if (it == _flexiBins.end()) {
633 _currenT = CentralityBinTraits<T>::clone(_unfilled.begin()->_t);
634 it = _flexiBins.insert(FlexiBin(_currenT, _currentCEst, weight)).first;
637 it->_weightsum += weight;
642 if ((
int)_flexiBins.size() <= _maxBins)
return _currenT;
647 auto selectit = _flexiBins.end();
648 double mindist = -1.0;
650 auto next = _flexiBins.begin();
652 for (; next != _flexiBins.end(); prev = next++) {
653 acc += prev->_weightsum / _weightsum;
658 if (acc + next->_weightsum / _weightsum > *citn)
continue;
659 double dist = MDist::dist(prev->_cestLo, next->_cestHi, next->_weightsum + prev->_weightsum, *cit0,
660 *citn, next->_n + prev->_n, next->_m + prev->_m);
661 if (mindist < 0.0 || dist < mindist) {
667 if (selectit == _flexiBins.end())
return _currenT;
668 auto mergeit = selectit++;
669 FlexiBin merged = *mergeit;
670 merged.merge(*selectit);
671 if (merged.inRange(cest) || selectit->inRange(cest)) _currenT = merged._t;
672 _flexiBins.erase(mergeit);
673 _flexiBins.erase(selectit);
674 _flexiBins.insert(merged);
680 template <
typename T,
typename MDist>
687 for (
const FlexiBin& fb : _flexiBins) {
688 double chi =
min(clo + fb._weightsum / _weightsum, 1.0);
689 for (Bin& bin : _unfilled) {
690 double olo = bin._centLo;
691 double ohi = bin._centHi;
692 if (clo > ohi || chi <= olo)
continue;
694 double lo =
max(olo, clo);
695 double hi =
min(ohi, chi);
696 T t = CentralityBinTraits<T>::clone(fb._t);
697 double frac = (hi - lo) / (chi - clo);
698 CentralityBinTraits<T>::scale(t, frac);
699 CentralityBinTraits<T>::add(bin._t, t);
700 bin._weightsum += fb._weightsum * frac;
701 if (clo <= olo) bin._cestLo = fb._cestLo + (fb._cestHi - fb._cestLo) * (olo - clo) / (chi - clo);
703 bin._underflow = clo;
704 bin._ambiguous += fb._n * frac;
705 bin._ambweight += fb._weightsum * frac * (1.0 - frac);
708 bin._cestHi = fb._cestLo + (fb._cestHi - fb._cestLo) * (ohi - clo) / (chi - clo);
710 bin._ambiguous += fb._n * frac;
711 bin._ambweight += fb._weightsum * frac * (1.0 - frac);
717 for (Bin& bin : _unfilled) {
718 if (bin._overflow == 0.0) bin._overflow = 1.0;
719 _ready[bin._t] = bin;
720 if (bin._ambweight / bin._weightsum > _warnlimit)
722 << CentralityBinTraits<T>::path(bin._t)
723 <<
"\", contains events with centralities between " << bin._underflow * 100.0 <<
" and "
724 << bin._overflow * 100.0 <<
"% (" <<
int(bin._ambiguous + 0.5)
725 <<
" ambiguous events with effectively " << 100.0 * bin._ambweight / bin._weightsum
726 <<
"% of the weights)."
727 <<
"Consider increasing the number of bins.");
732 template <
typename T,
typename MDist>
733 void CentralityBinner<T, MDist>::fulldebug() {
739 for (
auto it = _flexiBins.begin(); it != _flexiBins.end();) {
742 double w = curr->_weightsum / _weightsum;
744 if (curr == _flexiBins.begin() || it == _flexiBins.end() || acc > *citn)
748 if (acc > *citn) cit0 = citn++;
749 cerr << setw(6) << i << setw(12) << acc - w << setw(12) << acc << setw(8) << curr->_n << setw(8)
750 << curr->_m << setw(12) << curr->_cestLo << setw(12) << curr->_cestHi << endl;
752 cerr <<
"Number of sampler bins: " << _flexiBins.size() << endl;
755 template <
typename T,
typename MDist>
762 for (
auto it = _flexiBins.begin(); it != _flexiBins.end();) {
765 double w = curr->_weightsum / _weightsum;
767 if (curr == _flexiBins.begin() || it == _flexiBins.end() || acc > *citn) {
768 if (acc > *citn) cit0 = citn++;
769 cerr << setw(6) << i << setw(12) << acc - w << setw(12) << acc << setw(8) << curr->_n << setw(8)
770 << curr->_m << setw(12) << curr->_cestLo << setw(12) << curr->_cestHi << endl;
773 cerr <<
"Number of sampler bins: " << _flexiBins.size() << endl;
double estimator() const
Definition CentralityBinner.hh:238
void normalizePerEvent()
Definition CentralityBinner.hh:216
map< double, double > edges() const
Definition CentralityBinner.hh:222
T select(const Event &event, double weight=1.0)
Definition CentralityBinner.hh:194
const T & current() const
Return the current AnalysisObject from the latest call to select().
Definition CentralityBinner.hh:232
void add(T t, double cmin, double cmax, double cestmin=-1.0, double cestmax=-1.0)
Definition CentralityBinner.hh:176
void finalize()
Definition CentralityBinner.hh:681
set< FlexiBin > FlexiBinSet
Convenient typedefs.
Definition CentralityBinner.hh:374
void setProjection(const CentralityEstimator &p, string pname)
Definition CentralityBinner.hh:154
CentralityBinner(int maxbins=200, double wlim=0.02)
Definition CentralityBinner.hh:146
void debug()
Print out the _flexiBins to cerr.
Definition CentralityBinner.hh:756
virtual std::string name() const
Return the class name.
Definition CentralityBinner.hh:160
Base class for projections profile observable value vs the collision centrality.
Definition CentralityBinner.hh:34
void project(const Event &e)
Perform the projection on the Event.
Definition CentralityBinner.hh:50
CentralityEstimator()
Constructor.
Definition CentralityBinner.hh:38
CmpState compare(const Projection &p) const
Compare projections.
Definition CentralityBinner.hh:58
RIVET_DEFAULT_PROJ_CLONE(CentralityEstimator)
Clone on the heap.
double estimate() const
The value of the centrality estimate.
Definition CentralityBinner.hh:66
Representation of a HepMC event, and enabler of Projection caching.
Definition Event.hh:22
GeneratedCentrality()
Constructor.
Definition CentralityBinner.hh:783
CmpState compare(const Projection &p) const
Compare projections.
Definition CentralityBinner.hh:798
void project(const Event &e)
Perform the projection on the Event.
Definition CentralityBinner.hh:793
RIVET_DEFAULT_PROJ_CLONE(GeneratedCentrality)
Clone on the heap.
Definition HepMCHeavyIon.hh:12
std::enable_if_t< std::is_base_of< Projection, PROJ >::value, const PROJ & > apply(const Event &evt, const Projection &proj) const
Apply the supplied projection on event evt.
Definition ProjectionApplier.hh:124
const PROJ & declare(const PROJ &proj, const std::string &name) const
Register a contained projection (user-facing version).
Definition ProjectionApplier.hh:205
ProjectionApplier()
Constructor.
Base class for all Rivet projections.
Definition Projection.hh:29
Projection()
The default constructor.
friend class Event
Event is a friend.
Definition Projection.hh:33
void setName(const std::string &name)
Used by derived classes to set their name.
Definition Projection.hh:146
Cmp< Projection > mkNamedPCmp(const Projection &otherparent, const std::string &pname) const
#define MSG_WARNING(x)
Warning messages for non-fatal bad things, using MSG_LVL.
Definition Logging.hh:200
double p(const ParticleBase &p)
Unbound function access to p.
Definition ParticleBaseUtils.hh:819
Definition LHCbCommon.hh:9
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > max(N1 a, N2 b)
Get the maximum of two numbers.
Definition MathUtils.hh:124
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > min(N1 a, N2 b)
Get the minimum of two numbers.
Definition MathUtils.hh:113