Project
Loading...
Searching...
No Matches
InteractionSampler.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13#include <fairlogger/Logger.h>
14
15using namespace o2::steer;
16
17//_________________________________________________
19{
20 // (re-)initialize sample and check parameters consistency
21
22 int nBCSet = mBCFilling.getNBunches();
23 if (!nBCSet) {
24 LOG(warning) << "No bunch filling provided, impose default one";
26 nBCSet = mBCFilling.getNBunches();
27 }
28
29 if (mMuBC < 0. && mIntRate < 0.) {
30 LOG(warning) << "No IR or muBC is provided, setting default IR";
32 }
33
34 if (mMuBC > 0.) {
36 LOG(info) << "Deducing IR=" << mIntRate << "Hz from " << nBCSet << " BCs at mu=" << mMuBC;
37 } else {
39 LOG(info) << "Deducing mu=" << mMuBC << " per BC from IR=" << mIntRate << " with " << nBCSet << " BCs";
40 }
41
42 mInteractingBCs.clear();
43 mInteractingBCs.reserve(nBCSet);
44 for (int i = 0; i < o2::constants::lhc::LHCMaxBunches; i++) {
45 if (mBCFilling.testBC(i)) {
46 mInteractingBCs.push_back(i);
47 }
48 }
49
50 auto mu = mMuBC;
51 // prob. of not having interaction in N consecutive BCs is P(N) = mu*exp(-(N-1)*mu), hence its cumulative distribution
52 // is T(N) = integral_1^N {P(N)} = 1. - exp(-(N-1)*mu)
53 // We generate random N using its inverse, N = 1 - log(1 - Rndm)/mu
54 mBCJumpGenerator.initialize([mu]() { return (1. - std::log(1. - gRandom->Rndm()) / mu); });
55
56 // Poisson distribution of number of collisions in the bunch excluding 0
58 int n = 0;
59 while ((n = gRandom->Poisson(mu)) == 0) {
60 ;
61 }
62 return n;
63 });
64
65 auto trms = mBCTimeRMS;
67 float t; // make sure it does not go outside half bunch
68 while (std::abs(t = gRandom->Gaus(0, trms)) > o2::constants::lhc::LHCBunchSpacingNS / 2.1) {
69 ;
70 }
71 return t;
72 });
73
74 mIntBCCache = 0;
75 mCurrBCIdx = 0;
76 mIR = mFirstIR;
78 mCurrBCIdx++;
79 }
80 // set the "current BC" right in front of the 1st BC to generate. There will be a jump by at least 1 during generation
81 mCurrBCIdx--;
82}
83
84//_________________________________________________
86{
87 if (mIntRate < 0) {
88 LOG(error) << "not yet initialized";
89 return;
90 }
91 LOG(info) << "InteractionSampler with " << mInteractingBCs.size() << " colliding BCs, mu(BC)= "
92 << getMuPerBC() << " -> total IR= " << getInteractionRate();
93 LOG(info) << "Current " << mIR << '(' << mIntBCCache << " coll left)";
94}
95
96//_________________________________________________
98{
99 // generate single interaction record
100 if (mIntRate < 0) {
101 init();
102 }
103
104 if (mIntBCCache < 1) { // do we still have interaction in current BC?
105 mIntBCCache = simulateInteractingBC(); // decide which BC interacts and N collisions
106 }
107 mIR.timeInBCNS = mTimeInBC.back();
108 mTimeInBC.pop_back();
109 mIntBCCache--;
110
111 return mIR;
112}
113
114//_________________________________________________
116{
117 // Returns number of collisions assigned to selected BC
119
120 // once BC is decided, enforce at least one interaction
121 int ncoll = mNCollBCGenerator.getNextValue();
122
123 // assign random time withing a bunch
124 for (int i = ncoll; i--;) {
126 }
127 if (ncoll > 1) { // sort in DECREASING time order (we are reading vector from the end)
128 std::sort(mTimeInBC.begin(), mTimeInBC.end(), [](const float a, const float b) { return a > b; });
129 }
130 return ncoll;
131}
132
133//_________________________________________________
135{
136 // Returns number of collisions assigned to selected BC
137
138 nextCollidingBC(mEveryN); // we jump regular intervals
139 int ncoll = mMultiplicity; // well defined pileup
140
141 // assign random time withing a bunch
142 for (int i = ncoll; i--;) {
144 }
145 if (ncoll > 1) { // sort in DECREASING time order (we are reading vector from the end)
146 std::sort(mTimeInBC.begin(), mTimeInBC.end(), [](const float a, const float b) { return a > b; });
147 }
148 return ncoll;
149}
150
151//_________________________________________________
152void InteractionSampler::setBunchFilling(const std::string& bcFillingFile)
153{
154 // load bunch filling from the file
155 auto* bc = o2::BunchFilling::loadFrom(bcFillingFile, "ccdb_object");
156 if (!bc) {
157 bc = o2::BunchFilling::loadFrom(bcFillingFile); // retry with default naming in case of failure
158 }
159 if (!bc) {
160 LOG(fatal) << "Failed to load bunch filling from " << bcFillingFile;
161 }
162 mBCFilling = *bc;
163 delete bc;
164}
165
166// ________________________________________________
167bool NonUniformMuInteractionSampler::setBCIntensityScales(const std::vector<float>& scales_from_vector)
168{
169 // Sets the intensity scales per bunch crossing index
170 // The length of this vector needs to be compatible with the bunch filling chosen
171 mBCIntensityScales = scales_from_vector;
172
173 if (scales_from_vector.size() != mInteractingBCs.size()) {
174 LOG(error) << "Scaling factors and bunch filling scheme are not compatible. Not doing anything";
175 return false;
176 }
177
178 float sum = 0.;
179 for (auto v : mBCIntensityScales) {
180 sum += std::abs(v);
181 }
182 if (sum == 0) {
183 LOGP(warn, "total intensity is 0, assuming uniform");
184 for (auto& v : mBCIntensityScales) {
185 v = 1.f;
186 }
187 } else { // normalize
188 float norm = mBCIntensityScales.size() / sum;
189 for (auto& v : mBCIntensityScales) {
190 v = std::abs(v) * norm;
191 }
192 }
193 return false;
194}
195
196// ________________________________________________
197
202
204{
205 if (mInteractingBCs.size() == 0) {
206 LOG(error) << " Initialize bunch crossing scheme before assigning scales";
207 }
208 std::vector<float> scales;
209 // we go through the BCs and query the count from histogram
210 for (auto bc : mInteractingBCs) {
211 scales.push_back(hist.GetBinContent(bc + 1));
212 }
213 return scales;
214}
215
217{
218 auto muFunc = [this](int bc_position) {
219 return mBCIntensityScales[bc_position % mInteractingBCs.size()] * mMuBC;
220 };
221
222 double U = gRandom->Rndm(); // uniform (0,1)
223 double T = -std::log(1.0 - U); // threshold
224 double sumMu = 0.0;
225 int offset = 0;
226 auto bcStart = mCurrBCIdx; // the current bc
227
228 while (sumMu < T) {
229 auto mu_here = muFunc(bcStart + offset); // mu at next BC
230 sumMu += mu_here;
231 if (sumMu >= T) {
232 break; // found BC with at least one collision
233 }
234 ++offset;
235 }
236 return offset;
237}
238
240{
242
243 auto muFunc = [this](int bc_position) {
244 return mBCIntensityScales[bc_position % mInteractingBCs.size()] * mMuBC;
245 };
246
247 // now sample number of collisions in chosenBC, conditioned >=1:
248 double mu_chosen = muFunc(mCurrBCIdx); // or does it need to be mCurrBCIdx
249 int ncoll = 0;
250 do {
251 ncoll = gRandom->Poisson(mu_chosen);
252 } while (ncoll == 0);
253
254 // assign random time withing a bunch
255 for (int i = ncoll; i--;) {
257 }
258 if (ncoll > 1) { // sort in DECREASING time order (we are reading vector from the end)
259 std::sort(mTimeInBC.begin(), mTimeInBC.end(), [](const float a, const float b) { return a > b; });
260 }
261 return ncoll;
262}
uint64_t bc
Definition RawEventData.h:5
int32_t i
int getNBunches(int dir=-1) const
bool testBC(int bcID, int dir=-1) const
static BunchFilling * loadFrom(const std::string &fileName, const std::string &objName="")
void initialize(const RandomType randomType=RandomType::Gaus)
Definition RandomRing.h:145
o2::InteractionTimeRecord mFirstIR
static constexpr float DefIntRate
default interaction rate
std::vector< uint16_t > mInteractingBCs
o2::BunchFilling mBCFilling
patter of active BCs
o2::math_utils::RandomRing< 10000 > mBCJumpGenerator
float mBCTimeRMS
BC time spread in NANOSECONDS.
double mMuBC
interaction probability per BC
o2::math_utils::RandomRing< 1000 > mNCollBCGenerator
o2::math_utils::RandomRing< 1000 > mCollTimeGenerator
std::vector< float > mTimeInBC
interaction times within single BC
int mCurrBCIdx
counter for current interacting bunch
const o2::InteractionTimeRecord & generateCollisionTime()
o2::InteractionTimeRecord mIR
void setBunchFilling(const BunchFilling &bc)
float mIntRate
total interaction rate in Hz
int mIntBCCache
N interactions left for current BC.
std::vector< float > determineBCIntensityScalesFromHistogram(const TH1F &scales_from_histo)
bool setBCIntensityScales(const std::vector< float > &scales_from_vector)
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLdouble n
Definition glcorearb.h:1982
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLintptr offset
Definition glcorearb.h:660
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
constexpr double LHCRevFreq
uint16_t bc
bunch crossing ID of interaction
double timeInBCNS
time in NANOSECONDS relative to orbit/bc
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"