1+ // Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+ // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+ // All rights not expressly granted are reserved.
4+ //
5+ // This software is distributed under the terms of the GNU General Public
6+ // License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+ //
8+ // In applying this license CERN does not waive the privileges and immunities
9+ // granted to it by virtue of its status as an Intergovernmental Organization
10+ // or submit itself to any jurisdiction.
11+
12+ // /
13+ // / \file strangenessBuilderHelper.cxx
14+ // / \since 07/01/2025
15+ // / \brief Utilities to build strange decays in a modular way. Used by strangeness builder task
16+ // /
17+
18+ #include " strangenessBuilderHelper.h"
19+ #include " ReconstructionDataFormats/Track.h"
20+ #include " DetectorsBase/GeometryManager.h"
21+ #include " CommonConstants/PhysicsConstants.h"
22+ #include " Framework/AnalysisDataModel.h"
23+ #include " Common/Core/trackUtilities.h"
24+
25+ namespace o2
26+ {
27+ namespace pwglf
28+ {
29+ // _______________________________________________________________
30+ strangenessBuilderHelper::strangenessBuilderHelper () {
31+ // standards hardcoded in builder ...
32+ // ...but can be changed easily since fitter is public
33+ fitter.setPropagateToPCA (true );
34+ fitter.setMaxR (200 .);
35+ fitter.setMinParamChange (1e-3 );
36+ fitter.setMinRelChi2Change (0.9 );
37+ fitter.setMaxDZIni (1e9 );
38+ fitter.setMaxDXYIni (4 .0f );
39+ fitter.setMaxChi2 (1e9 );
40+ fitter.setUseAbsDCA (true );
41+ fitter.setWeightedFinalPCA (false );
42+
43+ // LUT has to be loaded later
44+ lut = nullptr ;
45+ fitter.setMatCorrType (o2::base::Propagator::MatCorrType::USEMatCorrLUT);
46+
47+ // mag field has to be set later
48+ fitter.setBz (-999 .9f ); // will NOT make sense if not changed
49+ }
50+
51+ // _______________________________________________________________
52+ // builds V0 from two tracks. Does not check any conditionals
53+ // except for DCA fitter convergence (should be minimal overhead)
54+ // Resulting properties can be checked with strangenessBuilderHelper::v0
55+ bool strangenessBuilderHelper::buildV0Candidate (
56+ o2::aod::Collision const & collision,
57+ soa::Join<o2::aod::TracksIU, o2::aod::TracksExtra, o2::aod::TracksCovIU>::iterator const & positiveTrack,
58+ soa::Join<o2::aod::TracksIU, o2::aod::TracksExtra, o2::aod::TracksCovIU>::iterator const & negativeTrack,
59+ bool useCollinearFit){
60+ // Calculate DCA with respect to the collision associated to the V0, not individual tracks
61+ gpu::gpustd::array<float , 2 > dcaInfo;
62+
63+ auto posTrackPar = getTrackPar (positiveTrack);
64+ o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, posTrackPar, 2 .f , fitter.getMatCorrType (), &dcaInfo);
65+ v0.positiveDCAxy = dcaInfo[0 ];
66+
67+ auto negTrackPar = getTrackPar (negativeTrack);
68+ o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, negTrackPar, 2 .f , fitter.getMatCorrType (), &dcaInfo);
69+ v0.negativeDCAxy = dcaInfo[0 ];
70+
71+ o2::track::TrackParCov positiveTrackParam = getTrackParCov (positiveTrack);
72+ o2::track::TrackParCov negativeTrackParam = getTrackParCov (negativeTrack);
73+
74+ // Perform DCA fit
75+ int nCand = 0 ;
76+ fitter.setCollinear (useCollinearFit);
77+ try {
78+ nCand = fitter.process (positiveTrackParam, negativeTrackParam);
79+ } catch (...) {
80+ return false ;
81+ }
82+ if (nCand == 0 ) {
83+ return false ;
84+ }
85+
86+ v0.positiveTrackX = fitter.getTrack (0 ).getX ();
87+ v0.negativeTrackX = fitter.getTrack (1 ).getX ();
88+ positiveTrackParam = fitter.getTrack (0 );
89+ negativeTrackParam = fitter.getTrack (1 );
90+ positiveTrackParam.getPxPyPzGlo (v0.positiveMomentum );
91+ negativeTrackParam.getPxPyPzGlo (v0.negativeMomentum );
92+ positiveTrackParam.getXYZGlo (v0.positivePosition );
93+ negativeTrackParam.getXYZGlo (v0.negativePosition );
94+
95+ // get decay vertex coordinates
96+ const auto & vtx = fitter.getPCACandidate ();
97+ for (int i = 0 ; i < 3 ; i++) {
98+ v0.position [i] = vtx[i];
99+ }
100+
101+ v0.daughterDCA = TMath::Sqrt (fitter.getChi2AtPCACandidate ());
102+ v0.pointingAngle = TMath::ACos (RecoDecay::cpa (
103+ std::array{collision.posX (), collision.posY (), collision.posZ ()},
104+ std::array{v0.position [0 ], v0.position [1 ], v0.position [2 ]},
105+ std::array{v0.positiveMomentum [0 ] + v0.negativeMomentum [0 ], v0.positiveMomentum [1 ] + v0.negativeMomentum [1 ], v0.positiveMomentum [2 ] + v0.negativeMomentum [2 ]}
106+ ));
107+
108+ v0.dcaXY = CalculateDCAStraightToPV (
109+ v0.position [0 ], v0.position [1 ], v0.position [2 ],
110+ v0.positiveMomentum [0 ] + v0.negativeMomentum [0 ],
111+ v0.positiveMomentum [1 ] + v0.negativeMomentum [1 ],
112+ v0.positiveMomentum [2 ] + v0.negativeMomentum [2 ],
113+ collision.posX (), collision.posY (), collision.posZ ());
114+
115+ // Calculate masses
116+ v0.massGamma = RecoDecay::m (std::array{
117+ std::array{v0.positiveMomentum [0 ], v0.positiveMomentum [1 ], v0.positiveMomentum [2 ]},
118+ std::array{v0.negativeMomentum [0 ], v0.negativeMomentum [1 ], v0.negativeMomentum [2 ]}},
119+ std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron});
120+ v0.massK0Short = RecoDecay::m (std::array{
121+ std::array{v0.positiveMomentum [0 ], v0.positiveMomentum [1 ], v0.positiveMomentum [2 ]},
122+ std::array{v0.negativeMomentum [0 ], v0.negativeMomentum [1 ], v0.negativeMomentum [2 ]}},
123+ std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged});
124+ v0.massLambda = RecoDecay::m (std::array{
125+ std::array{v0.positiveMomentum [0 ], v0.positiveMomentum [1 ], v0.positiveMomentum [2 ]},
126+ std::array{v0.negativeMomentum [0 ], v0.negativeMomentum [1 ], v0.negativeMomentum [2 ]}},
127+ std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged});
128+ v0.massAntiLambda = RecoDecay::m (std::array{
129+ std::array{v0.positiveMomentum [0 ], v0.positiveMomentum [1 ], v0.positiveMomentum [2 ]},
130+ std::array{v0.negativeMomentum [0 ], v0.negativeMomentum [1 ], v0.negativeMomentum [2 ]}},
131+ std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton});
132+
133+ // information validated, V0 built successfully. Signal OK
134+ return true ;
135+ }
136+
137+ // _______________________________________________________________
138+ // internal helper to calculate DCAxy of a straight line to a given PV analytically
139+ float strangenessBuilderHelper::CalculateDCAStraightToPV (float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ)
140+ {
141+ return std::sqrt ((std::pow ((pvY - Y) * Pz - (pvZ - Z) * Py, 2 ) + std::pow ((pvX - X) * Pz - (pvZ - Z) * Px, 2 ) + std::pow ((pvX - X) * Py - (pvY - Y) * Px, 2 )) / (Px * Px + Py * Py + Pz * Pz));
142+ }
143+
144+ // _______________________________________________________________
145+ } // namespace pwglf
146+ } // namespace o2
0 commit comments