1919#include " Common/Core/RecoDecay.h"
2020#include " Common/Core/trackUtilities.h"
2121#include " PWGLF/DataModel/LFStrangenessTables.h"
22+ #include " PWGLF/DataModel/LFStrangenessMLTables.h"
2223#include " PWGLF/DataModel/LFParticleIdentification.h"
2324#include " Common/Core/TrackSelection.h"
2425#include " Common/DataModel/McCollisionExtra.h"
@@ -64,6 +65,8 @@ using CollisionsWithEvSels = soa::Join<aod::Collisions, aod::EvSels>;
6465using LabeledTracksExtra = soa::Join<aod::TracksIU, aod::TracksCovIU, aod::TracksExtra, aod::McTrackLabels>;
6566
6667struct v0assoqa {
68+ Produces<aod::V0Duplicates> photonDuplicates;
69+
6770 HistogramRegistry histos{" Histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
6871
6972 // helper object
@@ -78,6 +81,9 @@ struct v0assoqa {
7881 // for handling TPC-only tracks (photons)
7982 o2::aod::common::TPCVDriftManager mVDriftMgr ;
8083
84+ // ML for deduplication
85+ Configurable<bool > fillDuplicatesTable{" fillDuplicatesTable" , false , " if true, fill table with duplicated v0s" };
86+
8187 // CCDB options
8288 struct : ConfigurableGroup {
8389 std::string prefix = " ccdb" ;
@@ -153,6 +159,96 @@ struct v0assoqa {
153159 return motherid1;
154160 }
155161
162+ // __________________________________________
163+ // Helper structure to save v0 duplicates auxiliary info
164+ struct V0DuplicateExtra {
165+ float collX;
166+ float collY;
167+ float collZ;
168+ float collTime;
169+ float v0PosTrackTime;
170+ float v0NegTrackTime;
171+ float v0DauDCAxy;
172+ float v0DauDCAz;
173+ int v0CollIdx;
174+ bool v0IsCorrectlyAssociated;
175+ bool isBuildOk;
176+ };
177+
178+ // _______________________________________________________________________
179+ // Fill tables with duplicated photons
180+ void processDuplicatesTable (std::vector<o2::pwglf::v0candidate> v0duplicates, std::vector<V0DuplicateExtra> V0DuplicateExtras, std::vector<o2::pwglf::V0group> V0Grouped, size_t iV0)
181+ {
182+
183+ float AvgPA = 0 .0f ;
184+ float AvgZ = 0 .0f ;
185+ float AvgDCAxy = 0 .0f ;
186+ float AvgDCAz = 0 .0f ;
187+
188+ for (size_t ic = 0 ; ic < V0Grouped[iV0].collisionIds .size (); ic++) {
189+ if (!V0DuplicateExtras[ic].isBuildOk ) {
190+ continue ; // skip not built V0s
191+ }
192+ AvgPA += v0duplicates[ic].pointingAngle ;
193+ AvgDCAxy += V0DuplicateExtras[ic].v0DauDCAxy ;
194+ AvgDCAz += V0DuplicateExtras[ic].v0DauDCAz ;
195+ }
196+
197+ AvgPA /= V0Grouped[iV0].collisionIds .size ();
198+ AvgDCAxy /= V0Grouped[iV0].collisionIds .size ();
199+ AvgDCAz /= V0Grouped[iV0].collisionIds .size ();
200+
201+ // fill duplicates table
202+ for (size_t ic = 0 ; ic < V0Grouped[iV0].collisionIds .size (); ic++) {
203+ if (!V0DuplicateExtras[ic].isBuildOk ) {
204+ continue ; // skip not built V0s
205+ }
206+
207+ float pxpos = v0duplicates[ic].positiveMomentum [0 ];
208+ float pypos = v0duplicates[ic].positiveMomentum [1 ];
209+ float pzpos = v0duplicates[ic].positiveMomentum [2 ];
210+ float pxneg = v0duplicates[ic].negativeMomentum [0 ];
211+ float pyneg = v0duplicates[ic].negativeMomentum [1 ];
212+ float pzneg = v0duplicates[ic].negativeMomentum [2 ];
213+
214+ float v0px = pxpos + pxneg;
215+ float v0py = pypos + pyneg;
216+ float v0pz = pzpos + pzneg;
217+
218+ float v0Z = v0duplicates[ic].position [2 ];
219+ float v0DCADau = v0duplicates[ic].daughterDCA ;
220+ float v0DCAxy = V0DuplicateExtras[ic].v0DauDCAxy ;
221+ float v0DCAz = V0DuplicateExtras[ic].v0DauDCAz ;
222+ float v0PA = v0duplicates[ic].pointingAngle ;
223+ float v0Radius = RecoDecay::sqrtSumOfSquares (v0duplicates[ic].position [0 ], v0duplicates[ic].position [1 ]);
224+ float v0PosDCAToPV = v0duplicates[ic].positiveDCAxy ;
225+ float v0NegDCAToPV = v0duplicates[ic].negativeDCAxy ;
226+ float v0Phi = RecoDecay::phi (v0px, v0py);
227+ float collX = V0DuplicateExtras[ic].collX ;
228+ float collY = V0DuplicateExtras[ic].collY ;
229+ float collZ = V0DuplicateExtras[ic].collZ ;
230+
231+ float v0PhotonMass = RecoDecay::m (std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron});
232+ float v0pt = RecoDecay::sqrtSumOfSquares (v0px, v0py);
233+
234+ float v0Y = RecoDecay::y (std::array{v0px, v0py, v0pz}, o2::constants::physics::MassElectron);
235+ float v0Eta = RecoDecay::eta (std::array{v0px, v0py, v0pz});
236+
237+ float v0PosTrackTime = V0DuplicateExtras[ic].v0PosTrackTime ;
238+ float v0NegTrackTime = V0DuplicateExtras[ic].v0NegTrackTime ;
239+ float collTime = V0DuplicateExtras[ic].collTime ;
240+ int v0CollIdx = V0DuplicateExtras[ic].v0CollIdx ;
241+ bool v0IsCorrectlyAssociated = V0DuplicateExtras[ic].v0IsCorrectlyAssociated ;
242+
243+ // fill table
244+ photonDuplicates (v0Z, v0DCADau, v0DCAxy, v0DCAz, v0PA, v0Radius, v0PosDCAToPV, v0NegDCAToPV, v0Phi,
245+ collX, collY, collZ, AvgDCAxy, AvgDCAz, AvgPA, AvgZ,
246+ v0PhotonMass, v0pt, v0px, v0py, v0pz, v0Y, v0Eta,
247+ v0PosTrackTime, v0NegTrackTime, collTime,
248+ v0CollIdx, v0IsCorrectlyAssociated);
249+ }
250+ }
251+
156252 void init (InitContext const &)
157253 {
158254 histos.add (" hDuplicateCount" , " hDuplicateCount" , kTH1F , {{50 , -0 .5f , 49 .5f }});
@@ -257,6 +353,7 @@ struct v0assoqa {
257353 return true ;
258354 }
259355
356+
260357 void process (soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels> const & collisions, aod::McCollisions const & mcCollisions, aod::V0s const & V0s, LabeledTracksExtra const & tracks, aod::McParticles const & mcParticles, aod::BCsWithTimestamps const & bcs)
261358 {
262359 if (!initCCDB (bcs, collisions))
@@ -321,6 +418,7 @@ struct v0assoqa {
321418
322419 std::vector<o2::pwglf::v0candidate> v0duplicates; // Vector of v0 candidate duplicates
323420 std::vector<bool > v0duplicatesCorrectlyAssociated;
421+ std::vector<V0DuplicateExtra> V0DuplicateExtras; // Vector to store V0 duplicate info
324422
325423 // de-duplication strategy tests start here
326424 // store best-of index for cross-checking strict de-duplication techniques
@@ -349,9 +447,7 @@ struct v0assoqa {
349447 correctlyAssociated = true ;
350448 }
351449 }
352- // store check for correct association
353- v0duplicatesCorrectlyAssociated.push_back (correctlyAssociated);
354-
450+
355451 // actually treat tracks
356452 auto posTrackPar = getTrackParCov (pTrack);
357453 auto negTrackPar = getTrackParCov (nTrack);
@@ -383,10 +479,9 @@ struct v0assoqa {
383479 }
384480 } // end TPC drift treatment
385481
482+
386483 // process candidate with helper
387- bool buildOK = straHelper.buildV0Candidate (v0tableGrouped[iV0].collisionIds [ic], collision.posX (), collision.posY (), collision.posZ (), pTrack, nTrack, posTrackPar, negTrackPar, true , false );
388-
389- v0duplicates.push_back (straHelper.v0 );
484+ bool buildOK = straHelper.buildV0Candidate <false >(v0tableGrouped[iV0].collisionIds [ic], collision.posX (), collision.posY (), collision.posZ (), pTrack, nTrack, posTrackPar, negTrackPar, true , false , true );
390485
391486 float daughterDCA3D = std::hypot (
392487 straHelper.v0 .positivePosition [0 ] - straHelper.v0 .negativePosition [0 ],
@@ -402,6 +497,25 @@ struct v0assoqa {
402497 daughterDCA3D = daughterDCAXY = daughterDCAZ = 1e+6 ;
403498 }
404499
500+ // V0 Duplicates extras
501+ V0DuplicateExtra v0DuplicateInfo;
502+ v0DuplicateInfo.collX = collision.posX ();
503+ v0DuplicateInfo.collY = collision.posY ();
504+ v0DuplicateInfo.collZ = collision.posZ ();
505+ v0DuplicateInfo.collTime = collision.collisionTime ();
506+ v0DuplicateInfo.v0PosTrackTime = pTrack.trackTime ();
507+ v0DuplicateInfo.v0NegTrackTime = nTrack.trackTime ();
508+ v0DuplicateInfo.v0DauDCAxy = daughterDCAXY;
509+ v0DuplicateInfo.v0DauDCAz = daughterDCAZ;
510+ v0DuplicateInfo.v0CollIdx = v0tableGrouped[iV0].collisionIds [ic];
511+ v0DuplicateInfo.v0IsCorrectlyAssociated = correctlyAssociated;
512+ v0DuplicateInfo.isBuildOk = buildOK;
513+
514+ // store check for correct association + saving duplicates info
515+ v0duplicatesCorrectlyAssociated.push_back (correctlyAssociated);
516+ v0duplicates.push_back (straHelper.v0 );
517+ V0DuplicateExtras.push_back (v0DuplicateInfo);
518+
405519 histos.fill (HIST (" hPA_All" ), straHelper.v0 .pointingAngle );
406520 histos.fill (HIST (" hPAvsPt_All" ), mcV0.pt (), straHelper.v0 .pointingAngle );
407521 histos.fill (HIST (" hDCADaughtersvsPt_All" ), mcV0.pt (), straHelper.v0 .daughterDCA );
@@ -463,6 +577,8 @@ struct v0assoqa {
463577 }
464578 }
465579
580+ if (fillDuplicatesTable) processDuplicatesTable (v0duplicates, V0DuplicateExtras, v0tableGrouped, iV0);
581+
466582 // printout for inspection
467583 // TString cosPAString = "";
468584 // for (size_t iCollisionId = 0; iCollisionId < v0tableGrouped[iV0].collisionIds.size(); iCollisionId++) {
0 commit comments