9 #include <generators/SAD/ReaderSAD.h>
11 #include <framework/logging/Logger.h>
12 #include <framework/gearbox/Unit.h>
13 #include <framework/gearbox/GearDir.h>
14 #include <mdst/dataobjects/MCParticle.h>
16 #include <generators/SAD/dataobjects/SADMetaHit.h>
19 #include <framework/datastore/StoreArray.h>
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)
87 m_file =
new TFile(filename.c_str(),
"READ");
88 if (
m_file == NULL)
throw(SADCouldNotOpenFileError() << filename);
92 if (
m_tree == NULL)
throw(SADCouldNotOpenFileError() << filename);
117 hit.registerInDataStore();
125 B2ERROR(
"The SAD tree doesn't exist !");
138 B2DEBUG(10,
"> Read particle " <<
m_readEntry + 1 <<
"/" <<
m_tree->GetEntries() <<
" with s = " <<
m_lostS <<
" cm" <<
144 if (zMom2 < 0) printf(
"zMom2= %f is negative. Skipped!\n", zMom2);
168 B2ERROR(
"The SAD tree doesn't exist !");
191 B2DEBUG(10,
"> Read particle " <<
m_readEntry + 1 <<
"/" <<
m_tree->GetEntries() <<
" with s = " <<
m_lostS <<
" cm" <<
193 }
while ((fabs(
m_lostS) >
m_sRange) && (m_readEntry < m_tree->GetEntries()));
203 "/" <<
m_tree->GetEntries());
215 B2ERROR(
"The SAD tree doesn't exist !");
219 int nPart =
m_tree->GetEntries();
221 for (
int iPart = 0; iPart < nPart; ++iPart) {
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};
279 case c_HER: particle.setPDG(11);
281 case c_LER: particle.setPDG(-11);
285 particle.setMassFromPDG();
293 particlePosSADfar[0] =
m_lostX;
294 particlePosSADfar[1] = -
m_lostY;
295 particlePosSADfar[2] = 0;
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.");
305 m_transMatrix->LocalToMaster(particlePosSAD, particlePosGeant4);
307 m_transMatrix2->LocalToMaster(particlePosSADfar, particlePosGeant4);
324 double zMom = sqrt(totalMomSqr - (particleMomSAD[0] * particleMomSAD[0]) - (particleMomSAD[1] * particleMomSAD[1]));
327 case c_HER: particleMomSAD[2] = zMom;
329 case c_LER: particleMomSAD[2] = -zMom;
336 case c_HER: ring = 1;
338 case c_LER: ring = 2;
365 int section_ordering[12] = {1, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2};
371 }
else if (ring == 2) {
377 int ring_section = section_ordering[(int)((ssraw) / 250.)];
380 m_transMatrix->LocalToMasterVect(particleMomSAD, particleMomGeant4);
382 m_transMatrix2->LocalToMasterVect(particleMomSAD, particleMomGeant4);
386 particle.setMomentum(TVector3(particleMomGeant4));
387 particle.setProductionVertex(TVector3(particlePosGeant4));
388 particle.setProductionTime(0.0);
389 particle.setEnergy(sqrt(
m_lostE *
m_lostE + particle.getMass()*particle.getMass()));
390 particle.setValidVertex(
true);
407 int numPart_int =
static_cast<int>(floor(numPart));
408 double numPart_dec = numPart - numPart_int;
410 double rnd = gRandom->Uniform();
411 if (rnd < numPart_dec) numPart_int += 1;
427 map<string, straightElement> straights;
428 map<string, bendingElement> bendings;
429 for (
const GearDir& element : content.getNodes(
"Straight")) {
431 string name = element.getString(
"@name");
432 string type = element.getString(
"@type");
434 if (type !=
"pipe")
continue;
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();}
451 straights[name] = straight;
454 string str_checklist[] = {
"LHR1",
"LHR2",
"LLR1",
"LLR2",
"LLR3",
"LLR4",
"LLR5",
"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.");
460 for (
const GearDir& element : content.getNodes(
"Bending")) {
462 string name = element.getString(
"@name");
463 string type = element.getString(
"@type");
465 if (type !=
"pipe")
continue;
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();}
484 bendings[name] = bending;
487 string bend_checklist[] = {
"BLC2RE",
"BC1RP",
"BLCWRP",
"BLC1RP",
"BLC2RP",
"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.");
493 static double her_breakpoints[6];
494 static double ler_breakpoints[18];
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;
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;
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;
516 ler_breakpoints[7] = -straights[
"LLR1"].l;
517 ler_breakpoints[8] = ler_breakpoints[7] - bendings[
"BC1RP"].rt * bendings[
"BC1RP"].dphi;
518 ler_breakpoints[9] = ler_breakpoints[8] - straights[
"LLR2"].l;
519 ler_breakpoints[10] = ler_breakpoints[9] - bendings[
"BLCWRP"].rt * bendings[
"BLCWRP"].dphi;
520 ler_breakpoints[11] = ler_breakpoints[10] - straights[
"LLR3"].l;
521 ler_breakpoints[12] = ler_breakpoints[11] - bendings[
"BLC1RP"].rt * bendings[
"BLC1RP"].dphi;
522 ler_breakpoints[13] = ler_breakpoints[12] - straights[
"LLR4"].l;
523 ler_breakpoints[14] = ler_breakpoints[13] - bendings[
"BLC2RP"].rt * bendings[
"BLC2RP"].dphi;
524 ler_breakpoints[15] = ler_breakpoints[14] - straights[
"LLR5"].l;
527 ler_breakpoints[16] = ler_breakpoints[6] + bendings[
"BLC2LP"].rt * bendings[
"BLC2LP"].dphi;
528 ler_breakpoints[17] = ler_breakpoints[16] + straights[
"LLL5"].l;
533 if (accRing ==
c_LER) {
537 if (s < ler_breakpoints[0]) {
538 phi = straights[
"LLL1"].phi;
539 dx = straights[
"LLL1"].x0 + s * sin(phi);
540 dz = straights[
"LLL1"].z0 + s * cos(phi);
541 }
else if (s < ler_breakpoints[1]) {
542 double sloc = s - ler_breakpoints[0];
543 phi = bendings[
"BC1LP"].sphi + sloc / bendings[
"BC1LP"].rt;
549 dx = bendings[
"BC1LP"].x0 + bendings[
"BC1LP"].rt * cos(-phi);
550 dz = bendings[
"BC1LP"].z0 + bendings[
"BC1LP"].rt * sin(-phi);
551 }
else if (s < ler_breakpoints[2]) {
552 double sloc = s - ler_breakpoints[1];
553 phi = straights[
"LLL2"].phi;
554 dx = straights[
"LLL2"].x0 + sloc * sin(phi);
555 dz = straights[
"LLL2"].z0 + sloc * cos(phi);
556 }
else if (s < ler_breakpoints[3]) {
557 double sloc = s - ler_breakpoints[2];
558 phi = bendings[
"BLC1LP1"].sphi + sloc / bendings[
"BLC1LP1"].rt;
560 dx = bendings[
"BLC1LP1"].x0 + bendings[
"BLC1LP1"].rt * cos(-phi);
561 dz = bendings[
"BLC1LP1"].z0 + bendings[
"BLC1LP1"].rt * sin(-phi);
562 }
else if (s < ler_breakpoints[4]) {
563 double sloc = s - ler_breakpoints[3];
564 phi = straights[
"LLL3"].phi;
565 dx = straights[
"LLL3"].x0 + sloc * sin(phi);
566 dz = straights[
"LLL3"].z0 + sloc * cos(phi);
567 }
else if (s < ler_breakpoints[5]) {
568 double sloc = s - ler_breakpoints[4];
574 phi = bendings[
"BLC1LP2"].sphi + bendings[
"BLC1LP2"].dphi - sloc / bendings[
"BLC1LP2"].rt;
576 dx = bendings[
"BLC1LP2"].x0 + bendings[
"BLC1LP2"].rt * cos(-phi);
577 dz = bendings[
"BLC1LP2"].z0 + bendings[
"BLC1LP2"].rt * sin(-phi);
579 }
else if (s < ler_breakpoints[6]) {
580 double sloc = s - ler_breakpoints[5];
581 phi = straights[
"LLL4"].phi;
582 dx = straights[
"LLL4"].x0 + sloc * sin(phi);
583 dz = straights[
"LLL4"].z0 + sloc * cos(phi);
584 }
else if (s < ler_breakpoints[17]) {
585 double sloc = s - ler_breakpoints[16];
586 phi = straights[
"LLL5"].phi;
587 dx = straights[
"LLL5"].x0 + sloc * sin(phi);
588 dz = straights[
"LLL5"].z0 + sloc * cos(phi);
597 if (s > ler_breakpoints[7]) {
599 phi = straights[
"LLR1"].phi;
600 dx = straights[
"LLR1"].x0 + sloc * sin(phi);
601 dz = straights[
"LLR1"].z0 + sloc * cos(phi);
602 }
else if (s > ler_breakpoints[8]) {
603 double sloc = ler_breakpoints[7] - s;
604 phi = bendings[
"BC1RP"].sphi + bendings[
"BC1RP"].dphi - sloc / bendings[
"BC1RP"].rt;
606 dx = bendings[
"BC1RP"].x0 + bendings[
"BC1RP"].rt * cos(-phi);
607 dz = bendings[
"BC1RP"].z0 + bendings[
"BC1RP"].rt * sin(-phi);
609 }
else if (s > ler_breakpoints[9]) {
610 double sloc = ler_breakpoints[8] - s;
611 phi = straights[
"LLR2"].phi;
612 dx = straights[
"LLR2"].x0 + sloc * sin(phi);
613 dz = straights[
"LLR2"].z0 + sloc * cos(phi);
614 }
else if (s > ler_breakpoints[10]) {
615 double sloc = ler_breakpoints[9] - s;
616 phi = bendings[
"BLCWRP"].sphi + bendings[
"BLCWRP"].dphi - sloc / bendings[
"BLCWRP"].rt;
618 dx = bendings[
"BLCWRP"].x0 + bendings[
"BLCWRP"].rt * cos(-phi);
619 dz = bendings[
"BLCWRP"].z0 + bendings[
"BLCWRP"].rt * sin(-phi);
621 }
else if (s > ler_breakpoints[11]) {
622 double sloc = ler_breakpoints[10] - s;
623 phi = straights[
"LLR3"].phi;
624 dx = straights[
"LLR3"].x0 + sloc * sin(phi);
625 dz = straights[
"LLR3"].z0 + sloc * cos(phi);
626 }
else if (s > ler_breakpoints[12]) {
627 double sloc = ler_breakpoints[11] - s;
628 phi = bendings[
"BLC1RP"].sphi + bendings[
"BLC1RP"].dphi - sloc / bendings[
"BLC1RP"].rt;
630 dx = bendings[
"BLC1RP"].x0 + bendings[
"BLC1RP"].rt * cos(-phi);
631 dz = bendings[
"BLC1RP"].z0 + bendings[
"BLC1RP"].rt * sin(-phi);
633 }
else if (s > ler_breakpoints[13]) {
634 double sloc = ler_breakpoints[12] - s;
635 phi = straights[
"LLR4"].phi;
636 dx = straights[
"LLR4"].x0 + sloc * sin(phi);
637 dz = straights[
"LLR4"].z0 + sloc * cos(phi);
638 }
else if (s > ler_breakpoints[14]) {
639 double sloc = ler_breakpoints[13] - s;
640 phi = bendings[
"BLC2RP"].sphi + sloc / bendings[
"BLC2RP"].rt;
642 dx = bendings[
"BLC2RP"].x0 + bendings[
"BLC2RP"].rt * cos(-phi);
643 dz = bendings[
"BLC2RP"].z0 + bendings[
"BLC2RP"].rt * sin(-phi);
644 }
else if (s > ler_breakpoints[15]) {
645 double sloc = ler_breakpoints[14] - s;
646 phi = straights[
"LLR5"].phi;
647 dx = straights[
"LLR5"].x0 + sloc * sin(phi);
648 dz = straights[
"LLR5"].z0 + sloc * cos(phi);
652 if (accRing ==
c_HER) {
656 if (s < her_breakpoints[0]) {
657 phi = straights[
"LHL1"].phi;
658 dx = straights[
"LHL1"].x0 + s * sin(phi);
659 dz = straights[
"LHL1"].z0 + s * cos(phi);
660 }
else if (s < her_breakpoints[1]) {
661 double sloc = s - her_breakpoints[0];
662 phi = bendings[
"BLC1LE"].sphi + sloc / bendings[
"BLC1LE"].rt;
664 dx = bendings[
"BLC1LE"].x0 + bendings[
"BLC1LE"].rt * cos(-phi);
665 dz = bendings[
"BLC1LE"].z0 + bendings[
"BLC1LE"].rt * sin(-phi);
666 }
else if (s < her_breakpoints[2]) {
667 double sloc = s - her_breakpoints[1];
668 phi = straights[
"LHL2"].phi;
669 dx = straights[
"LHL2"].x0 + sloc * sin(phi);
670 dz = straights[
"LHL2"].z0 + sloc * cos(phi);
676 if (s > her_breakpoints[3]) {
678 phi = straights[
"LHR1"].phi;
679 dx = straights[
"LHR1"].x0 + sloc * sin(phi);
680 dz = straights[
"LHR1"].z0 + sloc * cos(phi);
681 }
else if (s > her_breakpoints[4]) {
682 double sloc = her_breakpoints[3] - s;
683 phi = bendings[
"BLC2RE"].sphi + sloc / bendings[
"BLC2RE"].rt;
685 dx = bendings[
"BLC2RE"].x0 + bendings[
"BLC2RE"].rt * cos(-phi);
686 dz = bendings[
"BLC2RE"].z0 + bendings[
"BLC2RE"].rt * sin(-phi);
687 }
else if (s > her_breakpoints[5]) {
688 double sloc = her_breakpoints[4] - s;
689 phi = straights[
"LHR2"].phi;
690 dx = straights[
"LHR2"].x0 + sloc * sin(phi);
691 dz = straights[
"LHR2"].z0 + sloc * cos(phi);
696 TGeoHMatrix matrix(
"SADTrafo");
GearDir is the basic class used for accessing the parameter store.
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.
Class to read files that have been created by SAD and store their content in a MCParticle graph.
double m_pyRes
The resolution for the y momentum component of the SAD real particle.
double m_lostPx
x momentum at lost position [m].
double getSADParticle(MCParticleGraph &graph)
Reads one SAD particle from the file and creates one event per SAD particle.
double m_inputSAD_x
x at lost position [m].
double m_lostS
lost position [m] along ring.
TTree * m_tree
The input root tree.
double m_inputSAD_ssraw
scattered position [m]
void addAllSADParticles(MCParticleGraph &graph)
Reads all SAD particles from the file into the MCParticles collection which are inside the specified ...
AcceleratorRings m_accRing
The accelerator ring from which the particles originate.
double m_inputSAD_r
sqrt(x*x+y*y) [m]
double m_lostX
x at lost position [m].
int calculateRealParticleNumber(double rate)
Calculates the number of real particles for a SAD particle.
TGeoHMatrix * m_transMatrix
Transformation matrix from local SAD to global geant4 space.
unsigned int m_realPartEntry
The current number of the created real particles.
void convertParamsToSADUnits()
Convert the parameters from the SAD units to the basf2 units.
void open(const std::string &filename)
Opens a root file and prepares it for reading.
double m_inputSAD_rr
sqrt(x*x+y*y) [m] before matching onto beam pipe inner surface
void initialize(TGeoHMatrix *transMatrix, double sRange, AcceleratorRings accRing, double readoutTime)
Initializes the reader, sets the particle parameters and calculates important values.
double m_inputSAD_watt
loss wattage [W]
int m_readEntry
The current number of the SAD entry that is read.
TFile * m_file
The input root file.
void addParticleToMCParticles(MCParticleGraph &graph, bool gaussSmearing=false)
Adds the current particle described by the member variables to the MCParticles collection.
TGeoHMatrix SADtoGeant(ReaderSAD::AcceleratorRings accRing, double s)
Transformation matrix.
double m_lostPy
y momentum at lost position [m].
double m_inputSAD_E
energy at lost position [m].
double m_inputSAD_yraw
y at lost position [m] before matching onto beam pipe inner surface
double m_inputSAD_dp_over_p0
dp_over_p0
double m_inputSAD_xraw
x at lost position [m] before matching onto beam pipe inner surface
double m_inputSAD_y
y at lost position [m].
double m_inputSAD_sraw
lost position [m
int m_inputSAD_nturn
number of turns from scattered to lost
double m_inputSAD_Lss
length of element in which scattered [m]
double m_lostY
y at lost position [m].
unsigned int m_realPartNum
The current number of the created real particles.
AcceleratorRings
The both accelerator rings.
@ c_HER
High Energy Ring (electrons)
@ c_LER
Low Energy Ring (positrons)
bool getRealParticle(MCParticleGraph &graph)
Reads one SAD particle from the file, calculates the number of real particles which are represented b...
double m_pxRes
The resolution for the x momentum component of the SAD real particle.
double m_readoutTime
The readout time.
double m_inputSAD_rate
loss rate [Hz]
double m_inputSAD_px
x momentum at lost position [m].
double m_inputSAD_py
y momentum at lost position [m].
double m_lostRate
loss rate [Hz]>
double m_inputSAD_s
lost position (|s|<Ltot/2) [m]
double m_inputSAD_ss
scattered position (|s|<Ltot/2) [m]
double m_sRange
The +- range for the s value for which particles are loaded.
double m_lostE
energy at lost position [m].
Accessor to arrays stored in the data store.
T * appendNew()
Construct a new T object at the end of the array.
static const double deg
degree to radians
static const double m
[meters]
static const double cm
Standard units with the value = 1.
static const double s
[second]
static const double GeV
Standard of [energy, momentum, mass].
static Gearbox & getInstance()
Return reference to the Gearbox instance.
GearDir getDetectorComponent(const std::string &component)
Return GearDir representing a given DetectorComponent.
GraphParticle & addParticle()
Add new particle to the graph.
Abstract base class for different kinds of events.
double z0
Initial position in Z
double sphi
Bending Angle.
double dphi
Bending Angle for torus in phi.
double x0
Initial position in X
Calculates the transformation matrix from local SAD to global geant4 space.
double z0
Initial position in Z.
double x0
Initial position in X.