Belle II Software development
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
24using namespace std;
25using namespace Belle2;
26
27
28ReaderSAD::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
44 m_inputSAD_ss = 0;
45 m_inputSAD_s = 0;
48 m_inputSAD_x = 0;
49 m_inputSAD_y = 0;
50 m_inputSAD_px = 0;
51 m_inputSAD_py = 0;
54 m_inputSAD_r = 0;
55 m_inputSAD_rr = 0;
57 m_inputSAD_E = 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
71void 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
80void 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
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{
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
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
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
ReaderSAD()
Constructor of the ReaderSAD class.
Definition: ReaderSAD.cc:28
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.
STL namespace.
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