17#include <RtypesCore.h>
18#include <TDatabasePDG.h>
19#include <TLorentzVector.h>
21#include <TParticlePDG.h>
32 auto pids = TDatabasePDG::Instance();
33 for (
int i = 0; i < 2; i++) {
34 auto pidpart = pids->GetParticle(fPdgCodes[i]);
36 fMass[i] = pidpart->Mass();
39 Hal::Cout::Text(Form(
"DecayChannel: Cannot find Particle with PID %i", fPdgCodes[i]),
"L", kOrange);
50 auto pids = TDatabasePDG::Instance();
51 for (
int i = 0; i < 3; i++) {
52 auto pidpart = pids->GetParticle(fPdgCodes[i]);
54 fMass[i] = pidpart->Mass();
57 Hal::Cout::Text(Form(
"DecayChannel: Cannot find Particle with PID %i", fPdgCodes[i]),
"L", kOrange);
62 Bool_t DecayChannel::Init() {
63 for (
auto m : fMass) {
70 fMotherPdg = motherPdg;
71 auto pids = TDatabasePDG::Instance();
72 auto pidpart = pids->GetParticle(fMotherPdg);
73 if (pidpart) { fMotherMass = pidpart->Mass(); }
76 Double_t Decay::GetDecayTime(
McTrack& mother, Double_t mass)
const {
78 if (fGamma == 0) {
return 1E+10; }
79 double tTau0 = mP.E() / (mass * fGamma);
81 return -tTau0 * TMath::Log(gRandom->Rndm());
84 void Decay::Decay2Body(McTrack& mother, std::vector<McTrack*>& daughters,
const DecayChannel& channel)
const {
85 Double_t M = fMotherMass;
86 if (fBreightWigher) { M = GetDecayTime(mother, fMotherMass); }
87 if (M < channel.GetMassThreshold()) { M = channel.GetMassThreshold(); }
88 Double_t tTime = GetDecayTime(mother, M);
90 const TLorentzVector& mP = mother.GetMomentum();
91 const TLorentzVector& mX = mother.GetFreezoutPosition();
92 Int_t pdg1 = channel.GetDaughterPdg(0);
93 Int_t pdg2 = channel.GetDaughterPdg(1);
94 Double_t m1 = channel.GetDaughterMass(0);
95 Double_t m2 = channel.GetDaughterMass(1);
97 TVector3 boost = mP.BoostVector();
98 Double_t X = mX.X() + boost.X() * tTime;
99 Double_t Y = mX.Y() + boost.Y() * tTime;
100 Double_t Z = mX.Z() + boost.Z() * tTime;
101 Double_t T = mX.T() + tTime;
103 Double_t tMC1 = (M * M - (m1 + m2) * (m1 + m2));
104 Double_t tMC2 = (M * M - (m1 - m2) * (m1 - m2));
105 Double_t tMom = TMath::Sqrt(tMC1 * tMC2) / (2 * M);
107 Double_t px1, py1, pz1;
108 Double_t px2, py2, pz2;
109 gRandom->Sphere(px1, py1, pz1, tMom);
113 TLorentzVector dau1, dau2;
114 dau1.SetPxPyPzE(px1, py1, pz1, TMath::Sqrt(tMom * tMom + m1 * m1));
115 dau2.SetPxPyPzE(px2, py2, pz2, TMath::Sqrt(tMom * tMom + m2 * m2));
118 auto& daughter1 = daughters[0];
119 auto& daughter2 = daughters[1];
120 daughter1->SetMotherIndex(mother.GetThisID());
121 daughter2->SetMotherIndex(mother.GetThisID());
122 daughter1->SetPdg(pdg1);
123 daughter2->SetPdg(pdg2);
124 daughter1->SetMomentum(dau1.X(), dau1.Y(), dau1.Z(), dau1.T());
125 daughter2->SetMomentum(dau2.X(), dau2.Y(), dau2.Z(), dau2.T());
126 daughter1->SetFreezoutPosition(X, Y, Z, T);
127 daughter2->SetFreezoutPosition(X, Y, Z, T);
130 void Decay::Decay3Body(McTrack& mother, std::vector<McTrack*>& daughters,
const DecayChannel& channel)
const {
131 Double_t tE = mother.GetMomentum().E();
132 Double_t tM1 = channel.GetDaughterMass(0);
133 Double_t tM2 = channel.GetDaughterMass(1);
134 Double_t tM3 = channel.GetDaughterMass(2);
135 Double_t M = fMotherMass;
136 if (fBreightWigher) { M = GetDecayTime(mother, fMotherMass); }
137 if (M < channel.GetMassThreshold()) { M = channel.GetMassThreshold(); }
138 Double_t tTime = GetDecayTime(mother, M);
140 Double_t tES1, tES2, tP1, tP2, tCos12, tZ;
144 tES1 = gRandom->Rndm() * (M - tM2 - tM3 - tM1) + tM1;
145 tES2 = gRandom->Rndm() * (M - tM1 - tM3 - tM2) + tM2;
146 }
while (tES1 + tES2 > M);
147 tP1 = TMath::Sqrt(tES1 * tES1 - tM1 * tM1);
148 tP2 = TMath::Sqrt(tES2 * tES2 - tM2 * tM2);
149 tZ = M - tES1 - tES2;
151 tCos12 = (tZ - tP1 * tP1 - tP2 * tP2 - tM3 * tM3) / (2 * tP1 * tP2);
152 }
while ((tCos12 < -1.0) || (tCos12 > 1.0));
155 auto& momP = mother.GetMomentum();
156 auto& momX = mother.GetFreezoutPosition();
158 Double_t X = momX.X() + (momP.Px() / tE) * tTime;
159 Double_t Y = momX.Y() + (momP.Py() / tE) * tTime;
160 Double_t Z = momX.Z() + (momP.Pz() / tE) * tTime;
161 Double_t T = momX.T() + tTime;
163 Double_t tPxr2 = tP2 * TMath::Sqrt(1 - tCos12 * tCos12);
164 Double_t tPzr2 = tP2 * tCos12;
165 Double_t tPxr3 = -tPxr2;
166 Double_t tPzr3 = -(tP1 + tPzr2);
167 Double_t tP3 = TMath::Hypot(tPxr3, tPzr3);
168 Double_t tES3 = TMath::Hypot(tM3, tP3);
171 Double_t tPhi = gRandom->Rndm() * 2 * TMath::Pi();
172 Double_t tKsi = gRandom->Rndm() * 2 * TMath::Pi();
173 Double_t tCosTh = gRandom->Rndm() * 2.0 - 1.0;
175 Double_t sp = TMath::Sin(tPhi);
176 Double_t cp = TMath::Cos(tPhi);
177 Double_t sk = TMath::Sin(tKsi);
178 Double_t ck = TMath::Cos(tKsi);
179 Double_t st = TMath::Sqrt(1.0 - tCosTh * tCosTh);
180 Double_t ct = tCosTh;
183 Double_t tPxp1 = -st * ck * tP1;
184 Double_t tPyp1 = st * sk * tP1;
185 Double_t tPzp1 = ct * tP1;
187 Double_t tPxp2 = (cp * ct * ck - sp * sk) * tPxr2 + (-st * ck) * tPzr2;
188 Double_t tPyp2 = (-cp * ct * sk - sp * ck) * tPxr2 + (st * sk) * tPzr2;
189 Double_t tPzp2 = cp * st * tPxr2 + ct * tPzr2;
191 Double_t tPxp3 = (cp * ct * ck - sp * sk) * tPxr3 + (-st * ck) * tPzr3;
192 Double_t tPyp3 = (-cp * ct * sk - sp * ck) * tPxr3 + (st * sk) * tPzr3;
193 Double_t tPzp3 = cp * st * tPxr3 + ct * tPzr3;
194 TVector3 boost = momP.BoostVector();
196 tES1 = TMath::Sqrt(tM1 * tM1 + tPxp1 * tPxp1 + tPyp1 * tPyp1 + tPzp1 * tPzp1);
197 tES2 = TMath::Sqrt(tM2 * tM2 + tPxp2 * tPxp2 + tPyp2 * tPyp2 + tPzp2 * tPzp2);
198 tES3 = TMath::Sqrt(tM3 * tM3 + tPxp3 * tPxp3 + tPyp3 * tPyp3 + tPzp3 * tPzp3);
200 TLorentzVector p1, p2, p3;
201 p1.SetPxPyPzE(tPxp1, tPyp1, tPzp1, tES1);
202 p2.SetPxPyPzE(tPxp2, tPyp2, tPzp2, tES2);
203 p3.SetPxPyPzE(tPxp3, tPyp3, tPzp3, tES3);
208 auto& daughter1 = daughters[0];
209 auto& daughter2 = daughters[1];
210 auto& daughter3 = daughters[2];
211 daughter1->SetMotherIndex(mother.GetThisID());
212 daughter2->SetMotherIndex(mother.GetThisID());
213 daughter3->SetMotherIndex(mother.GetThisID());
214 daughter1->SetPdg(channel.GetDaughterPdg(0));
215 daughter2->SetPdg(channel.GetDaughterPdg(1));
216 daughter3->SetPdg(channel.GetDaughterPdg(2));
217 daughter1->SetMomentum(p1.X(), p1.Y(), p1.Z(), p1.T());
218 daughter2->SetMomentum(p2.X(), p2.Y(), p2.Z(), p2.T());
219 daughter3->SetMomentum(p3.X(), p3.Y(), p3.Z(), p3.T());
220 daughter1->SetFreezoutPosition(X, Y, Z, T);
221 daughter2->SetFreezoutPosition(X, Y, Z, T);
222 daughter3->SetFreezoutPosition(X, Y, Z, T);
229 Double_t val = gRandom->Uniform();
231 while (val > fDecayChannels[chan].GetBranchingRatio()) {
234 auto decay = fDecayChannels[chan];
235 Int_t daughtersNo = decay.GetDaughtersNo();
236 if (daughtersNo <= 0) {
237 Hal::Cout::PrintInfo(
"Decay::DecayParitcle this number of channels not supported", EInfo::kError);
240 if (daughtersNo == 2) {
241 Decay2Body(mother, daughters, decay);
242 }
else if (daughtersNo == 3) {
243 Decay3Body(mother, daughters, decay);
247 for (
int i = 0; i < daughtersNo; i++) {
248 int tracks =
event->GetTotalTrackNo();
261 if (fDecayChannels.size() == 0)
return kFALSE;
262 Double_t branchSum = 0;
263 for (
auto& d : fDecayChannels) {
264 if (!d.Init())
return kFALSE;
266 for (
auto d : fDecayChannels) {
267 branchSum += d.GetBranchingRatio();
269 for (
auto& d : fDecayChannels) {
270 d.SetBranchRatio(d.GetBranchingRatio() / branchSum);
273 for (
auto& d : fDecayChannels) {
274 branchSum += d.GetBranchingRatio();
275 d.SetBranchRatio(branchSum);
277 fDecayChannels[fDecayChannels.size() - 1].SetBranchRatio(1.1);
278 auto pids = TDatabasePDG::Instance();
279 auto pidpart = pids->GetParticle(fMotherPdg);
280 if (!pidpart)
return kFALSE;
281 fMotherMass = pidpart->Mass();
static void Text(TString text, TString option="L", Color_t color=-1)
static void PrintInfo(TString text, Hal::EInfo status)
DecayChannel(Int_t dau1=0, Int_t dau2=0, Double_t ratio=0.0)
virtual Int_t DecayParticle(McTrack &mother, std::vector< McTrack * > &daughters, Bool_t addToEvent=kFALSE) const
Decay(Int_t motherPdg=-1)
const TLorentzVector & GetMomentum() const
void SetEvent(Event *event)
virtual void CopyAllData(Track *other)