rivet is hosted by Hepforge, IPPP Durham
Rivet 4.0.0
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 <deque>
9#include <algorithm>
10
11namespace Rivet {
12
13
33
38 template <class RandomAccessIterator,
39 class WeightIterator, class RandomNumberGenerator>
40 void weighted_shuffle(RandomAccessIterator first, RandomAccessIterator last,
41 WeightIterator fw, WeightIterator lw, RandomNumberGenerator& g) {
42 while(first != last && fw != lw) {
43 std::discrete_distribution<int> weightDist(fw, lw);
44 int i = weightDist(g);
45 if(i){
46 std::iter_swap(first, next(first, i));
47 std::iter_swap(fw, next(fw, i));
48 }
49 ++first;
50 ++fw;
51 }
52 }
53
55 typedef pair<Particles, double> MixEvent;
56 typedef map<double, std::deque<MixEvent> > MixMap;
57
71 class EventMixingBase : public Projection {
72 protected:
74 EventMixingBase(const Projection & mixObsProj, const ParticleFinder& mix,
75 size_t nMixIn, double oMin, double oMax, double deltao,
76 const size_t defaultIdx) : nMix(nMixIn), unitWeights(true) {
77 // The base class contructor should be called explicitly in derived classes
78 // to add projections below.
79 setName("EventMixingBase");
80 declare(mixObsProj,"OBS");
81 declare(mix,"MIX");
82 MSG_WARNING("EventMixing is not fully validated. Use with caution.");
83
84 _defaultWeightIdx = defaultIdx;
85 // Set up the map for mixing events.
86 for(double o = oMin; o < oMax; o+=deltao )
87 mixEvents[o] = std::deque<MixEvent>();
88 }
89
91 using Projection::operator =;
92
93
94 public:
95
98 bool hasMixingEvents() const {
99 MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
100 if(mixItr == mixEvents.end() || mixItr->second.size() < nMix + 1)
101 return false;
102 return true;
103 }
104
106 vector<MixEvent> getMixingEvents() const {
107 if (!hasMixingEvents())
108 return vector<MixEvent>();
109 MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
110 return vector<MixEvent>(mixItr->second.begin(), mixItr->second.end() - 1);
111 }
112
117 virtual const Particles particles() const {
118 // Test if we have enough mixing events.
119 if (!hasMixingEvents())
120 return Particles();
121 // Get mixing events for the current, projected mixing observable.
122 MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
123 vector<MixEvent> mixEvents(mixItr->second.begin(), mixItr->second.end() - 1);
124 // Make the vector of mixed particles.
125 Particles mixParticles;
126 vector<double> weights;
127 size_t pSize = 0;
128 for (size_t i = 0; i < mixEvents.size(); ++i)
129 pSize+=mixEvents[i].first.size();
130 mixParticles.reserve(pSize);
131 weights.reserve(pSize);
132 // Put the particles in the vector.
133 for (size_t i = 0; i < mixEvents.size(); ++i) {
134 mixParticles.insert(mixParticles.end(), mixEvents[i].first.begin(), mixEvents[i].first.end());
135 vector<double> tmp(mixEvents[i].first.size(), mixEvents[i].second);
136 weights.insert(weights.end(), tmp.begin(), tmp.end());
137 }
138
139 // Shuffle the particles.
140 if (unitWeights) {
141 // Use the thread safe random number generator.
142 //auto rnd = [&] (int i) {return rng()()%i;};
143 std::shuffle(mixParticles.begin(), mixParticles.end(), rng());
144 return mixParticles;
145 } else {
146 weighted_shuffle(mixParticles.begin(), mixParticles.end(), weights.begin(), weights.end(), rng());
147 Particles tmp = vector<Particle>(mixParticles.begin(), mixParticles.begin() + size_t(ceil(mixParticles.size() / 2)));
148 return tmp;
149 }
150 }
151
152
153 protected:
154
158 virtual void calculateMixingObs(const Projection* mProj) = 0;
159
160
162 void project(const Event& e) {
163 const Projection* mixObsProjPtr = &apply<Projection>(e, "OBS");
164 calculateMixingObs(mixObsProjPtr);
165 MixMap::iterator mixItr = mixEvents.lower_bound(mObs);
166 if (mixItr == mixEvents.end()){
167 // We are out of bounds.
168 MSG_DEBUG("Mixing observable out of bounds.");
169 return;
170 }
171 const Particles mix = apply<ParticleFinder>(e, "MIX").particles();
172 mixItr->second.push_back(make_pair(mix,e.weights()[_defaultWeightIdx]));
173 // Assume unit weights until we see otherwise.
174 if (unitWeights && e.weights()[_defaultWeightIdx] != 1.0 ) {
175 unitWeights = false;
176 nMix *= 2;
177 }
178 if (mixItr->second.size() > nMix + 1)
179 mixItr->second.pop_front();
180 }
181
182
184 CmpState compare(const Projection& p) const {
185 return mkNamedPCmp(p,"OBS");
186 }
187
188
190 double mObs;
191
192
193 protected:
194
196 size_t nMix;
197
199 MixMap mixEvents;
200
203
204 size_t _defaultWeightIdx;
205
206 };
207
208
211 public:
212 EventMixingFinalState(const ParticleFinder & mixObsProj,
213 const ParticleFinder& mix, size_t nMixIn, double oMin, double oMax,
214 double deltao, const size_t defaultIdx) :
215 EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao, defaultIdx) {
216 setName("EventMixingFinalState");
217 }
218
219 RIVET_DEFAULT_PROJ_CLONE(EventMixingFinalState);
220
222 using Projection::operator =;
223
224
225 protected:
226
228 virtual void calculateMixingObs(const Projection* mProj) {
229 mObs = ((ParticleFinder*) mProj)->particles().size();
230 }
231
232 };
233
234
237 public:
238
240 const ParticleFinder& mix, size_t nMixIn, double oMin, double oMax,
241 double deltao, const size_t defaultIdx) :
242 EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao, defaultIdx) {
243 setName("EventMixingCentrality");
244 }
245
246 RIVET_DEFAULT_PROJ_CLONE(EventMixingCentrality);
247
249 using Projection::operator =;
250
251 protected:
252
254 virtual void calculateMixingObs(const Projection* mProj) {
255 mObs = ((CentralityProjection*) mProj)->operator()();
256 }
257
258 };
259
260
261}
262
263#endif
Used together with the percentile-based analysis objects Percentile and PercentileXaxis.
Definition CentralityProjection.hh:27
Definition EventMixingFinalState.hh:71
virtual void calculateMixingObs(const Projection *mProj)=0
size_t nMix
The number of event to mix with.
Definition EventMixingFinalState.hh:196
bool unitWeights
Using unit weights or not.
Definition EventMixingFinalState.hh:202
vector< MixEvent > getMixingEvents() const
Return a vector of mixing events.
Definition EventMixingFinalState.hh:106
MixMap mixEvents
The event map.
Definition EventMixingFinalState.hh:199
EventMixingBase(const Projection &mixObsProj, const ParticleFinder &mix, size_t nMixIn, double oMin, double oMax, double deltao, const size_t defaultIdx)
Constructor.
Definition EventMixingFinalState.hh:74
void project(const Event &e)
Perform the projection on the Event.
Definition EventMixingFinalState.hh:162
double mObs
The mixing observable of the current event.
Definition EventMixingFinalState.hh:190
bool hasMixingEvents() const
Definition EventMixingFinalState.hh:98
virtual const Particles particles() const
Return a vector of particles from the mixing events.
Definition EventMixingFinalState.hh:117
CmpState compare(const Projection &p) const
Compare with other projections.
Definition EventMixingFinalState.hh:184
EventMixingCentrality has centrality as the mixing observable.
Definition EventMixingFinalState.hh:236
virtual void calculateMixingObs(const Projection *mProj)
Calculate the mixing observable.
Definition EventMixingFinalState.hh:254
EventMixingFinalState has multiplicity as the mixing observable.
Definition EventMixingFinalState.hh:210
virtual void calculateMixingObs(const Projection *mProj)
Calculate the mixing observable.
Definition EventMixingFinalState.hh:228
Representation of a HepMC event, and enabler of Projection caching.
Definition Event.hh:22
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
const PROJ & declare(const PROJ &proj, const std::string &name) const
Register a contained projection (user-facing version)
Definition ProjectionApplier.hh:175
Base class for all Rivet projections.
Definition Projection.hh:29
void setName(const std::string &name)
Used by derived classes to set their name.
Definition Projection.hh:148
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:182
#define MSG_WARNING(x)
Warning messages for non-fatal bad things, using MSG_LVL.
Definition Logging.hh:187
Definition MC_CENT_PPB_Projections.hh:10
void weighted_shuffle(RandomAccessIterator first, RandomAccessIterator last, WeightIterator fw, WeightIterator lw, RandomNumberGenerator &g)
Make an event mixed together from several events.
Definition EventMixingFinalState.hh:40
pair< Particles, double > MixEvent
A MixEvent is a vector of particles with and associated weight.
Definition EventMixingFinalState.hh:55
std::mt19937 & rng()
Return a thread-safe random number generator (mainly for internal use)