Belle II Software  release-08-01-10
ReaderSAD.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 #include <generators/SAD/ReaderSAD.h>
10 
11 #include <framework/logging/Logger.h>
12 #include <framework/gearbox/Unit.h>
13 #include <framework/gearbox/GearDir.h>
14 #include <mdst/dataobjects/MCParticle.h>
15 
16 #include <generators/SAD/dataobjects/SADMetaHit.h>
17 
18 // framework - DataStore
19 #include <framework/datastore/StoreArray.h>
20 
21 #include <TRandom3.h>
22 #include <iostream>
23 
24 using namespace std;
25 using namespace Belle2;
26 
27 
28 ReaderSAD::ReaderSAD(): m_file(NULL), m_tree(NULL), m_transMatrix(NULL),
29  m_sRange(3000.0), m_accRing(ReaderSAD::c_LER), m_pxRes(0.01), m_pyRes(0.01),
30  m_SADToRealFactor(5.76e6), m_readoutTime(20.0), m_realPartNum(0),
31  m_realPartEntry(0), m_readEntry(0)
32 {
33  m_lostX = 0.0;
34  m_lostY = 0.0;
35  m_lostS = 0.0;
36  m_lostPx = 0.0;
37  m_lostPy = 0.0;
38  m_lostRate = 0.0;
39  m_lostE = 0.0;
40 
41  //Start my addition
42  m_inputSAD_ssraw = 0;
43  m_inputSAD_sraw = 0;
44  m_inputSAD_ss = 0;
45  m_inputSAD_s = 0;
46  m_inputSAD_Lss = 0;
47  m_inputSAD_nturn = 0;
48  m_inputSAD_x = 0;
49  m_inputSAD_y = 0;
50  m_inputSAD_px = 0;
51  m_inputSAD_py = 0;
52  m_inputSAD_xraw = 0;
53  m_inputSAD_yraw = 0;
54  m_inputSAD_r = 0;
55  m_inputSAD_rr = 0;
57  m_inputSAD_E = 0;
58  m_inputSAD_rate = 0;
59  m_inputSAD_watt = 0;
60  //End my addition
61 }
62 
63 
65 {
66  // comment out the following line for the march 16 build (TF)
67  // if (m_file != NULL) m_file->Close();
68 }
69 
70 
71 void ReaderSAD::initialize(TGeoHMatrix* transMatrix, double sRange, ReaderSAD::AcceleratorRings accRing, double readoutTime)
72 {
73  m_transMatrix = transMatrix;
74  m_sRange = sRange;
75  m_accRing = accRing;
76  m_readoutTime = readoutTime;
77 }
78 
79 
80 void ReaderSAD::open(const string& filename)
81 {
82  if (m_file != NULL) {
83  m_file->Close();
84  delete m_file;
85  }
86 
87  m_file = new TFile(filename.c_str(), "READ");
88  if (m_file == NULL) throw(SADCouldNotOpenFileError() << filename);
89 
90  m_file->cd("");
91  m_tree = dynamic_cast<TTree*>(m_file->Get("tp"));
92  if (m_tree == NULL) throw(SADCouldNotOpenFileError() << filename);
93 
94  m_tree->SetBranchAddress("x", &m_lostX);
95  m_tree->SetBranchAddress("y", &m_lostY);
96  m_tree->SetBranchAddress("s", &m_lostS);
97  m_tree->SetBranchAddress("px", &m_lostPx);
98  m_tree->SetBranchAddress("py", &m_lostPy);
99  m_tree->SetBranchAddress("rate", &m_lostRate);
100  m_tree->SetBranchAddress("E", &m_lostE);
101 
102  m_tree->SetBranchAddress("ssraw", &m_inputSAD_ssraw);
103  m_tree->SetBranchAddress("sraw", &m_inputSAD_sraw);
104  m_tree->SetBranchAddress("ss", &m_inputSAD_ss);
105  m_tree->SetBranchAddress("Lss", &m_inputSAD_Lss);
106  m_tree->SetBranchAddress("nturn", &m_inputSAD_nturn);
107  m_tree->SetBranchAddress("xraw", &m_inputSAD_xraw);
108  m_tree->SetBranchAddress("yraw", &m_inputSAD_yraw);
109  m_tree->SetBranchAddress("r", &m_inputSAD_r);
110  m_tree->SetBranchAddress("rr", &m_inputSAD_rr);
111  m_tree->SetBranchAddress("dp_over_p0", &m_inputSAD_dp_over_p0);
112  m_tree->SetBranchAddress("watt", &m_inputSAD_watt);
113 
114  m_readEntry = -1;
115 
117  hit.registerInDataStore();
118 
119 }
120 
121 
123 {
124  if (m_tree == NULL) {
125  B2ERROR("The SAD tree doesn't exist !");
126  return -1;
127  }
128 
129  do {
130  m_readEntry++;
131 
132  //Check for end of file
133  if (m_readEntry >= m_tree->GetEntries()) throw SADEndOfFile();
134 
135  //Load the SAD particle
136  m_tree->GetEntry(m_readEntry);
138  B2DEBUG(10, "> Read particle " << m_readEntry + 1 << "/" << m_tree->GetEntries() << " with s = " << m_lostS << " cm" <<
139  " and rate = " << m_lostRate << " Hz");
140 
141  //printf("Read particle %d / %d with s= %f [m]\n", m_readEntry + 1 , (int)m_tree->GetEntries(), m_lostS / 100.);
142 
143  double zMom2 = m_lostE * m_lostE - m_lostPx * m_lostPx - m_lostPy * m_lostPy ;
144  if (zMom2 < 0) printf("zMom2= %f is negative. Skipped!\n", zMom2);
145 
146  } while ((fabs(m_lostS) > m_sRange) or (m_lostE * m_lostE - m_lostPx * m_lostPx - m_lostPy * m_lostPy < 0));
147 
148 // do {
149 // //Check for end of file
150 // m_readEntry++;
151 // if (m_readEntry >= m_tree->GetEntries()) throw SADEndOfFile();
152 //
153 // //Load the SAD particle
154 // m_tree->GetEntry(m_readEntry);
155 // convertParamsToSADUnits();
156 //
157 // B2DEBUG(10, "> Read particle " << m_readEntry + 1 << "/" << m_tree->GetEntries() << " with s = " << m_lostS << " cm" << " and rate = " << m_lostRate << " Hz" )
158 // } while (fabs(m_lostS) > m_sRange);
159 
161  return m_lostRate;
162 }
163 
164 
166 {
167  if (m_tree == NULL) {
168  B2ERROR("The SAD tree doesn't exist !");
169  return false;
170  }
171 
172  //Check for end of file
173  if ((m_readEntry >= m_tree->GetEntries()) || (m_tree->GetEntries() == 0)) throw SADEndOfFile();
174 
175  //Check if the number of the real particles is reached
177  m_realPartEntry = 0;
178  m_realPartNum = 0;
179  }
180 
181  //Check if a new SAD particle has to be read from the file
182  if (m_realPartNum == 0) {
183  //Read only SAD particles which are inside the chosen sRange
184  do {
185  m_readEntry++;
186  if (m_readEntry >= m_tree->GetEntries()) throw SADEndOfFile();
187 
188  m_tree->GetEntry(m_readEntry);
190 
191  B2DEBUG(10, "> Read particle " << m_readEntry + 1 << "/" << m_tree->GetEntries() << " with s = " << m_lostS << " cm" <<
192  " and rate = " << m_lostRate << " Hz");
193  } while ((fabs(m_lostS) > m_sRange) && (m_readEntry < m_tree->GetEntries()));
194 
195  if (fabs(m_lostS) <= m_sRange)
197  }
198 
199  //Create a new real particle from the SAD particle
200  if ((fabs(m_lostS) <= m_sRange) && (m_realPartNum > 0)) {
202  B2DEBUG(10, "* Created real particle " << m_realPartEntry + 1 << "/" << m_realPartNum << " for SAD particle " << m_readEntry + 1 <<
203  "/" << m_tree->GetEntries());
204  }
205 
206  m_realPartEntry++;
207 
208  return true;
209 }
210 
211 
213 {
214  if (m_tree == NULL) {
215  B2ERROR("The SAD tree doesn't exist !");
216  return ;
217  }
218 
219  int nPart = m_tree->GetEntries();
220 
221  for (int iPart = 0; iPart < nPart; ++iPart) {
222  m_tree->GetEntry(iPart);
224  if (fabs(m_lostS) <= m_sRange) addParticleToMCParticles(graph);
225 
226  //std::cout << " in sad " << m_inputSAD_sraw << std::endl;
227 
228  }
229 }
230 
231 
232 //======================================================================
233 // Private methods
234 //======================================================================
235 
237 {
238  m_lostX = m_lostX * Unit::m;
239  m_lostY = m_lostY * Unit::m;
240  m_lostS = m_lostS * Unit::m;
243 
244  //Start my addition
249  //m_inputSAD_Lss
250  //m_inputSAD_nturn
257  //m_inputSAD_r
258  //m_inputSAD_rr
259  //m_inputSAD_dp_over_p0
260  //m_inputSAD_E
261  //m_inputSAD_rate
262  //End my addition
263 }
264 
265 
266 void ReaderSAD::addParticleToMCParticles(MCParticleGraph& graph, bool gaussSmearing)
267 {
268  double particlePosSAD[3] = {0.0, 0.0, 0.0};
269  double particlePosSADfar[3] = {0.0, 0.0, 0.0};
270  double particlePosGeant4[3] = {0.0, 0.0, 0.0};
271  double particleMomSAD[3] = {0.0, 0.0, 0.0};
272  double particleMomGeant4[3] = {0.0, 0.0, 0.0};
273 
274  //Add particle to MCParticle collection
275  MCParticleGraph::GraphParticle& particle = graph.addParticle();
276  particle.setStatus(MCParticle::c_PrimaryParticle);
277 
278  switch (m_accRing) {
279  case c_HER: particle.setPDG(11); //electrons
280  break;
281  case c_LER: particle.setPDG(-11); //positrons
282  break;
283  }
284 
285  particle.setMassFromPDG();
286 
287  //Convert the position of the particle from local SAD space to global geant4 space.
288  //Flip the sign for the y and z component to go from the accelerator to the detector coordinate system.
289  particlePosSAD[0] = m_lostX;
290  particlePosSAD[1] = -m_lostY;
291  particlePosSAD[2] = -m_lostS;
292 
293  particlePosSADfar[0] = m_lostX;
294  particlePosSADfar[1] = -m_lostY;
295  particlePosSADfar[2] = 0;
296 
297 
298  static GearDir content = Gearbox::getInstance().getDetectorComponent("FarBeamLine");
299  if (!content)
300  B2FATAL("You need FarBeamLine.xml to run SADInput module. Please include FarBeamLine.xml in Belle2.xml. You also need to change 'length' in Belle2.xml to be 40m.");
301 
302  TGeoHMatrix* m_transMatrix2 = new TGeoHMatrix(SADtoGeant(m_accRing, m_lostS)); //overwrite m_transMatrix given by initialize()
303 
304  if (abs(m_lostS) <= 400.) { //4m
305  m_transMatrix->LocalToMaster(particlePosSAD, particlePosGeant4);
306  } else {
307  m_transMatrix2->LocalToMaster(particlePosSADfar, particlePosGeant4);
308  }
309 
310  //Convert the momentum of the particle from local SAD space to global geant4 space.
311  //Flip the sign for the y and z component to go from the accelerator to the detector coordinate system.
312  //Calculate the missing pz by using the energy of the particle at the position where it has been lost.
313  //double totalMomSqr = (m_lostE * m_lostE - (particle.getMass() * particle.getMass()));
314  double totalMomSqr = m_lostE * m_lostE; // SAD output "E" is "P", in fact.
315 
316  if (gaussSmearing) {
317  particleMomSAD[0] = gRandom->Gaus(m_lostPx, m_pxRes * m_lostPx); //1% px resolution
318  particleMomSAD[1] = -1.0 * gRandom->Gaus(m_lostPy, m_pyRes * m_lostPy);
319  } else {
320  particleMomSAD[0] = m_lostPx;
321  particleMomSAD[1] = -m_lostPy;
322  }
323 
324  double zMom = sqrt(totalMomSqr - (particleMomSAD[0] * particleMomSAD[0]) - (particleMomSAD[1] * particleMomSAD[1]));
325 
326  switch (m_accRing) {
327  case c_HER: particleMomSAD[2] = zMom;
328  break;
329  case c_LER: particleMomSAD[2] = -zMom;
330  break;
331  }
332 
333  int ring = 0;
334 
335  switch (m_accRing) {
336  case c_HER: ring = 1;
337  break;
338  case c_LER: ring = 2;
339  break;
340  }
341  /*
342  int ler_section[12] = {1, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2};
343  int ler_inf_section[12] = {0., 254.74, 498.59, 754.14, 1009.66, 1253.52, 1488.7, 1764.1, 2007.05, 2262.14, 2517.2, 2760.15};
344  int her_inf_section[12] = {254.32, 494.31, 750.25, 1009.24, 1249.24, 1488.43, 1763.68, 2002.77, 2258.25, 2516.78, 2755.87, 3011.33};
345  int her_section[12] = {1, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2};
346  int ler_sup_section[12] = {0., 254.61, 496.52, 727.23, 1007.7, 1249.3, 1479.82, 1761.31, 2003.88, 2239.89, 2516.31, 2758.89};
347  int her_sup_section[12] = {254.3, 495.32, 726.92, 1007.39, 1248.41, 1479.51, 1761, 2002.99, 2239.58, 2516, 2758, 3011.87};
348 
349  int section = -1;
350 
351  if (ring == 1) {
352  for (int i = 0; i < 12; i++) {
353  if (her_inf_section[i] <= (m_inputSAD_ssraw + 1500.) && (m_inputSAD_ssraw + 1500.) <= her_sup_section[i])
354  section = her_section[i] - 1;
355  }
356  } else if (ring == 2) {
357  for (int i = 0; i < 12; i++) {
358  if (ler_inf_section[i] <= (m_inputSAD_ssraw + 1500.) && (m_inputSAD_ssraw + 1500.) <= ler_sup_section[i])
359  section = ler_section[i] - 1;
360  }
361  }
362  */
363  //each rings have 12 section of ~250m
364  //the 1st section D01, the second section is D12, followed by D11, D10 .... for both rings
365  const int section_ordering[12] = {1, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2};
366  //int ring_section = section_ordering[(int)((m_inputSAD_ssraw + 1500.) / 12.)];
367  double ssraw = 0.;
368  if (ring == 1) {
369  if (m_inputSAD_ssraw >= 0) ssraw = m_inputSAD_ssraw / 100.;
370  else ssraw = 3000. + m_inputSAD_ssraw / 100.;
371  } else if (ring == 2) {
372  //if (m_inputSAD_ssraw >= 0) ssraw = 3000. - m_inputSAD_ssraw / 100.;
373  //else if (m_inputSAD_ssraw < 0) ssraw = -m_inputSAD_ssraw / 100.;
374  if (m_inputSAD_ssraw >= 0) ssraw = m_inputSAD_ssraw / 100.;
375  else ssraw = 3000. + m_inputSAD_ssraw / 100.;
376  }
377  int ring_section = section_ordering[(int)((ssraw) / 250.)];
378 
379  if (abs(m_lostS) <= 400.) {
380  m_transMatrix->LocalToMasterVect(particleMomSAD, particleMomGeant4);
381  } else {
382  m_transMatrix2->LocalToMasterVect(particleMomSAD, particleMomGeant4);
383  }
384 
385  //Set missing particle information
386  particle.setMomentum(ROOT::Math::XYZVector(particleMomGeant4[0], particleMomGeant4[1], particleMomGeant4[2]));
387  particle.setProductionVertex(ROOT::Math::XYZVector(particlePosGeant4[0], particlePosGeant4[1], particlePosGeant4[2]));
388  particle.setProductionTime(0.0);
389  particle.setEnergy(sqrt(m_lostE * m_lostE + particle.getMass()*particle.getMass()));
390  particle.setValidVertex(true);
391 
392  //Start my addition
393  StoreArray<SADMetaHit> SADMetaHits;
398  m_inputSAD_watt, ring, ring_section));
399  //End my addition
400 }
401 
402 
404 {
405  double numPart = rate * m_readoutTime / Unit::s; //readoutTime [ns]
406 
407  int numPart_int = static_cast<int>(floor(numPart));
408  double numPart_dec = numPart - numPart_int;
409 
410  double rnd = gRandom->Uniform(); //returns a random number in the interval ]0, 1]
411  if (rnd < numPart_dec) numPart_int += 1;
412 
413  return numPart_int;
414 }
415 
417 {
418  // 0<sraw<3016.3145 m
419  // -1500<s<1500 m
420 
421  //static double max_s_her = 3016.3145 * Unit::m;
422  //static double max_s_ler = 3016.3026 * Unit::m;
423 
424  //get parameters from .xml file
425  static GearDir content = Gearbox::getInstance().getDetectorComponent("FarBeamLine");
426 
427  map<string, straightElement> straights;
428  map<string, bendingElement> bendings;
429  for (const GearDir& element : content.getNodes("Straight")) {
430 
431  string name = element.getString("@name");
432  string type = element.getString("@type");
433 
434  if (type != "pipe") continue;
435 
436  straightElement straight;
437 
438  for (const GearDir& slot : element.getNodes("sec")) {
439  string nameSec = slot.getString("@name");
440  if (nameSec.find("X0") != std::string::npos) {straight.x0 = slot.getLength();}
441  if (nameSec.find("Z0") != std::string::npos) {straight.z0 = slot.getLength();}
442  if (nameSec.find("L") != std::string::npos) {straight.l = slot.getLength();}
443  if (nameSec.find("PHI") != std::string::npos) {straight.phi = slot.getAngle();}
444  }
445 
446  //straight.x0 = element.getLength("X0");
447  //straight.z0 = element.getLength("Z0");
448  //straight.l = element.getLength("L");
449  //straight.phi = element.getLength("PHI");
450 
451  straights[name] = straight;
452  }
453 
454  string str_checklist[] = {"LHR1", "LHR2", "LLR1", "LLR2", "LLR3", "LLR4", "LLR5", "LLR6", "LHL1", "LHL2", "LLL1", "LLL2", "LLL3", "LLL4", "LLL5"};
455  for (const string& str : str_checklist) {
456  if (straights.count(str) == 0)
457  B2FATAL("You need FarBeamLine.xml to run SADInput module. Please include FarBeamLine.xml in Belle2.xml. You also need to change 'length' in Belle2.xml to be 40m.");
458  }
459 
460  for (const GearDir& element : content.getNodes("Bending")) {
461 
462  string name = element.getString("@name");
463  string type = element.getString("@type");
464 
465  if (type != "pipe") continue;
466 
467  bendingElement bending;
468 
469  for (const GearDir& slot : element.getNodes("sec")) {
470  string nameSec = slot.getString("@name");
471  if (nameSec.find("RT") != std::string::npos) {bending.rt = slot.getLength();}
472  if (nameSec.find("X0") != std::string::npos) {bending.x0 = slot.getLength();}
473  if (nameSec.find("Z0") != std::string::npos) {bending.z0 = slot.getLength();}
474  if (nameSec.find("SPHI") != std::string::npos) {bending.sphi = slot.getAngle();}
475  if (nameSec.find("DPHI") != std::string::npos) {bending.dphi = slot.getAngle();}
476  }
477 
478  //bending.rt = element.getLength("RT");
479  //bending.x0 = element.getLength("X0");
480  //bending.z0 = element.getLength("Z0");
481  //bending.sphi = element.getLength("SPHI");
482  //bending.dphi = element.getLength("DPHI");
483 
484  bendings[name] = bending;
485  }
486 
487  string bend_checklist[] = {"BLC2RE", "BC1RP", "BLCWRP", "BLC1RP", "BLC2RP", "BLC2RP.2", "BLY2RP.2", "BLC1LE", "BC1LP", "BLC1LP1", "BLC1LP2", "BLC2LP"};
488  for (const string& bnd : bend_checklist) {
489  if (bendings.count(bnd) == 0)
490  B2FATAL("You need FarBeamLine.xml to run SADInput module. Please include FarBeamLine.xml in Belle2.xml. You also need to change 'length' in Belle2.xml to be 40m.");
491  }
492 
493  static double her_breakpoints[6];
494  static double ler_breakpoints[21];
495 
496  // positive s
497  her_breakpoints[0] = straights["LHL1"].l;
498  her_breakpoints[1] = her_breakpoints[0] + bendings["BLC1LE"].rt * bendings["BLC1LE"].dphi;
499  her_breakpoints[2] = her_breakpoints[1] + straights["LHL2"].l;
500 
501  // negative s
502  her_breakpoints[3] = -straights["LHR1"].l;
503  her_breakpoints[4] = her_breakpoints[3] - bendings["BLC2RE"].rt * bendings["BLC2RE"].dphi;
504  her_breakpoints[5] = her_breakpoints[4] - straights["LHR2"].l;
505 
506  // positive s
507  ler_breakpoints[0] = straights["LLL1"].l;
508  ler_breakpoints[1] = ler_breakpoints[0] + bendings["BC1LP"].rt * bendings["BC1LP"].dphi;
509  ler_breakpoints[2] = ler_breakpoints[1] + straights["LLL2"].l;
510  ler_breakpoints[3] = ler_breakpoints[2] + bendings["BLC1LP1"].rt * bendings["BLC1LP1"].dphi;
511  ler_breakpoints[4] = ler_breakpoints[3] + straights["LLL3"].l;
512  ler_breakpoints[5] = ler_breakpoints[4] + bendings["BLC1LP2"].rt * bendings["BLC1LP2"].dphi;
513  ler_breakpoints[6] = ler_breakpoints[5] + straights["LLL4"].l;
514  ler_breakpoints[7] = ler_breakpoints[6] + bendings["BLC2LP"].rt * bendings["BLC2LP"].dphi;
515  ler_breakpoints[8] = ler_breakpoints[7] + straights["LLL5"].l;
516 
517  // negative s
518  ler_breakpoints[9] = -straights["LLR1"].l;
519  ler_breakpoints[10] = ler_breakpoints[9] - bendings["BC1RP"].rt * bendings["BC1RP"].dphi;
520  ler_breakpoints[11] = ler_breakpoints[10] - straights["LLR2"].l;
521  ler_breakpoints[12] = ler_breakpoints[11] - bendings["BLCWRP"].rt * bendings["BLCWRP"].dphi;
522  ler_breakpoints[13] = ler_breakpoints[12] - straights["LLR3"].l;
523  ler_breakpoints[14] = ler_breakpoints[13] - bendings["BLC1RP"].rt * bendings["BLC1RP"].dphi;
524  ler_breakpoints[15] = ler_breakpoints[14] - straights["LLR4"].l;
525  ler_breakpoints[16] = ler_breakpoints[15] - bendings["BLC2RP"].rt * bendings["BLC2RP"].dphi;
526  ler_breakpoints[17] = ler_breakpoints[16] - bendings["BLC2RP.2"].rt * bendings["BLC2RP.2"].dphi;
527  ler_breakpoints[18] = ler_breakpoints[17] - straights["LLR5"].l;
528  ler_breakpoints[19] = ler_breakpoints[18] - bendings["BLY2RP.2"].rt * bendings["BLY2RP.2"].dphi;
529  ler_breakpoints[20] = ler_breakpoints[20] - straights["LLR6"].l;
530 
531 
532  double dx = 0;
533  double dz = 0;
534  double phi = 0;
535  if (accRing == c_LER) {
536  // LER
537  // positive s
538  if (400.0 * Unit::cm < s) {
539  if (s < ler_breakpoints[0]) {
540  phi = straights["LLL1"].phi;
541  dx = straights["LLL1"].x0 + s * sin(phi);
542  dz = straights["LLL1"].z0 + s * cos(phi);
543  } else if (s < ler_breakpoints[1]) {
544  double sloc = s - ler_breakpoints[0];
545  phi = bendings["BC1LP"].sphi + sloc / bendings["BC1LP"].rt;
546  // Torus is created in x-y plain.
547  // It is then rotated to x-z plain,
548  // and its direction changes to reversed,
549  // thus phi_real=-phi_xml
550  phi = -phi;
551  dx = bendings["BC1LP"].x0 + bendings["BC1LP"].rt * cos(-phi);
552  dz = bendings["BC1LP"].z0 + bendings["BC1LP"].rt * sin(-phi);
553  } else if (s < ler_breakpoints[2]) {
554  double sloc = s - ler_breakpoints[1];
555  phi = straights["LLL2"].phi;
556  dx = straights["LLL2"].x0 + sloc * sin(phi);
557  dz = straights["LLL2"].z0 + sloc * cos(phi);
558  } else if (s < ler_breakpoints[3]) {
559  double sloc = s - ler_breakpoints[2];
560  phi = bendings["BLC1LP1"].sphi + sloc / bendings["BLC1LP1"].rt;
561  phi = -phi;
562  dx = bendings["BLC1LP1"].x0 + bendings["BLC1LP1"].rt * cos(-phi);
563  dz = bendings["BLC1LP1"].z0 + bendings["BLC1LP1"].rt * sin(-phi);
564  } else if (s < ler_breakpoints[4]) {
565  double sloc = s - ler_breakpoints[3];
566  phi = straights["LLL3"].phi;
567  dx = straights["LLL3"].x0 + sloc * sin(phi);
568  dz = straights["LLL3"].z0 + sloc * cos(phi);
569  } else if (s < ler_breakpoints[5]) {
570  double sloc = s - ler_breakpoints[4];
571  // Torus dphi may be only positive,
572  // while direction of increasing |s| is sometimes negative,
573  // and we need to use -s and not change phi.
574  // Since we add pi to phi later,
575  // we subtract it now for this element.
576  phi = bendings["BLC1LP2"].sphi + bendings["BLC1LP2"].dphi - sloc / bendings["BLC1LP2"].rt;
577  phi = -phi;
578  dx = bendings["BLC1LP2"].x0 + bendings["BLC1LP2"].rt * cos(-phi);
579  dz = bendings["BLC1LP2"].z0 + bendings["BLC1LP2"].rt * sin(-phi);
580  phi -= M_PI;
581  } else if (s < ler_breakpoints[6]) {
582  double sloc = s - ler_breakpoints[5];
583  phi = straights["LLL4"].phi;
584  dx = straights["LLL4"].x0 + sloc * sin(phi);
585  dz = straights["LLL4"].z0 + sloc * cos(phi);
586  } else if (s < ler_breakpoints[8]) {
587  double sloc = s - ler_breakpoints[7];
588  phi = straights["LLL5"].phi;
589  dx = straights["LLL5"].x0 + sloc * sin(phi);
590  dz = straights["LLL5"].z0 + sloc * cos(phi);
591  }
592  // For this direction rotation angle of elements changes to negative,
593  // while SAD coordinates keep orientation.
594  // We need to compensate.
595  phi += M_PI;
596  }
597  // negative s
598  else if (s < -400.0 * Unit::cm) {
599  if (s > ler_breakpoints[9]) {
600  double sloc = -s;
601  phi = straights["LLR1"].phi;
602  dx = straights["LLR1"].x0 + sloc * sin(phi);
603  dz = straights["LLR1"].z0 + sloc * cos(phi);
604  } else if (s > ler_breakpoints[10]) {
605  double sloc = ler_breakpoints[9] - s;
606  phi = bendings["BC1RP"].sphi + bendings["BC1RP"].dphi - sloc / bendings["BC1RP"].rt;
607  phi = -phi;
608  dx = bendings["BC1RP"].x0 + bendings["BC1RP"].rt * cos(-phi);
609  dz = bendings["BC1RP"].z0 + bendings["BC1RP"].rt * sin(-phi);
610  phi += M_PI;
611  } else if (s > ler_breakpoints[11]) {
612  double sloc = ler_breakpoints[10] - s;
613  phi = straights["LLR2"].phi;
614  dx = straights["LLR2"].x0 + sloc * sin(phi);
615  dz = straights["LLR2"].z0 + sloc * cos(phi);
616  } else if (s > ler_breakpoints[12]) {
617  double sloc = ler_breakpoints[11] - s;
618  phi = bendings["BLCWRP"].sphi + bendings["BLCWRP"].dphi - sloc / bendings["BLCWRP"].rt;
619  phi = -phi;
620  dx = bendings["BLCWRP"].x0 + bendings["BLCWRP"].rt * cos(-phi);
621  dz = bendings["BLCWRP"].z0 + bendings["BLCWRP"].rt * sin(-phi);
622  phi += M_PI;
623  } else if (s > ler_breakpoints[13]) {
624  double sloc = ler_breakpoints[12] - s;
625  phi = straights["LLR3"].phi;
626  dx = straights["LLR3"].x0 + sloc * sin(phi);
627  dz = straights["LLR3"].z0 + sloc * cos(phi);
628  } else if (s > ler_breakpoints[14]) {
629  double sloc = ler_breakpoints[13] - s;
630  phi = bendings["BLC1RP"].sphi + bendings["BLC1RP"].dphi - sloc / bendings["BLC1RP"].rt;
631  phi = -phi;
632  dx = bendings["BLC1RP"].x0 + bendings["BLC1RP"].rt * cos(-phi);
633  dz = bendings["BLC1RP"].z0 + bendings["BLC1RP"].rt * sin(-phi);
634  phi += M_PI;
635  } else if (s > ler_breakpoints[15]) {
636  double sloc = ler_breakpoints[14] - s;
637  phi = straights["LLR4"].phi;
638  dx = straights["LLR4"].x0 + sloc * sin(phi);
639  dz = straights["LLR4"].z0 + sloc * cos(phi);
640  } else if (s > ler_breakpoints[16]) {
641  double sloc = ler_breakpoints[15] - s;
642  phi = bendings["BLC2RP"].sphi + sloc / bendings["BLC2RP"].rt;
643  phi = -phi;
644  dx = bendings["BLC2RP"].x0 + bendings["BLC2RP"].rt * cos(-phi);
645  dz = bendings["BLC2RP"].z0 + bendings["BLC2RP"].rt * sin(-phi);
646  } else if (s > ler_breakpoints[17]) {
647  double sloc = ler_breakpoints[16] - s;
648  phi = bendings["BLC2RP.2"].sphi + sloc / bendings["BLC2RP.2"].rt;
649  phi = -phi;
650  dx = bendings["BLC2RP.2"].x0 + bendings["BLC2RP.2"].rt * cos(-phi);
651  dz = bendings["BLC2RP.2"].z0 + bendings["BLC2RP.2"].rt * sin(-phi);
652  } else if (s > ler_breakpoints[18]) {
653  double sloc = ler_breakpoints[17] - s;
654  phi = straights["LLR5"].phi;
655  dx = straights["LLR5"].x0 + sloc * sin(phi);
656  dz = straights["LLR5"].z0 + sloc * cos(phi);
657  } else if (s > ler_breakpoints[19]) {
658  double sloc = ler_breakpoints[18] - s;
659  phi = bendings["BLY2RP.2"].sphi + sloc / bendings["BLY2RP.2"].rt;
660  phi = -phi;
661  dx = bendings["BLY2RP.2"].x0 + bendings["BLY2RP.2"].rt * cos(-phi);
662  dz = bendings["BLY2RP.2"].z0 + bendings["BLY2RP.2"].rt * sin(-phi);
663  } else if (s > ler_breakpoints[20]) {
664  double sloc = ler_breakpoints[19] - s;
665  phi = straights["LLR6"].phi;
666  dx = straights["LLR6"].x0 + sloc * sin(phi);
667  dz = straights["LLR6"].z0 + sloc * cos(phi);
668  }
669  }
670  }
671  if (accRing == c_HER) {
672  // HER
673  // positive s
674  if (400.0 * Unit::cm < s) {
675  if (s < her_breakpoints[0]) {
676  phi = straights["LHL1"].phi;
677  dx = straights["LHL1"].x0 + s * sin(phi);
678  dz = straights["LHL1"].z0 + s * cos(phi);
679  } else if (s < her_breakpoints[1]) {
680  double sloc = s - her_breakpoints[0];
681  phi = bendings["BLC1LE"].sphi + sloc / bendings["BLC1LE"].rt;
682  phi = -phi;
683  dx = bendings["BLC1LE"].x0 + bendings["BLC1LE"].rt * cos(-phi);
684  dz = bendings["BLC1LE"].z0 + bendings["BLC1LE"].rt * sin(-phi);
685  } else if (s < her_breakpoints[2]) {
686  double sloc = s - her_breakpoints[1];
687  phi = straights["LHL2"].phi;
688  dx = straights["LHL2"].x0 + sloc * sin(phi);
689  dz = straights["LHL2"].z0 + sloc * cos(phi);
690  }
691  phi += M_PI;
692  }
693  // negative s
694  else if (s < -400.0 * Unit::cm) {
695  if (s > her_breakpoints[3]) {
696  double sloc = -s;
697  phi = straights["LHR1"].phi;
698  dx = straights["LHR1"].x0 + sloc * sin(phi);
699  dz = straights["LHR1"].z0 + sloc * cos(phi);
700  } else if (s > her_breakpoints[4]) {
701  double sloc = her_breakpoints[3] - s;
702  phi = bendings["BLC2RE"].sphi + sloc / bendings["BLC2RE"].rt;
703  phi = -phi;
704  dx = bendings["BLC2RE"].x0 + bendings["BLC2RE"].rt * cos(-phi);
705  dz = bendings["BLC2RE"].z0 + bendings["BLC2RE"].rt * sin(-phi);
706  } else if (s > her_breakpoints[5]) {
707  double sloc = her_breakpoints[4] - s;
708  phi = straights["LHR2"].phi;
709  dx = straights["LHR2"].x0 + sloc * sin(phi);
710  dz = straights["LHR2"].z0 + sloc * cos(phi);
711  }
712  }
713  }
714 
715  TGeoHMatrix matrix("SADTrafo");
716  matrix.RotateY(phi / Unit::deg);
717  matrix.SetDx(dx);
718  matrix.SetDz(dz);
719  return matrix;
720 }
721 
GearDir is the basic class used for accessing the parameter store.
Definition: GearDir.h:31
Class to represent Particle data in graph.
Class to build, validate and sort a particle decay chain.
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
Class to read files that have been created by SAD and store their content in a MCParticle graph.
Definition: ReaderSAD.h:35
double m_pyRes
The resolution for the y momentum component of the SAD real particle.
Definition: ReaderSAD.h:127
double m_lostPx
x momentum at lost position [m].
Definition: ReaderSAD.h:139
double getSADParticle(MCParticleGraph &graph)
Reads one SAD particle from the file and creates one event per SAD particle.
Definition: ReaderSAD.cc:122
double m_inputSAD_x
x at lost position [m].
Definition: ReaderSAD.h:150
double m_lostS
lost position [m] along ring.
Definition: ReaderSAD.h:138
TTree * m_tree
The input root tree.
Definition: ReaderSAD.h:121
double m_inputSAD_ssraw
scattered position [m]
Definition: ReaderSAD.h:144
~ReaderSAD()
Destructor.
Definition: ReaderSAD.cc:64
void addAllSADParticles(MCParticleGraph &graph)
Reads all SAD particles from the file into the MCParticles collection which are inside the specified ...
Definition: ReaderSAD.cc:212
AcceleratorRings m_accRing
The accelerator ring from which the particles originate.
Definition: ReaderSAD.h:125
double m_inputSAD_r
sqrt(x*x+y*y) [m]
Definition: ReaderSAD.h:156
double m_lostX
x at lost position [m].
Definition: ReaderSAD.h:136
int calculateRealParticleNumber(double rate)
Calculates the number of real particles for a SAD particle.
Definition: ReaderSAD.cc:403
TGeoHMatrix * m_transMatrix
Transformation matrix from local SAD to global geant4 space.
Definition: ReaderSAD.h:123
unsigned int m_realPartEntry
The current number of the created real particles.
Definition: ReaderSAD.h:133
void convertParamsToSADUnits()
Convert the parameters from the SAD units to the basf2 units.
Definition: ReaderSAD.cc:236
void open(const std::string &filename)
Opens a root file and prepares it for reading.
Definition: ReaderSAD.cc:80
double m_inputSAD_rr
sqrt(x*x+y*y) [m] before matching onto beam pipe inner surface
Definition: ReaderSAD.h:157
void initialize(TGeoHMatrix *transMatrix, double sRange, AcceleratorRings accRing, double readoutTime)
Initializes the reader, sets the particle parameters and calculates important values.
Definition: ReaderSAD.cc:71
double m_inputSAD_watt
loss wattage [W]
Definition: ReaderSAD.h:161
int m_readEntry
The current number of the SAD entry that is read.
Definition: ReaderSAD.h:134
TFile * m_file
The input root file.
Definition: ReaderSAD.h:120
void addParticleToMCParticles(MCParticleGraph &graph, bool gaussSmearing=false)
Adds the current particle described by the member variables to the MCParticles collection.
Definition: ReaderSAD.cc:266
TGeoHMatrix SADtoGeant(ReaderSAD::AcceleratorRings accRing, double s)
Transformation matrix.
Definition: ReaderSAD.cc:416
double m_lostPy
y momentum at lost position [m].
Definition: ReaderSAD.h:140
double m_inputSAD_E
energy at lost position [m].
Definition: ReaderSAD.h:159
double m_inputSAD_yraw
y at lost position [m] before matching onto beam pipe inner surface
Definition: ReaderSAD.h:155
double m_inputSAD_dp_over_p0
dp_over_p0
Definition: ReaderSAD.h:158
double m_inputSAD_xraw
x at lost position [m] before matching onto beam pipe inner surface
Definition: ReaderSAD.h:154
double m_inputSAD_y
y at lost position [m].
Definition: ReaderSAD.h:151
double m_inputSAD_sraw
lost position [m
Definition: ReaderSAD.h:145
int m_inputSAD_nturn
number of turns from scattered to lost
Definition: ReaderSAD.h:149
double m_inputSAD_Lss
length of element in which scattered [m]
Definition: ReaderSAD.h:148
double m_lostY
y at lost position [m].
Definition: ReaderSAD.h:137
unsigned int m_realPartNum
The current number of the created real particles.
Definition: ReaderSAD.h:132
AcceleratorRings
The both accelerator rings.
Definition: ReaderSAD.h:46
@ c_HER
High Energy Ring (electrons)
Definition: ReaderSAD.h:47
@ c_LER
Low Energy Ring (positrons)
Definition: ReaderSAD.h:48
bool getRealParticle(MCParticleGraph &graph)
Reads one SAD particle from the file, calculates the number of real particles which are represented b...
Definition: ReaderSAD.cc:165
double m_pxRes
The resolution for the x momentum component of the SAD real particle.
Definition: ReaderSAD.h:126
double m_readoutTime
The readout time.
Definition: ReaderSAD.h:130
double m_inputSAD_rate
loss rate [Hz]
Definition: ReaderSAD.h:160
double m_inputSAD_px
x momentum at lost position [m].
Definition: ReaderSAD.h:152
double m_inputSAD_py
y momentum at lost position [m].
Definition: ReaderSAD.h:153
double m_lostRate
loss rate [Hz]>
Definition: ReaderSAD.h:141
double m_inputSAD_s
lost position (|s|<Ltot/2) [m]
Definition: ReaderSAD.h:147
double m_inputSAD_ss
scattered position (|s|<Ltot/2) [m]
Definition: ReaderSAD.h:146
double m_sRange
The +- range for the s value for which particles are loaded.
Definition: ReaderSAD.h:124
double m_lostE
energy at lost position [m].
Definition: ReaderSAD.h:142
ClassSADMetaHit - digitization simulated metahit for the SAD detector.
Definition: SADMetaHit.h:25
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
static const double deg
degree to radians
Definition: Unit.h:109
static const double m
[meters]
Definition: Unit.h:69
static const double cm
Standard units with the value = 1.
Definition: Unit.h:47
static const double s
[second]
Definition: Unit.h:95
static const double GeV
Standard of [energy, momentum, mass].
Definition: Unit.h:51
static Gearbox & getInstance()
Return reference to the Gearbox instance.
Definition: Gearbox.cc:81
GearDir getDetectorComponent(const std::string &component)
Return GearDir representing a given DetectorComponent.
Definition: Gearbox.cc:314
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.
double z0
Initial position in Z
Definition: ReaderSAD.h:196
double sphi
Bending Angle.
Definition: ReaderSAD.h:197
double dphi
Bending Angle for torus in phi.
Definition: ReaderSAD.h:198
double x0
Initial position in X
Definition: ReaderSAD.h:195
Calculates the transformation matrix from local SAD to global geant4 space.
Definition: ReaderSAD.h:185
double z0
Initial position in Z.
Definition: ReaderSAD.h:187
double x0
Initial position in X.
Definition: ReaderSAD.h:186