Belle II Software  release-06-02-00
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 include
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 // coordinates translation
31 #include <iostream>
32 #include <TGeoMatrix.h>
33 #include <generators/SAD/ReaderSAD.h>
34 
35 using namespace std;
36 
37 namespace Belle2 {
43  //-----------------------------------------------------------------
44  // Register module
45  //-----------------------------------------------------------------
46 
47  REG_MODULE(BeamBkgGenerator)
48 
49  //-----------------------------------------------------------------
50  // Implementation
51  //-----------------------------------------------------------------
52 
54  {
55  // set module description
56  setDescription("Beam background generator based on SAD files. "
57  "The generator picks up particles from the SAD file randomly "
58  "according to their rates. "
59  "Number of events is determined from 'realTime' and overall rate, and "
60  "the generator terminates the execution when this number is reached.");
61 
62  // Add parameters
63  addParam("fileName", m_fileName, "name of the SAD file converted to root");
64  addParam("treeName", m_treeName, "name of the TTree in the SAD file", string("sad"));
65  addParam("ringName", m_ringName, "name of the superKEKB ring (LER or HER)");
66  addParam("realTime", m_realTime,
67  "equivalent superKEKB running time to generate sample [ns].");
68  }
69 
70  BeamBkgGeneratorModule::~BeamBkgGeneratorModule()
71  {
72  }
73 
74  void BeamBkgGeneratorModule::initialize()
75  {
76  // register MCParticles
77 
78  StoreArray<MCParticle> mcParticles;
79  mcParticles.registerInDataStore();
80 
81  StoreArray<SADMetaHit> sadHits;
82  sadHits.registerInDataStore();
83 
84 
85  // check steering parameters
86 
87  if (m_ringName != "LER" and m_ringName != "HER") {
88  B2ERROR("ringName can only be LER or HER");
89  }
90  if (m_realTime <= 0) {
91  B2ERROR("realTime must be positive");
92  }
93 
94  // open SAD file and get TTree
95 
96  m_file = TFile::Open(m_fileName.c_str());
97  if (!m_file) {
98  B2ERROR(m_fileName << ": can't open file");
99  return;
100  }
101  m_tree = (TTree*) m_file->Get(m_treeName.c_str());
102  if (!m_tree) {
103  B2ERROR(m_treeName << ": no such TTree in the SAD file");
104  return;
105  }
106 
107  m_tree->SetBranchAddress("s", &m_sad.s);
108  m_tree->SetBranchAddress("x", &m_sad.x);
109  m_tree->SetBranchAddress("px", &m_sad.px);
110  m_tree->SetBranchAddress("y", &m_sad.y);
111  m_tree->SetBranchAddress("py", &m_sad.py);
112  m_tree->SetBranchAddress("E", &m_sad.E);
113  m_tree->SetBranchAddress("rate", &m_sad.rate);
114 
115  // for SADMetaHit
116  m_tree->SetBranchAddress("ss", &m_sad.ss);
117  m_tree->SetBranchAddress("sraw", &m_sad.sraw);
118  m_tree->SetBranchAddress("ssraw", &m_sad.ssraw);
119  m_tree->SetBranchAddress("nturn", &m_sad.nturn);
120  m_tree->SetBranchAddress("xraw", &m_sad.xraw);
121  m_tree->SetBranchAddress("yraw", &m_sad.yraw);
122  m_tree->SetBranchAddress("r", &m_sad.r);
123  m_tree->SetBranchAddress("rr", &m_sad.rr);
124  m_tree->SetBranchAddress("dp_over_p0", &m_sad.dp_over_p0);
125  m_tree->SetBranchAddress("watt", &m_sad.watt);
126 
127  int numEntries = m_tree->GetEntries();
128  if (numEntries <= 0) {
129  B2ERROR("SAD tree is empty");
130  return;
131  }
132 
133  // construct vector of cumulative rates and determine number of events to generate
134 
135  m_rates.push_back(0);
136  for (int i = 0; i < numEntries; i++) {
137  m_tree->GetEntry(i);
138  m_rates.push_back(m_sad.rate + m_rates.back());
139  m_counters.push_back(0);
140  }
141 
142  m_numEvents = gRandom->Poisson(m_rates.back() * m_realTime / Unit::s);
143 
144  // set rotation from SAD to Belle II
145 
146  if (m_ringName == "LER") {
147  GearDir ring("/Detector/SuperKEKB/LER/");
148  m_rotation.RotateY(ring.getAngle("angle"));
149  m_ring = 2;
150  } else {
151  GearDir ring("/Detector/SuperKEKB/HER/");
152  m_rotation.RotateY(ring.getAngle("angle"));
153  m_ring = 1;
154  }
155 
156  m_sectionOrdering.insert(m_sectionOrdering.end(), {1, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2});
157 
158  B2RESULT("BG rate: " << m_rates.back() / 1e6 << " MHz, events to generate: "
159  << m_numEvents);
160 
161  }
162 
163  void BeamBkgGeneratorModule::beginRun()
164  {
165  }
166 
167  void BeamBkgGeneratorModule::event()
168  {
169 
170  // check event counter
171 
172  if (m_eventCounter >= m_numEvents) {
173  StoreObjPtr<EventMetaData> eventMetaData;
174  eventMetaData->setEndOfData(); // stop event processing
175  return;
176  }
177  m_eventCounter++;
178 
179  // get SAD entry
180 
181  int i = generateEntry();
182  m_tree->GetEntry(i);
183  m_counters[i]++;
184 
185  // make SADMetaHit
186  int ring_section = -1;
187  double ssraw = m_sad.ss;
188  if (m_sad.ss < 0) ssraw += 3016.;
189  int section = (int)(ssraw * 12 / 3016.);
190  if ((unsigned)section < m_sectionOrdering.size()) ring_section = m_sectionOrdering[section];
191 
192  StoreArray<SADMetaHit> SADMetaHits;
193  SADMetaHits.appendNew(SADMetaHit(m_sad.ssraw, m_sad.sraw, m_sad.ss, m_sad.s,
194  0., m_sad.nturn,
195  m_sad.x, m_sad.y, m_sad.px, m_sad.py, m_sad.xraw, m_sad.yraw,
196  m_sad.r, m_sad.rr, m_sad.dp_over_p0, m_sad.E, m_sad.rate,
197  m_sad.watt, m_ring, ring_section));
198 
199 
200  // transform to Belle II (flip sign of y and s, rotate)
201 
202  TVector3 position(m_sad.x * Unit::m, -m_sad.y * Unit::m, -m_sad.s * Unit::m);
203  position.Transform(m_rotation);
204 
205  double pz = sqrt(m_sad.E * m_sad.E - m_sad.px * m_sad.px - m_sad.py * m_sad.py);
206  if (m_ringName == "LER") pz = -pz;
207  TVector3 momentum(m_sad.px, -m_sad.py, pz);
208  momentum.Transform(m_rotation);
209 
210  // PDG code and mass
211 
212  int pdgCode = Const::electron.getPDGCode();
213  double mass = Const::electron.getMass();
214  if (m_ringName == "LER") pdgCode = -pdgCode;
215 
216  // append SAD particle to MCParticles
217 
218  StoreArray<MCParticle> MCParticles;
219  MCParticle* part = MCParticles.appendNew();
220  part->setPDG(pdgCode);
221  part->setMass(mass);
222  part->setProductionVertex(position);
223  part->setProductionTime(0);
224  part->setMomentum(momentum);
225  part->setEnergy(sqrt(momentum.Mag2() + mass * mass));
226  part->setValidVertex(true);
227  part->setStatus(MCParticle::c_PrimaryParticle);
228  part->addStatus(MCParticle::c_StableInGenerator);
229 
230  // FarBeamLine region transformation
231  if (abs(m_sad.s * Unit::m) > 4.0 * Unit::m) {
232  // initial coordinates in SAD space
233  double particlePosSADfar[] = {m_sad.x* Unit::m, -m_sad.y* Unit::m, 0.0 * Unit::m};
234  double particleMomSADfar[] = {m_sad.px* Unit::GeV, -m_sad.py* Unit::GeV, pz* Unit::GeV};
235  // final coordinates in Geant4 space
236  double particlePosGeant4[] = {0.0, 0.0, 0.0};
237  double particleMomGeant4[] = {0.0, 0.0, 0.0};
238 
239  // create a transformation matrix for a given ring
240  TGeoHMatrix transMatrix;
241  if (m_ringName == "LER") {
242  transMatrix = m_readerSAD.SADtoGeant(ReaderSAD::c_LER, m_sad.s * Unit::m);
243  } else {
244  transMatrix = m_readerSAD.SADtoGeant(ReaderSAD::c_HER, m_sad.s * Unit::m);
245  }
246 
247  // calculate a new set of coordinates in Geant4 space
248  transMatrix.LocalToMaster(particlePosSADfar, particlePosGeant4); // position
249  transMatrix.LocalToMasterVect(particleMomSADfar, particleMomGeant4); // momentum
250  // apply a new set of coordinates
251  part->setMomentum(TVector3(particleMomGeant4));
252  part->setProductionVertex(TVector3(particlePosGeant4));
253  }
254  }
255 
256  void BeamBkgGeneratorModule::endRun()
257  {
258  }
259 
260  void BeamBkgGeneratorModule::terminate()
261  {
262  // close SAD file
263  m_file->Close();
264 
265  B2RESULT("BG rate: " << m_rates.back() / 1e6 << " MHz, equivalent time: "
266  << m_realTime / Unit::us << " us, "
267  << m_eventCounter << " events generated");
268  if (m_eventCounter != m_numEvents)
269  B2ERROR("Number of generated events does not match the equivalent running time: "
270  << m_numEvents << " events needed, but "
271  << m_eventCounter << " generated");
272 
273  int imax = 0;
274  double average = 0;
275  for (unsigned i = 0; i < m_counters.size(); i++) {
276  if (m_counters[i] > m_counters[imax]) imax = i;
277  average += m_counters[i];
278  }
279  average /= m_counters.size();
280  B2RESULT("SAD particle usage: on average " << average << " times, max "
281  << m_counters[imax] << " times (entry " << imax << ")");
282 
283  }
284 
285 
286  int BeamBkgGeneratorModule::generateEntry() const
287  {
288  double rate = gRandom->Uniform(m_rates.back());
289  int i1 = 0;
290  int i2 = m_rates.size() - 1;
291  while (i2 - i1 > 1) {
292  int i = (i1 + i2) / 2;
293  if (rate > m_rates[i]) {
294  i1 = i;
295  } else {
296  i2 = i;
297  }
298  }
299  return i1;
300  }
301 
303 } // end Belle2 namespace
304 
Beam background generator based on SAD files.
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
Base class for Modules.
Definition: Module.h:72
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.
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:95
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
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.