Belle II Software development
BeamBkgGeneratorModule.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9// Own header.
10#include <background/modules/BeamBkgGenerator/BeamBkgGeneratorModule.h>
11
12// framework - DataStore
13#include <framework/datastore/StoreArray.h>
14#include <framework/datastore/StoreObjPtr.h>
15
16// framework aux
17#include <framework/gearbox/Unit.h>
18#include <framework/gearbox/Const.h>
19#include <framework/logging/Logger.h>
20#include <framework/gearbox/GearDir.h>
21
22// data objects
23#include <framework/dataobjects/EventMetaData.h>
24#include <mdst/dataobjects/MCParticle.h>
25#include <generators/SAD/dataobjects/SADMetaHit.h>
26
27// random generator
28#include <TRandom.h>
29
30#include <Math/VectorUtil.h>
31
32// coordinates translation
33#include <iostream>
34#include <TGeoMatrix.h>
35#include <generators/SAD/ReaderSAD.h>
36
37using namespace std;
38using namespace Belle2;
39
40//-----------------------------------------------------------------
41// Register module
42//-----------------------------------------------------------------
43
44REG_MODULE(BeamBkgGenerator);
45
46//-----------------------------------------------------------------
47// Implementation
48//-----------------------------------------------------------------
49
51{
52 // set module description
53 setDescription("Beam background generator based on SAD files. "
54 "The generator picks up particles from the SAD file randomly "
55 "according to their rates. "
56 "Number of events is determined from 'realTime' and overall rate, and "
57 "the generator terminates the execution when this number is reached.");
58
59 // Add parameters
60 addParam("fileName", m_fileName, "name of the SAD file converted to root");
61 addParam("treeName", m_treeName, "name of the TTree in the SAD file", string("sad"));
62 addParam("ringName", m_ringName, "name of the superKEKB ring (LER or HER)");
63 addParam("realTime", m_realTime,
64 "equivalent superKEKB running time to generate sample [ns].");
65}
66
68{
69}
70
72{
73 // register MCParticles
74
75 StoreArray<MCParticle> mcParticles;
76 mcParticles.registerInDataStore();
77
79 sadHits.registerInDataStore();
80
81
82 // check steering parameters
83
84 if (m_ringName != "LER" and m_ringName != "HER") {
85 B2ERROR("ringName can only be LER or HER");
86 }
87 if (m_realTime <= 0) {
88 B2ERROR("realTime must be positive");
89 }
90
91 // open SAD file and get TTree
92
93 m_file = TFile::Open(m_fileName.c_str());
94 if (!m_file) {
95 B2ERROR(m_fileName << ": can't open file");
96 return;
97 }
98 m_tree = (TTree*) m_file->Get(m_treeName.c_str());
99 if (!m_tree) {
100 B2ERROR(m_treeName << ": no such TTree in the SAD file");
101 return;
102 }
103
104 m_tree->SetBranchAddress("s", &m_sad.s);
105 m_tree->SetBranchAddress("x", &m_sad.x);
106 m_tree->SetBranchAddress("px", &m_sad.px);
107 m_tree->SetBranchAddress("y", &m_sad.y);
108 m_tree->SetBranchAddress("py", &m_sad.py);
109 m_tree->SetBranchAddress("E", &m_sad.E);
110 m_tree->SetBranchAddress("rate", &m_sad.rate);
111
112 // for SADMetaHit
113 m_tree->SetBranchAddress("ss", &m_sad.ss);
114 m_tree->SetBranchAddress("sraw", &m_sad.sraw);
115 m_tree->SetBranchAddress("ssraw", &m_sad.ssraw);
116 m_tree->SetBranchAddress("nturn", &m_sad.nturn);
117 m_tree->SetBranchAddress("xraw", &m_sad.xraw);
118 m_tree->SetBranchAddress("yraw", &m_sad.yraw);
119 m_tree->SetBranchAddress("r", &m_sad.r);
120 m_tree->SetBranchAddress("rr", &m_sad.rr);
121 m_tree->SetBranchAddress("dp_over_p0", &m_sad.dp_over_p0);
122 m_tree->SetBranchAddress("watt", &m_sad.watt);
123
124 int numEntries = m_tree->GetEntries();
125 if (numEntries <= 0) {
126 B2ERROR("SAD tree is empty");
127 return;
128 }
129
130 // construct vector of cumulative rates and determine number of events to generate
131
132 m_rates.push_back(0);
133 for (int i = 0; i < numEntries; i++) {
134 m_tree->GetEntry(i);
135 m_rates.push_back(m_sad.rate + m_rates.back());
136 m_counters.push_back(0);
137 }
138
139 m_numEvents = gRandom->Poisson(m_rates.back() * m_realTime / Unit::s);
140
141 // set rotation from SAD to Belle II
142
143 if (m_ringName == "LER") {
144 GearDir ring("/Detector/SuperKEKB/LER/");
145 m_rotation.SetAngle(ring.getAngle("angle"));
146 m_ring = 2;
147 } else {
148 GearDir ring("/Detector/SuperKEKB/HER/");
149 m_rotation.SetAngle(ring.getAngle("angle"));
150 m_ring = 1;
151 }
152
153 m_sectionOrdering.insert(m_sectionOrdering.end(), {1, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2});
154
155 B2RESULT("BG rate: " << m_rates.back() / 1e6 << " MHz, events to generate: "
156 << m_numEvents);
157
158}
159
161{
162}
163
165{
166
167 // check event counter
168
170 StoreObjPtr<EventMetaData> eventMetaData;
171 eventMetaData->setEndOfData(); // stop event processing
172 return;
173 }
175
176 // get SAD entry
177
178 int i = generateEntry();
179 m_tree->GetEntry(i);
180 m_counters[i]++;
181
182 // make SADMetaHit
183 int ring_section = -1;
184 double ssraw = m_sad.ss;
185 if (m_sad.ss < 0) ssraw += 3016.;
186 int section = (int)(ssraw * 12 / 3016.);
187 if ((unsigned)section < m_sectionOrdering.size()) ring_section = m_sectionOrdering[section];
188
189 StoreArray<SADMetaHit> SADMetaHits;
191 0., m_sad.nturn,
194 m_sad.watt, m_ring, ring_section));
195
196
197 // transform to Belle II (flip sign of y and s, rotate)
198
199 ROOT::Math::XYZVector position(m_sad.x * Unit::m, -m_sad.y * Unit::m, -m_sad.s * Unit::m);
200 position = m_rotation * position;
201
202 double pz = sqrt(m_sad.E * m_sad.E - m_sad.px * m_sad.px - m_sad.py * m_sad.py);
203 if (m_ringName == "LER") pz = -pz;
204 ROOT::Math::XYZVector momentum(m_sad.px, -m_sad.py, pz);
205 momentum = m_rotation * momentum;
206
207 // PDG code and mass
208
209 int pdgCode = Const::electron.getPDGCode();
210 double mass = Const::electron.getMass();
211 if (m_ringName == "LER") pdgCode = -pdgCode;
212
213 // append SAD particle to MCParticles
214
215 StoreArray<MCParticle> MCParticles;
216 MCParticle* part = MCParticles.appendNew();
217 part->setPDG(pdgCode);
218 part->setMass(mass);
219 part->setProductionVertex(position);
220 part->setProductionTime(0);
221 part->setMomentum(momentum);
222 part->setEnergy(sqrt(momentum.Mag2() + mass * mass));
223 part->setValidVertex(true);
226
227 // FarBeamLine region transformation
228 if (abs(m_sad.s * Unit::m) > 4.0 * Unit::m) {
229 // initial coordinates in SAD space
230 double particlePosSADfar[] = {m_sad.x* Unit::m, -m_sad.y* Unit::m, 0.0 * Unit::m};
231 double particleMomSADfar[] = {m_sad.px* Unit::GeV, -m_sad.py* Unit::GeV, pz* Unit::GeV};
232 // final coordinates in Geant4 space
233 double particlePosGeant4[] = {0.0, 0.0, 0.0};
234 double particleMomGeant4[] = {0.0, 0.0, 0.0};
235
236 // create a transformation matrix for a given ring
237 TGeoHMatrix transMatrix;
238 if (m_ringName == "LER") {
240 } else {
242 }
243
244 // calculate a new set of coordinates in Geant4 space
245 transMatrix.LocalToMaster(particlePosSADfar, particlePosGeant4); // position
246 transMatrix.LocalToMasterVect(particleMomSADfar, particleMomGeant4); // momentum
247 // apply a new set of coordinates
248 part->setMomentum(ROOT::Math::XYZVector(particleMomGeant4[0], particleMomGeant4[1], particleMomGeant4[2]));
249 part->setProductionVertex(ROOT::Math::XYZVector(particlePosGeant4[0], particlePosGeant4[1], particlePosGeant4[2]));
250 }
251}
252
254{
255}
256
258{
259 // close SAD file
260 m_file->Close();
261
262 B2RESULT("BG rate: " << m_rates.back() / 1e6 << " MHz, equivalent time: "
263 << m_realTime / Unit::us << " us, "
264 << m_eventCounter << " events generated");
266 B2ERROR("Number of generated events does not match the equivalent running time: "
267 << m_numEvents << " events needed, but "
268 << m_eventCounter << " generated");
269
270 int imax = 0;
271 double average = 0;
272 for (unsigned i = 0; i < m_counters.size(); i++) {
273 if (m_counters[i] > m_counters[imax]) imax = i;
274 average += m_counters[i];
275 }
276 average /= m_counters.size();
277 B2RESULT("SAD particle usage: on average " << average << " times, max "
278 << m_counters[imax] << " times (entry " << imax << ")");
279
280}
281
282
284{
285 double rate = gRandom->Uniform(m_rates.back());
286 int i1 = 0;
287 int i2 = m_rates.size() - 1;
288 while (i2 - i1 > 1) {
289 int i = (i1 + i2) / 2;
290 if (rate > m_rates[i]) {
291 i1 = i;
292 } else {
293 i2 = i;
294 }
295 }
296 return i1;
297}
std::vector< int > m_counters
counters: how many times SAD particles are used
virtual void initialize() override
Initialize the Module.
virtual ~BeamBkgGeneratorModule()
Destructor.
virtual void event() override
Event processor.
virtual void endRun() override
End-of-run action.
ReaderSAD m_readerSAD
the transformation from SAD to Belle II system for the far beamline
std::vector< double > m_rates
cumulative rates of SAD particles [Hz]
virtual void terminate() override
Termination action.
ROOT::Math::RotationY m_rotation
rotation from SAD to Belle II frame
std::string m_fileName
name of the SAD file converted to root
int generateEntry() const
Pick up particle randomly from the SAD file according to its rate.
int m_ring
ring number, 1-HER, 2-LER
int m_numEvents
number of events to generate
double m_realTime
equivalent SuperKEKB running time in [ns]
virtual void beginRun() override
Called when entering a new run.
std::vector< int > m_sectionOrdering
superKEKB section ordering
std::string m_ringName
name of the superKEKB ring (LER or HER)
std::string m_treeName
name of the TTree in the SAD file
int getPDGCode() const
PDG code.
Definition: Const.h:473
double getMass() const
Particle mass.
Definition: UnitConst.cc:356
static const ChargedStable electron
electron particle
Definition: Const.h:659
GearDir is the basic class used for accessing the parameter store.
Definition: GearDir.h:31
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
@ c_StableInGenerator
bit 1: Particle is stable, i.e., not decaying in the generator.
Definition: MCParticle.h:49
void setMass(float mass)
Set particle mass.
Definition: MCParticle.h:366
void addStatus(unsigned short int bitmask)
Add bitmask to current status.
Definition: MCParticle.h:353
void setEnergy(float energy)
Set energy.
Definition: MCParticle.h:372
void setValidVertex(bool valid)
Set indication wether vertex and time information is valid or just default.
Definition: MCParticle.h:378
void setProductionVertex(const ROOT::Math::XYZVector &vertex)
Set production vertex position.
Definition: MCParticle.h:396
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:335
void setMomentum(const ROOT::Math::XYZVector &momentum)
Set particle momentum.
Definition: MCParticle.h:417
void setStatus(unsigned short int status)
Set Status code for the particle.
Definition: MCParticle.h:346
void setProductionTime(float time)
Set production time.
Definition: MCParticle.h:384
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
TGeoHMatrix SADtoGeant(ReaderSAD::AcceleratorRings accRing, double s)
Transformation matrix.
Definition: ReaderSAD.cc:416
@ c_HER
High Energy Ring (electrons)
Definition: ReaderSAD.h:47
@ c_LER
Low Energy Ring (positrons)
Definition: ReaderSAD.h:48
ClassSADMetaHit - digitization simulated metahit for the SAD detector.
Definition: SADMetaHit.h:25
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
static const double us
[microsecond]
Definition: Unit.h:97
static const double m
[meters]
Definition: Unit.h:69
static const double s
[second]
Definition: Unit.h:95
static const double GeV
Standard of [energy, momentum, mass].
Definition: Unit.h:51
double getAngle(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard angle unit.
Definition: Interface.h:299
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.
STL namespace.
int nturn
number of turns from scattered to lost
double E
E at lost position [GeV] (in fact momentum magnitude!)
double sraw
s at lost position [m] before matching G4 beam pipe inner surface
double ss
scattered position (|s|<Ltot/2) [m]
double yraw
y at lost position [m] before matching G4 beam pipe inner surface
double rr
sqrt(xraw*xraw+yraw*yraw) [m]
double dp_over_p0
momentum deviation of the lost particle
double xraw
x at lost position [m] before matching G4 beam pipe inner surface
double s
lost position measured from IP along the ring [m]