Rivet  3.1.4
PercentileProjection.hh
1 // -*- C++ -*-
2 #ifndef RIVET_PERCENTILEPROJECTION_HH
3 #define RIVET_PERCENTILEPROJECTION_HH
4 
5 #include "Rivet/Projections/SingleValueProjection.hh"
6 #include "Rivet/Tools/RivetYODA.hh"
7 #include <map>
8 
9 namespace Rivet {
10 
20 public:
21 
27  PercentileProjection(const SingleValueProjection & sv, const Histo1D& calhist,
28  bool increasing = false)
29  : _calhist("EMPTY"), _increasing(increasing) {
30  setName("PercentileProjection");
31  declare(sv, "OBSERVABLE");
32  //if ( !calhist ) return;
33  MSG_DEBUG("Constructing PercentileProjection from " << calhist.path());
34  _calhist = calhist.path();
35  int N = calhist.numBins();
36  double sum = calhist.sumW();
37 
38  if ( increasing ) {
39  double acc = calhist.underflow().sumW();
40  _table.insert(make_pair(calhist.bin(0).xEdges().first, 100.0*acc/sum));
41  for ( int i = 0; i < N; ++i ) {
42  acc += calhist.bin(i).sumW();
43  _table.insert(make_pair(calhist.bin(i).xEdges().second, 100.0*acc/sum));
44  }
45  } else {
46  double acc = calhist.overflow().sumW();
47  _table.insert(make_pair(calhist.bin(N - 1).xEdges().second, 100.0*acc/sum));
48  for ( int i = N - 1; i >= 0; --i ) {
49  acc += calhist.bin(i).sumW();
50  _table.insert(make_pair(calhist.bin(i).xEdges().first, 100.0*acc/sum));
51  }
52  }
53  if (getLog().isActive(Log::DEBUG)) {
54  MSG_DEBUG("Mapping from observable to percentile:");
55  for (auto p : _table) {
56  std::cout << std::setw(16) << p.first << " -> "
57  << std::setw(16) << p.second << "%" << std::endl;
58  if (not increasing and p.second <= 0) break;
59  if (increasing and p.second >= 100) break;
60  }
61  }
62  }
63 
64  // Constructor taking a SingleValueProjection and a calibration
65  // histogram. If increasing it means that low values corresponds to
66  // lower percentiles.
67  PercentileProjection(const SingleValueProjection & sv, const Scatter2D& calscat,
68  bool increasing = false)
69  : _calhist("EMPTY"), _increasing(increasing) {
70  declare(sv, "OBSERVABLE");
71 
72  //if ( !calscat ) return;
73  MSG_DEBUG("Constructing PercentileProjection from " << calscat.path());
74  _calhist = calscat.path();
75  int N = calscat.numPoints();
76  double sum = 0.0;
77  for ( const auto & p : calscat.points() ) sum += p.y();
78 
79  double acc = 0.0;
80  if ( increasing ) {
81  _table.insert(make_pair(calscat.point(0).xMin(), 100.0*acc/sum));
82  for ( int i = 0; i < N; ++i ) {
83  acc += calscat.point(i).y();
84  _table.insert(make_pair(calscat.point(i).xMax(), 100.0*acc/sum));
85  }
86  } else {
87  _table.insert(make_pair(calscat.point(N - 1).xMax(), 100.0*acc/sum));
88  for ( int i = N - 1; i >= 0; --i ) {
89  acc += calscat.point(i).y();
90  _table.insert(make_pair(calscat.point(i).xMin(), 100.0*acc/sum));
91  }
92  }
93  }
94 
95  DEFAULT_RIVET_PROJ_CLONE(PercentileProjection);
96 
97  // The projection function takes the assigned SingeValueProjection
98  // and sets the value of this projection to the corresponding
99  // percentile. If no calibration has been provided, -1 will be
100  // returned. If values are outside of the calibration histogram, 0
101  // or 100 will be returned.
102  void project(const Event& e) {
103  clear();
104  if ( _table.empty() ) return;
105  auto& pobs = apply<SingleValueProjection>(e, "OBSERVABLE");
106  double obs = pobs();
107  double pcnt = lookup(obs);
108  if ( pcnt >= 0.0 ) set(pcnt);
109  MSG_DEBUG("Observable(" << pobs.name() << ")="
110  << std::setw(16) << obs
111  << "-> Percentile=" << std::setw(16) << pcnt << "%");
112  }
113 
114 
115  // Standard comparison function.
116  CmpState compare(const Projection& p) const {
117  const PercentileProjection pp = dynamic_cast<const PercentileProjection&>(p);
118  return mkNamedPCmp(p, "OBSERVABLE") ||
119  cmp(_increasing, pp._increasing) ||
120  cmp(_calhist, pp._calhist);
121  }
122 
123 private:
124 
125  // The (interpolated) lookup table
126  double lookup(double obs) const {
127  auto low = _table.upper_bound(obs);
128  if ( low == _table.end() ) return _increasing? 100.0: 0.0;
129  if ( low == _table.begin() ) return _increasing? 0.0: 100.0;
130  auto high = low--;
131  return low->second + (obs - low->first)*(high->second - low->second)/
132  (high->first - low->first);
133  }
134 
135  // Astring identifying the calibration histogram.
136  string _calhist;
137 
138  // A lookup table to find (by interpolation) the percentile given
139  // the value of the underlying SingleValueProjection.
140  map<double,double> _table;
141 
142  // A flag to say whether the distribution should be integrated from
143  // below or above.
144  bool _increasing;
145 
146 };
147 
148 
149 
150 
151 }
152 
153 #endif
void setName(const std::string &name)
Used by derived classes to set their name.
Definition: Projection.hh:142
Definition: MC_Cent_pPb.hh:10
Base class for projections returning a single floating point value.
Definition: SingleValueProjection.hh:17
#define MSG_DEBUG(x)
Debug messaging, not enabled by default, using MSG_LVL.
Definition: Logging.hh:195
bool isActive(int level) const
Will this log level produce output on this logger at the moment?
Definition: Logging.hh:129
Representation of a HepMC event, and enabler of Projection caching.
Definition: Event.hh:22
CmpState compare(const Projection &p) const
Definition: PercentileProjection.hh:116
void project(const Event &e)
Definition: PercentileProjection.hh:102
PercentileProjection(const SingleValueProjection &sv, const Histo1D &calhist, bool increasing=false)
Definition: PercentileProjection.hh:27
CONTAINER::value_type sum(const CONTAINER &c)
Generic sum function, adding x for all x in container c.
Definition: Utils.hh:434
const PROJ & declare(const PROJ &proj, const std::string &name)
Register a contained projection (user-facing version)
Definition: ProjectionApplier.hh:170
Cmp< Projection > mkNamedPCmp(const Projection &otherparent, const std::string &pname) const
class for projections that reports the percentile for a given SingleValueProjection when initialized ...
Definition: PercentileProjection.hh:19
Base class for all Rivet projections.
Definition: Projection.hh:29
Log & getLog() const
Get a Log object based on the getName() property of the calling projection object.
Definition: Projection.hh:136
void clear()
Unset the value.
Definition: SingleValueProjection.hh:54
Cmp< T > cmp(const T &t1, const T &t2)
Global helper function for easy creation of Cmp objects.
Definition: Cmp.hh:255