17#include <FairRootManager.h>
20#include <TClonesArray.h>
39template<
bool IsMixedEvent>
43 constexpr auto CreatePVector = [](
const auto& prt) ->
PVector4_t {
44 double px = prt.GetPx();
45 double py = prt.GetPy();
46 double pz = prt.GetPz();
47 double m = prt.NDaughters() == 1 ? prt.GetMassHypo() : prt.GetMass();
49 double e = std::sqrt(m * m + px * px + py * py + pz * pz);
54 constexpr auto CreateXVector = [](
const auto& prtInfo) ->
XVector4_t {
55 const auto*
h = prtInfo.pTofHit;
62 size_t iDa = v0cand.DaughterIds()[0];
63 size_t iDb = v0cand.DaughterIds()[1];
64 const auto& daughterA{particles[iDa]};
65 const auto& daughterB{particles[iDb]};
66 const auto& daughterAinfo{(*fpParticleInfo)[iDa]};
67 const auto& daughterBinfo{(*fpParticleInfo)[iDb]};
70 Cutter_t::ParticleProperty property;
71 KFParticleSIMD particleSIMD(
const_cast<KFParticle&
>(v0cand));
77 float_v decayLengthSIMD;
78 float_v decayLengthErrSIMD;
79 particleSIMD.GetDistanceToVertexLine(primVertex, decayLengthSIMD, decayLengthErrSIMD);
80 property.daughterA.dcaRelToOrigin = daughterAinfo.dca;
81 property.daughterB.dcaRelToOrigin = daughterBinfo.dca;
82 property.decayLength = decayLengthSIMD[0];
83 property.dcaRelToPrimVertex = particleSIMD.GetDistanceFromVertex(primVertex)[0];
84 particleSIMD.SetProductionVertex(primVertex);
85 property.chi2NdfTopo = double(particleSIMD.Chi2()[0]) / double(particleSIMD.NDF()[0]);
86 property.chi2NdfGeo = v0cand.Chi2() / v0cand.NDF();
87 property.dcaBetweenDaughters = daughterB.GetDistanceFromParticle(daughterA);
88 property.daughterVtxZ = v0cand.Z();
92 auto aP = CreatePVector(daughterA);
93 auto bP = CreatePVector(daughterB);
96 auto v0X =
XVector4_t(v0cand.X(), v0cand.Y(), v0cand.Z(), v0Tof);
97 auto aX = CreateXVector(daughterAinfo);
98 auto bX = CreateXVector(daughterBinfo);
99 auto aR = aX.Vect() - v0X.Vect();
100 auto bR = bX.Vect() - v0X.Vect();
101 auto angle = std::acos((aR.x() * bR.x() + aR.y() * bR.y() + aR.z() * bR.z()) / (aR.r() * bR.r()));
102 auto angleKf = daughterA.GetAngle(daughterB);
104 float v0MassErr{0.f};
105 v0cand.GetMass(v0Mass, v0MassErr);
106 property.openingAngle = angle;
107 property.daughterA.beta = aP.P() / aP.E();
108 property.daughterB.beta = bP.P() / bP.E();
111 h.opening_angle->Fill(property.openingAngle);
112 h.opening_angle_kf->Fill(angleKf);
113 h.dca_rt_pv->Fill(property.dcaRelToPrimVertex);
114 h.dca_daughters->Fill(property.dcaBetweenDaughters);
115 h.decay_length->Fill(property.decayLength);
116 h.decay_vtx_xy->Fill(v0cand.X(), v0cand.Y());
117 h.decay_vtx_z->Fill(property.daughterVtxZ);
118 h.chi2ndf_topo->Fill(property.chi2NdfTopo);
119 h.chi2ndf_geo->Fill(property.chi2NdfGeo);
120 h.mass->Fill(v0Mass);
124 h.beta->Fill(dtrProperty.
beta);
125 h.dca_rt_origin->Fill(dtrProperty.dcaRelToOrigin);
127 h.pt->Fill(dtrP.Pt());
138 if constexpr (!IsMixedEvent) {
145 if (
fpCutter->SelectParticle(property)) {
155 if (
fpCutter->SelectParticle(property)) {
165 h.beta->Fill(prtInfo.
beta);
166 h.dca_rt_origin->Fill(prtInfo.
dca);
167 h.p->Fill(prt.GetP());
168 h.pt->Fill(prt.GetPt());
179 std::vector<char> vbUnused(particles.size(),
true);
180 for (
size_t iP = 0; iP < particles.size(); ++iP) {
181 const auto& particle{particles[iP]};
182 if (particle.NDaughters() > 1) {
183 for (
size_t iD : particle.DaughterIds()) {
184 vbUnused[iD] =
false;
190 for (
size_t iP = 0; iP < particles.size(); ++iP) {
191 const auto& particle{particles[iP]};
192 const auto& particleInfo{(*fpParticleInfo)[iP]};
194 if (particle.NDaughters() == 1) {
195 bool bUnused = vbUnused[iP];
200 if (particle.GetPDG() == -211) {
206 else if (particle.GetPDG() == 2212) {
213 else if (particle.GetPDG() == Cutter_t::GetV0Pdg()) {
219 for (
size_t iP = 0; iP < particles.size(); ++iP) {
220 const auto& particleA{particles[iP]};
221 if (particleA.GetPDG() != -211) {
224 const auto& particleInfoA{(*fpParticleInfo)[iP]};
225 for (
size_t iQ = 0; iQ < particles.size(); ++iQ) {
226 const auto& particleB{particles[iQ]};
227 if (particleB.GetPDG() != 2212) {
230 const auto& particleInfoB{(*fpParticleInfo)[iQ]};
231 if (particleInfoA.eventID == particleInfoB.eventID) {
235 const KFParticle* pDaughters[2] = {&particleA, &particleB};
237 particle.Construct(pDaughters, 2,
nullptr);
238 particle.AddDaughterId(iP);
239 particle.AddDaughterId(iQ);
251 for (
int iTrk = 0; iTrk < nTracks; ++iTrk) {
253 const auto& trkInfo = (*fpTrackInfo)[iTrk];
255 bool bMomDefined = !std::isnan(par->GetQp());
258 double p = bMomDefined ? mom.Mag() : -9999.;
259 double pt = bMomDefined ? mom.Perp() : -9999.;
262 int pdg = pTrk->GetPidHypo();
265 h.beta->Fill(trkInfo.beta);
266 h.dca_rt_origin->Fill(trkInfo.dca);
278 else if (pdg == 2212) {
284 if (
fpCutter->SelectTrack(Cutter_t::TrackProperty{
285 .dcaRelToOrigin = trkInfo.dca,
286 .beta = trkInfo.beta,
293 else if (pdg == 2212) {
305 LOG(error) << fName <<
": data branches from V0FinderTask are not initialized. Make sure, that the SetDataBranches "
306 <<
"was called from the macro";
310 auto* pFairManager = FairRootManager::Instance();
312 LOG(error) << fName <<
": FairRootManager not found";
316 auto InitBranch = [&](TClonesArray*& branch,
const char* name) ->
bool {
317 branch =
dynamic_cast<TClonesArray*
>(pFairManager->GetObject(name));
319 LOG(error) << fName <<
": branch \"" << name <<
"\" not found";
325 bool bBranchesInitialized{
true};
326 bBranchesInitialized = InitBranch(
fpBrGlobalTracks,
"GlobalTrack") && bBranchesInitialized;
327 if (!bBranchesInitialized) {
340 auto InitRefPrt = [&](
RefHistogramsPrt&
h,
const std::string& prefN,
const std::string& prefT) {
343 Form(
"%s_beta", prefN.c_str()),
344 Form(
"#beta %s;#beta;Counts", prefT.c_str()),
347 Form(
"%s_dca_rt_origin", prefN.c_str()),
348 Form(
"DCA rel. to origin %s;DCA_{origin} [cm];Counts", prefT.c_str()),
351 Form(
"%s_p", prefN.c_str()),
352 Form(
"Momentum %s;p [GeV/c];Counts", prefT.c_str()),
355 Form(
"%s_pt", prefN.c_str()),
356 Form(
"Transverse momentum %s;p_{T} [GeV/c];Counts", prefT.c_str()),
361 auto InitRef = [&](
RefHistograms&
h,
const std::string& prefN,
const std::string& prefT) {
362 InitRefPrt(
h.pion, Form(
"%s_pion", prefN.c_str()), Form(
"pions %s", prefT.c_str()));
363 InitRefPrt(
h.proton, Form(
"%s_proton", prefN.c_str()), Form(
"protons %s", prefT.c_str()));
364 InitRefPrt(
h.all, Form(
"%s_all", prefN.c_str()), Form(
"all %s", prefT.c_str()));
367 auto InitRefV0 = [&](
RefHistogramsV0&
h,
const std::string& prefN,
const std::string& prefT) {
370 Form(
"%s_opening_angle", prefN.c_str()),
371 Form(
"Opening angle of daughters %s;#alpha [radians];Counts", prefT.c_str()),
374 Form(
"%s_opening_angle_kf", prefN.c_str()),
375 Form(
"Opening angle of daughters (KFParticle) %s;#alpha [radians];Counts", prefT.c_str()),
378 Form(
"%s_dca_rt_origin", prefN.c_str()),
379 Form(
"DCA rel. to prim. vertex %s;DCA_{PV} [cm];Counts", prefT.c_str()),
382 Form(
"%s_dca_daughters", prefN.c_str()),
383 Form(
"DCA between daughters %s;DCA_{daughters} [cm];Counts", prefT.c_str()),
386 Form(
"%s_decay_length", prefN.c_str()),
387 Form(
"Decay length %s;L [cm];Counts", prefT.c_str()),
390 Form(
"%s_decay_vtx_z", prefN.c_str()),
391 Form(
"Decay vertex z-coordinate %s;z_{v0-vertex} [cm];Counts", prefT.c_str()),
394 Form(
"%s_decay_vtx_xy", prefN.c_str()),
395 Form(
"Decay vertex in xy plane %s;x_{v0-vertex} [cm];y_{v0-vertex} [cm];Counts", prefT.c_str()),
398 Form(
"%s_chi2ndf_topo", prefN.c_str()),
399 Form(
"#chi^{2}/NDF to PV %s; #chi^2/NDF;Counts", prefT.c_str()),
402 Form(
"%s_chi2ndf_geo", prefN.c_str()),
403 Form(
"#chi^{2}/NDF to origin %s; #chi^2/NDF;Counts", prefT.c_str()),
406 Form(
"%s_mass", prefN.c_str()),
407 Form(
"Invariant mass %s; m_{inv} [GeV/c^{2}];Counts", prefT.c_str()),
420 InitRefV0(
fhRefMeBefore,
"me_bef",
"mixed-event bef. selection");
421 InitRefV0(
fhRefMeAfter,
"me_aft",
"mixed-event aft. selection");
429 constexpr double MaxDifferenceV0Tof{0.001};
430 constexpr size_t MaxNofIterations{25};
431 double v0DecayLength{mX.r()};
432 double v0Tof{mX.t()};
433 double v0TofLast{100.};
436 auto aR = aX.Vect() - mX.Vect();
437 auto bR = bX.Vect() - mX.Vect();
440 constexpr double MaxBeta{0.9999};
443 double gamma = 1. / std::sqrt(1 - beta * beta);
444 double mom = beta * gamma * mass;
446 P =
PVector4_t(p.x(), p.y(), p.z(), std::sqrt(mom * mom + mass * mass));
447 LOG(info) <<
"iter: " << iIter <<
", mass=" << mass <<
", beta=" << beta <<
", mom=" << mom <<
", v0R=" << mX.r();
450 while (std::fabs(v0Tof - v0TofLast) > MaxDifferenceV0Tof && iIter <= MaxNofIterations) {
451 ShiftMomentum(aX.T(), aR, aP);
452 ShiftMomentum(bX.T(), bR, bP);
456 LOG(info) <<
"iter: " << iIter <<
", v0Tof=" << v0TofLast <<
", mom=" << mP.P() <<
", mass=" << mP.M();
468 LOG(fatal) << fName <<
": a nullptr V0FinderTask instance is passed to InitData() function";
473 LOG(fatal) << fName <<
": the topology reconstructor is not defined in the finder task";
478 LOG(fatal) << fName <<
": the V0-cutter class is not defined in the finder task";
A simple QA for the V0 finder class (runs together with the finder task)
A selector class for V0-candidates in mCBM.
const FairTrackParam * GetParamFirst() const
T * MakeQaObject(TString sName, TString sTitle, Args... args)
Data class with information on a STS local track.
A QA-task for the V0-finding algorithm.
static constexpr int kBdca_rt_pv
DCA rel. to prim. vertex: number of bins.
static constexpr int kBdecay_vtx_y
Decay vertex y-coordinate: number of bins.
void FillTracks()
Fills track distributions.
static constexpr double kUdecay_vtx_y
Decay vertex y-coordinate: upper bound [cm].
static constexpr int kBbeta
beta: number of bins
static constexpr double kUchi2ndf_geo
chi2/NDF geometry: upper bound
static constexpr int kBdca_rt_origin
DCA rel. to origin: number of bins.
static constexpr double kLdca_rt_origin
DCA rel. to origin: lower bound [cm].
std::shared_ptr< const KFParticleTopoReconstructor > fpTopoReconstructor
static constexpr double kLpt
transverse momentum : lower bound [GeV/c]
static constexpr double kLdecay_length
Decay length: lower bound [cm].
static constexpr double kLdecay_vtx_z
Decay vertex z-coordinate: lower bound [cm].
const std::vector< V0FinderTask::ParticleInfo > * fpParticleInfo
void FillSecondary(RefHistogramsPrt &h, const KFParticle &prt, const V0FinderTask::ParticleInfo &prtInfo)
Fills secondary distributions.
const std::vector< V0FinderTask::TrackInfo > * fpTrackInfo
static constexpr double kUmass
Invariant mass: upper bound [GeV/c2].
static constexpr double kLdecay_vtx_y
Decay vertex y-coordinate: lower bound [cm].
RefHistograms fhRefTracksBefore
Track distributions before track selection.
static constexpr double kUp
abs. momentum : upper bound [GeV/c]
static constexpr int kBopening_angle
opening angle: number of bins
RefHistograms fhRefDaughtersAfter
Daughter particle distribution after cuts on v0.
static constexpr double kUdca_rt_origin
DCA rel. to origin: upper bound [cm].
static constexpr int kBdecay_vtx_x
Decay vertex x-coordinate: number of bins.
void ExecQa()
Executes QA.
static constexpr double kLchi2ndf_topo
chi2/NDF topology: lower bound
ROOT::Math::XYZVector Vector3_t
static constexpr double kLopening_angle
opening angle: lower bound [radians]
static constexpr double kLp
abs. momentum : lower bound [GeV/c]
static constexpr int kBchi2ndf_topo
chi2/NDF topology: number of bins
static constexpr double kLdca_rt_pv
DCA rel. to prim. vertex: lower bound [cm].
static constexpr double kUbeta
beta: upper bound [c]
void FillV0Candidates(const KFParticle &v0cand)
Fills v0 distributions.
static constexpr double kUdecay_vtx_z
Decay vertex z-coordinate: upper bound [cm].
static constexpr double kLmass
Invariant mass: lower bound [GeV/c2].
static constexpr int kBdca_daughters
DCA between daughters: number of bins.
static constexpr double kLdca_daughters
DCA between daughters: lower bound [cm].
static constexpr int kBdecay_length
Decay length: number of bins.
ROOT::Math::XYZTVector XVector4_t
static constexpr double kUdca_rt_pv
DCA rel. to prim. vertex: upper bound [cm].
RefHistograms fhRefDaughtersBefore
Daughter particle distribution before cuts on v0.
static constexpr double kLbeta
beta: lower bound [c]
RefHistogramsV0 fhRefV0After
V0 distributions after cuts.
RefHistograms fhRefSecondaryUnused
Secondary particles, which were not attached to any v0.
RefHistograms fhRefTracksAfter
Track distributions after track selection.
static constexpr double kLdecay_vtx_x
Decay vertex x-coordinate: lower bound [cm].
RefHistogramsV0 fhRefV0Before
V0 distributions before cuts.
void FillParticles()
Fill particles.
static constexpr double kUchi2ndf_topo
chi2/NDF topology: upper bound
static constexpr double kUdecay_length
Decay length: upper bound [cm].
InitStatus InitQa()
Initializes QA.
static constexpr int kBmass
Invariant mass: number of bins.
void Refit(const XVector4_t &aX, const XVector4_t &bX, XVector4_t &mX, PVector4_t &aP, PVector4_t &bP, PVector4_t &mP)
Refits 4-momenta of daughters.
static constexpr double kUdca_daughters
DCA between daughters: upper bound [cm].
void SetFrom(const V0FinderTask *pFinder)
Sets data branches from V0FinderTask.
static constexpr int kBdecay_vtx_z
Decay vertex z-coordinate: number of bins.
static constexpr double kUpt
transverse momentum : upper bound [GeV/c]
static constexpr double kLchi2ndf_geo
chi2/NDF geometry: lower bound
static constexpr double kUdecay_vtx_x
Decay vertex x-coordinate: upper bound [cm].
void InitHistograms()
Initializes histograms.
RefHistogramsV0 fhRefMeAfter
Mixed-event distributions after cuts.
RefHistogramsV0 fhRefMeBefore
Mixed-event distributions before cuts.
ROOT::Math::PxPyPzEVector PVector4_t
static constexpr int kBp
abs. momentum : number of bins
std::shared_ptr< const Cutter_t > fpCutter
bool fbDataBranchesInitialized
static constexpr double kUopening_angle
opening angle: upper bound [radians]
static constexpr int kBchi2ndf_geo
chi2/NDF geometry: number of bins
TClonesArray * fpBrGlobalTracks
static constexpr int kBpt
transverse momentum : number of bins
RefHistograms fhRefSecondaryStored
Stored secondary particles.
A class to find V0 candidates in mCBM.
const std::vector< TrackInfo > & GetTrackInfo() const
Accessor to the track extra info.
std::shared_ptr< const Cutter_t > GetCutter() const
Accessor to the cutter.
static constexpr double kSpeedOfLight
Speed of light [cm/ns].
std::shared_ptr< const KFParticleTopoReconstructor > GetTopoReconstructor() const
Accessor to the topology reconstructor.
const std::vector< ParticleInfo > & GetParticleInfo() const
Accessor to the particle extra info.
ETrackPid
An enumeration for PID of global tracks.
A collection of reference histograms for a particle (specific or all)
A collection of reference histograms for V0 candidates.
A collection of reference histograms for different analysis stage.
Extra information on KFParticle, required by the V0 analysis.
double beta
Speed of particle [c] (from TOF hit info)
double dca
DCA to origin [cm] (from STS hit info)