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>
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 const 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(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);
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",
"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.");
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",
"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.");
493 static double her_breakpoints[6];
494 static double ler_breakpoints[21];
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;
514 ler_breakpoints[7] = ler_breakpoints[6] + bendings[
"BLC2LP"].rt * bendings[
"BLC2LP"].dphi;
515 ler_breakpoints[8] = ler_breakpoints[7] + straights[
"LLL5"].l;
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;
535 if (accRing ==
c_LER) {
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;
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;
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];
576 phi = bendings[
"BLC1LP2"].sphi + bendings[
"BLC1LP2"].dphi - sloc / bendings[
"BLC1LP2"].rt;
578 dx = bendings[
"BLC1LP2"].x0 + bendings[
"BLC1LP2"].rt * cos(-phi);
579 dz = bendings[
"BLC1LP2"].z0 + bendings[
"BLC1LP2"].rt * sin(-phi);
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);
599 if (s > ler_breakpoints[9]) {
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;
608 dx = bendings[
"BC1RP"].x0 + bendings[
"BC1RP"].rt * cos(-phi);
609 dz = bendings[
"BC1RP"].z0 + bendings[
"BC1RP"].rt * sin(-phi);
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;
620 dx = bendings[
"BLCWRP"].x0 + bendings[
"BLCWRP"].rt * cos(-phi);
621 dz = bendings[
"BLCWRP"].z0 + bendings[
"BLCWRP"].rt * sin(-phi);
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;
632 dx = bendings[
"BLC1RP"].x0 + bendings[
"BLC1RP"].rt * cos(-phi);
633 dz = bendings[
"BLC1RP"].z0 + bendings[
"BLC1RP"].rt * sin(-phi);
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;
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;
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;
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);
671 if (accRing ==
c_HER) {
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;
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);
695 if (s > her_breakpoints[3]) {
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;
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);
715 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.
ReaderSAD()
Constructor of the ReaderSAD class.
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.
double sqrt(double a)
sqrt for double
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.