Rivet API documentation

Rivet 4.1.3
EventMixingFinalState.hh
1// -*- C++ -*-
2#ifndef RIVET_EventMixingFinalState_HH
3#define RIVET_EventMixingFinalState_HH
4
5#include "Rivet/Projection.hh"
6#include "Rivet/Projections/ParticleFinder.hh"
7#include "Rivet/Tools/Random.hh"
8#include <algorithm>
9#include <deque>
10
11namespace Rivet {
12
13
33
38 template <class RandomAccessIterator, class WeightIterator, class RandomNumberGenerator>
39 void weighted_shuffle(RandomAccessIterator first,
40 RandomAccessIterator last,
41 WeightIterator fw,
42 WeightIterator lw,
43 RandomNumberGenerator& g) {
44 while (first != last && fw != lw) {
45 std::discrete_distribution<int> weightDist(fw, lw);
46 int i = weightDist(g);
47 if (i) {
48 std::iter_swap(first, next(first, i));
49 std::iter_swap(fw, next(fw, i));
50 }
51 ++first;
52 ++fw;
53 }
54 }
55
57 typedef pair<Particles, double> MixEvent;
58 typedef map<double, std::deque<MixEvent>> MixMap;
59
73 class EventMixingBase : public Projection {
74 protected:
75
77 EventMixingBase(const Projection& mixObsProj,
78 const ParticleFinder& mix,
79 size_t nMixIn,
80 double oMin,
81 double oMax,
82 double deltao,
83 const size_t defaultIdx)
84 : nMix(nMixIn), unitWeights(true) {
85 // The base class contructor should be called explicitly in derived classes
86 // to add projections below.
87 setName("EventMixingBase");
88 declare(mixObsProj, "OBS");
89 declare(mix, "MIX");
90 MSG_WARNING("EventMixing is not fully validated. Use with caution.");
91
92 _defaultWeightIdx = defaultIdx;
93 // Set up the map for mixing events.
94 for (double o = oMin; o < oMax; o += deltao) mixEvents[o] = std::deque<MixEvent>();
95 }
96
98 using Projection::operator=;
99
100
101 public:
102
105 bool hasMixingEvents() const {
106 MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
107 if (mixItr == mixEvents.end() || mixItr->second.size() < nMix + 1) return false;
108 return true;
109 }
110
112 vector<MixEvent> getMixingEvents() const {
113 if (!hasMixingEvents()) return vector<MixEvent>();
114 MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
115 return vector<MixEvent>(mixItr->second.begin(), mixItr->second.end() - 1);
116 }
117
122 virtual const Particles particles() const {
123 // Test if we have enough mixing events.
124 if (!hasMixingEvents()) return Particles();
125 // Get mixing events for the current, projected mixing observable.
126 MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
127 vector<MixEvent> mixEvents(mixItr->second.begin(), mixItr->second.end() - 1);
128 // Make the vector of mixed particles.
129 Particles mixParticles;
130 vector<double> weights;
131 size_t pSize = 0;
132 for (size_t i = 0; i < mixEvents.size(); ++i) pSize += mixEvents[i].first.size();
133 mixParticles.reserve(pSize);
134 weights.reserve(pSize);
135 // Put the particles in the vector.
136 for (size_t i = 0; i < mixEvents.size(); ++i) {
137 mixParticles.insert(mixParticles.end(), mixEvents[i].first.begin(), mixEvents[i].first.end());
138 vector<double> tmp(mixEvents[i].first.size(), mixEvents[i].second);
139 weights.insert(weights.end(), tmp.begin(), tmp.end());
140 }
141
142 // Shuffle the particles.
143 if (unitWeights) {
144 // Use the thread safe random number generator.
145 //auto rnd = [&] (int i) {return rng()()%i;};
146 std::shuffle(mixParticles.begin(), mixParticles.end(), rng());
147 return mixParticles;
148 }
149 else {
150 weighted_shuffle(mixParticles.begin(), mixParticles.end(), weights.begin(), weights.end(), rng());
151 Particles tmp = vector<Particle>(mixParticles.begin(),
152 mixParticles.begin() + size_t(ceil(mixParticles.size() / 2)));
153 return tmp;
154 }
155 }
156
157
158 protected:
159
163 virtual void calculateMixingObs(const Projection* mProj) = 0;
164
165
167 void project(const Event& e) {
168 const Projection* mixObsProjPtr = &apply<Projection>(e, "OBS");
169 calculateMixingObs(mixObsProjPtr);
170 MixMap::iterator mixItr = mixEvents.lower_bound(mObs);
171 if (mixItr == mixEvents.end()) {
172 // We are out of bounds.
173 MSG_DEBUG("Mixing observable out of bounds.");
174 return;
175 }
176 const Particles mix = apply<ParticleFinder>(e, "MIX").particles();
177 mixItr->second.push_back(make_pair(mix, e.weights()[_defaultWeightIdx]));
178 // Assume unit weights until we see otherwise.
179 if (unitWeights && e.weights()[_defaultWeightIdx] != 1.0) {
180 unitWeights = false;
181 nMix *= 2;
182 }
183 if (mixItr->second.size() > nMix + 1) mixItr->second.pop_front();
184 }
185
186
188 CmpState compare(const Projection& p) const {
189 return mkNamedPCmp(p, "OBS");
190 }
191
192
194 double mObs;
195
196
197 protected:
198
200 size_t nMix;
201
203 MixMap mixEvents;
204
207
208 size_t _defaultWeightIdx;
209 };
210
211
213 class EventMixingFinalState : public EventMixingBase {
214 public:
215
216 EventMixingFinalState(const ParticleFinder& mixObsProj,
217 const ParticleFinder& mix,
218 size_t nMixIn,
219 double oMin,
220 double oMax,
221 double deltao,
222 const size_t defaultIdx)
223 : EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao, defaultIdx) {
224 setName("EventMixingFinalState");
225 }
226
227 RIVET_DEFAULT_PROJ_CLONE(EventMixingFinalState);
228
230 using Projection::operator=;
231
232
233 protected:
234
236 virtual void calculateMixingObs(const Projection* mProj) {
237 mObs = ((ParticleFinder*)mProj)->particles().size();
238 }
239 };
240
241
243 class EventMixingCentrality : public EventMixingBase {
244 public:
245
246 EventMixingCentrality(const CentralityProjection& mixObsProj,
247 const ParticleFinder& mix,
248 size_t nMixIn,
249 double oMin,
250 double oMax,
251 double deltao,
252 const size_t defaultIdx)
253 : EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao, defaultIdx) {
254 setName("EventMixingCentrality");
255 }
256
257 RIVET_DEFAULT_PROJ_CLONE(EventMixingCentrality);
258
260 using Projection::operator=;
261
262 protected:
263
265 virtual void calculateMixingObs(const Projection* mProj) {
266 mObs = ((CentralityProjection*)mProj)->operator()();
267 }
268 };
269
270
271}
272
273#endif
Used together with the percentile-based analysis objects Percentile and PercentileXaxis.
Definition CentralityProjection.hh:27
virtual void calculateMixingObs(const Projection *mProj)=0
size_t nMix
The number of event to mix with.
Definition EventMixingFinalState.hh:200
bool unitWeights
Using unit weights or not.
Definition EventMixingFinalState.hh:206
vector< MixEvent > getMixingEvents() const
Return a vector of mixing events.
Definition EventMixingFinalState.hh:112
MixMap mixEvents
The event map.
Definition EventMixingFinalState.hh:203
EventMixingBase(const Projection &mixObsProj, const ParticleFinder &mix, size_t nMixIn, double oMin, double oMax, double deltao, const size_t defaultIdx)
Constructor.
Definition EventMixingFinalState.hh:77
void project(const Event &e)
Perform the projection on the Event.
Definition EventMixingFinalState.hh:167
double mObs
The mixing observable of the current event.
Definition EventMixingFinalState.hh:194
bool hasMixingEvents() const
Definition EventMixingFinalState.hh:105
virtual const Particles particles() const
Return a vector of particles from the mixing events.
Definition EventMixingFinalState.hh:122
CmpState compare(const Projection &p) const
Compare with other projections.
Definition EventMixingFinalState.hh:188
virtual void calculateMixingObs(const Projection *mProj)
Calculate the mixing observable.
Definition EventMixingFinalState.hh:265
virtual void calculateMixingObs(const Projection *mProj)
Calculate the mixing observable.
Definition EventMixingFinalState.hh:236
std::valarray< double > weights() const
The generation weights associated with the event.
Base class for projections which return subsets of an event's particles.
Definition ParticleFinder.hh:11
Specialised vector of Particle objects.
Definition Particle.hh:21
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
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_DEBUG(x)
Debug messaging, not enabled by default, using MSG_LVL.
Definition Logging.hh:195
#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
void weighted_shuffle(RandomAccessIterator first, RandomAccessIterator last, WeightIterator fw, WeightIterator lw, RandomNumberGenerator &g)
Make an event mixed together from several events.
Definition EventMixingFinalState.hh:39
pair< Particles, double > MixEvent
A MixEvent is a vector of particles with and associated weight.
Definition EventMixingFinalState.hh:57
std::mt19937 & rng()
Return a thread-safe random number generator (mainly for internal use).