2424#include " PWGDQ/Core/VarManager.h"
2525#include " PWGDQ/DataModel/ReducedInfoTables.h"
2626
27+ #include " Common/DataModel/CollisionAssociationTables.h"
2728#include " Common/DataModel/EventSelection.h"
2829#include " Common/DataModel/PIDResponseTOF.h"
2930#include " Common/DataModel/PIDResponseTPC.h"
30- #include " Common/DataModel/TrackSelectionTables.h"
3131
3232#include < CCDB/BasicCCDBManager.h>
3333#include < DataFormatsParameters/GRPMagField.h>
@@ -60,20 +60,23 @@ using namespace o2::framework::expressions;
6060using namespace o2 ::aod;
6161using namespace o2 ::soa;
6262
63- using MyEvents = soa::Join<aod::Collisions, aod::EvSels>;
63+ // using MyEvents = soa::Join<aod::Collisions, aod::EvSels>
64+ using MyEventsWithCent = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs, aod::CentFT0As, aod::CentFT0Ms>;
6465
65- using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection, aod:: TracksDCA,
66+ using MyBarrelTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA,
6667 aod::pidTPCFullEl, aod::pidTPCFullPi, aod::pidTPCFullMu,
6768 aod::pidTPCFullKa, aod::pidTPCFullPr,
6869 aod::pidTOFFullEl, aod::pidTOFFullPi, aod::pidTOFFullMu,
6970 aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFbeta>;
7071
71- constexpr static uint32_t EventFillMap = VarManager::ObjTypes::Collision;
72- constexpr static uint32_t TrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackPID;
72+ // constexpr static uint32_t EventFillMap = VarManager::ObjTypes::Collision;
73+ constexpr static uint32_t EventFillMapWithCent = VarManager::ObjTypes::Collision| VarManager::ObjTypes::CollisionCent;
74+ constexpr static uint32_t TrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackPID;
7375
7476struct DalitzSelection {
7577 Produces<o2::aod::DalitzBits> dalitzbits;
7678 Preslice<MyBarrelTracks> perCollision = aod::track::collisionId;
79+ Preslice<aod::TrackAssoc> trackIndicesPerCollision = aod::track_association::collisionId;
7780
7881 // Configurables
7982 // cuts
@@ -102,6 +105,7 @@ struct DalitzSelection {
102105 struct : ConfigurableGroup {
103106 Configurable<bool > fConfigEnableLikeSign {" cfgEnableLikeSign" , false , " Whether or not also add like-sign pairs (for studying combinatorial background which might contain misID or non-primary electrons)" };
104107 Configurable<bool > fQA {" cfgQA" , true , " QA histograms" };
108+ Configurable<bool > fRemoveDoubleCounting {" cfgRemoveDoubleCounting" , true , " If a track/pair is selected for several collisions, we still count it only once" };
105109 // Configurables for TPC post-calibration maps
106110 Configurable<std::string> fConfigCcdbUrl {" ccdb-url" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
107111 Configurable<std::string> fConfigCcdbPathTPC {" ccdb-path-tpc" , " Users/i/iarsene/Calib/TPCpostCalib" , " base path to the ccdb object" };
@@ -125,6 +129,11 @@ struct DalitzSelection {
125129 std::map<int , uint8_t > fTrackmapProbe ; // whether it is selected with probe cut
126130 std::map<int , uint8_t > fDalitzmap ; // whether it is selected as dalitz decay daughter with symmetric or tag cut
127131 std::map<int , uint8_t > fDalitzmapProbe ; // whether it is selected as dalitz decay daughter with probe cut
132+
133+ // maps to remove ambiguities
134+ std::map<int , uint8_t > fDalitzmapAmbiguity ;
135+ std::map<int , uint8_t > fDalitzmapProbeAmbiguity ;
136+ std::map<std::pair<int , int >, uint8_t > fAmbiguousPairs ;
128137
129138 AnalysisCompositeCut* fEventCut ;
130139 std::vector<AnalysisCompositeCut> fTrackCuts ;
@@ -295,13 +304,23 @@ struct DalitzSelection {
295304 fOutputList .setObject (fHistMan ->GetMainHistogramList ());
296305 }
297306
298- template <uint32_t TTrackFillMap, typename TTracks>
299- void runTrackSelection (TTracks const & tracksBarrel)
307+ template <bool isReassoc, uint32_t TTrackFillMap, typename TTracks, typename TEvent >
308+ void runTrackSelection (TTracks const & tracksBarrel, TEvent const & collision )
300309 {
301- for (const auto & track : tracksBarrel) {
310+ for (const auto & track1 : tracksBarrel) {
302311 uint8_t filterMap = uint8_t (0 );
303312 uint8_t filterMapProbe = uint8_t (0 );
304- VarManager::FillTrack<TTrackFillMap>(track);
313+ int fullTrackIdx = 0 ;
314+ if constexpr (isReassoc) {
315+ auto const & fullTrack = track1.template track_as <MyBarrelTracks>();
316+ VarManager::FillTrack<TTrackFillMap>(fullTrack);
317+ VarManager::FillTrackCollision<TTrackFillMap>(fullTrack, collision);
318+ fullTrackIdx = fullTrack.globalIndex ();
319+ }
320+ else {
321+ VarManager::FillTrack<TTrackFillMap>(track1);
322+ fullTrackIdx = track1.globalIndex ();
323+ }
305324 int i = 0 ;
306325 for (auto cut = fTrackCuts .begin (); cut != fTrackCuts .end (); ++cut, ++i) {
307326 if ((*cut).IsSelected (VarManager::fgValues)) {
@@ -317,35 +336,66 @@ struct DalitzSelection {
317336 }
318337 }
319338 if (filterMap) {
320- fTrackmap [track. globalIndex () ] = filterMap;
339+ fTrackmap [fullTrackIdx ] = filterMap;
321340 }
322341 if (filterMapProbe) {
323- fTrackmapProbe [track. globalIndex () ] = filterMapProbe;
342+ fTrackmapProbe [fullTrackIdx ] = filterMapProbe;
324343 }
325344 } // end loop over tracks
326345 }
327346
328- template <int TPairType, uint32_t TTrackFillMap, typename TTracks>
329- void runDalitzPairing (TTracks const & tracks1, TTracks const & tracks2)
347+ template <bool isReassoc, int TPairType, uint32_t TTrackFillMap, typename TTracks, typename TEvent >
348+ void runDalitzPairing (TTracks const & tracks1, TTracks const & tracks2, TEvent collision )
330349 {
350+ if (isReassoc & fConfigOptions .fRemoveDoubleCounting ) {
351+ // keep track of selections from previous events to check if the track was already selected or not
352+ fDalitzmapAmbiguity = fDalitzmap ;
353+ fDalitzmapProbeAmbiguity = fDalitzmapProbe ;
354+ }
355+
331356 for (const auto & [track1, track2] : o2::soa::combinations (CombinationsFullIndexPolicy (tracks1, tracks2))) {
332- if (track1.globalIndex () == track2.globalIndex ()) {
357+
358+ int trackIdx1;
359+ int trackIdx2;
360+ bool isLikeSign;
361+ if constexpr (isReassoc) {
362+ auto const & fullTrack1 = track1.template track_as <MyBarrelTracks>();
363+ auto const & fullTrack2 = track2.template track_as <MyBarrelTracks>();
364+ trackIdx1 = fullTrack1.globalIndex ();
365+ trackIdx2 = fullTrack2.globalIndex ();
366+ isLikeSign = (fullTrack1.sign () * fullTrack2.sign () > 0 );
367+ }
368+ else {
369+ trackIdx1 = track1.globalIndex ();
370+ trackIdx2 = track2.globalIndex ();
371+ isLikeSign = (track1.sign () * track2.sign () > 0 );
372+ }
373+
374+ if (trackIdx1 == trackIdx2) {
333375 continue ;
334376 }
335- if (!fIsTagAndProbe && track1. globalIndex () >= track2. globalIndex () ) {
377+ if (!fIsTagAndProbe && trackIdx1 >= trackIdx2 ) {
336378 continue ;
337379 }
338- if (!fConfigOptions .fConfigEnableLikeSign && (track1. sign () * track2. sign () > 0 ) ) {
380+ if (!fConfigOptions .fConfigEnableLikeSign && isLikeSign ) {
339381 continue ;
340382 }
341383
342- uint8_t twoTracksFilterMap = fTrackmap [track1. globalIndex () ] & (fIsTagAndProbe ? fTrackmapProbe [track2. globalIndex () ] : fTrackmap [track2. globalIndex () ]);
384+ uint8_t twoTracksFilterMap = fTrackmap [trackIdx1 ] & (fIsTagAndProbe ? fTrackmapProbe [trackIdx2 ] : fTrackmap [trackIdx2 ]);
343385 if (!twoTracksFilterMap) {
344386 continue ;
345387 }
346388
347389 // pairing
348- VarManager::FillPair<TPairType, TTrackFillMap>(track1, track2);
390+ if constexpr (isReassoc) {
391+ auto const & fullTrack1 = track1.template track_as <MyBarrelTracks>();
392+ auto const & fullTrack2 = track2.template track_as <MyBarrelTracks>();
393+ VarManager::FillPair<TPairType, TTrackFillMap>(fullTrack1, fullTrack2);
394+ }
395+ else {
396+ VarManager::FillPair<TPairType, TTrackFillMap>(track1, track2);
397+ }
398+
349399
350400 // Fill pair selection map and fill pair histogram
351401 int icut = 0 ;
@@ -355,21 +405,35 @@ struct DalitzSelection {
355405 continue ;
356406 }
357407 if ((*pairCut).IsSelected (VarManager::fgValues)) {
358- if (track1.sign () * track2.sign () < 0 ) {
359- fDalitzmap [track1.globalIndex ()] |= (uint8_t (1 ) << icut);
408+ bool isPairAlreadySelected = false ;
409+ if (isReassoc & fConfigOptions .fRemoveDoubleCounting ) {
410+ // if we remove double counting and the pair is already selected, we don't fill the histograms
411+ std::pair<int , int > iPair (trackIdx1, trackIdx2);
412+ if (fAmbiguousPairs .find (iPair) != fAmbiguousPairs .end ()) {
413+ if (fAmbiguousPairs [iPair] & (static_cast <uint8_t >(1 ) << icut)) { // if this pair is already stored with this cut
414+ isPairAlreadySelected = true ;
415+ } else {
416+ fAmbiguousPairs [iPair] |= static_cast <uint8_t >(1 ) << icut;
417+ }
418+ } else {
419+ fAmbiguousPairs [iPair] = static_cast <uint8_t >(1 ) << icut;
420+ }
421+ }
422+ if (!isLikeSign) {
423+ fDalitzmap [trackIdx1] |= (uint8_t (1 ) << icut);
360424 if (fIsTagAndProbe ) {
361- fDalitzmapProbe [track2. globalIndex () ] |= (uint8_t (1 ) << icut);
362- if (fConfigOptions .fQA ) {
425+ fDalitzmapProbe [trackIdx2 ] |= (uint8_t (1 ) << icut);
426+ if (fConfigOptions .fQA && !isPairAlreadySelected ) {
363427 fHistMan ->FillHistClass (Form (" Pair_%s_%s_%s" , (*trackCut).GetName (), fTrackCutsProbe .at (icut).GetName (), (*pairCut).GetName ()), VarManager::fgValues);
364428 }
365429 } else {
366- fDalitzmap [track2. globalIndex () ] |= (uint8_t (1 ) << icut);
367- if (fConfigOptions .fQA ) {
430+ fDalitzmap [trackIdx2 ] |= (uint8_t (1 ) << icut);
431+ if (fConfigOptions .fQA && !isPairAlreadySelected ) {
368432 fHistMan ->FillHistClass (Form (" Pair_%s_%s" , (*trackCut).GetName (), (*pairCut).GetName ()), VarManager::fgValues);
369433 }
370434 }
371435 } else {
372- if (fConfigOptions .fQA ) {
436+ if (fConfigOptions .fQA && !isPairAlreadySelected ) {
373437 fHistMan ->FillHistClass (fIsTagAndProbe ? Form (" PairLS_%s_%s_%s" , (*trackCut).GetName (), fTrackCutsProbe .at (icut).GetName (), (*pairCut).GetName ()) : Form (" PairLS_%s_%s" , (*trackCut).GetName (), (*pairCut).GetName ()), VarManager::fgValues);
374438 }
375439 } // end if like-sign
@@ -380,12 +444,38 @@ struct DalitzSelection {
380444 // Fill Hists
381445 if (fConfigOptions .fQA ) {
382446 for (const auto & track : tracks1) {
383- uint8_t filterMap = fDalitzmap [track.globalIndex ()];
384- uint8_t filterMapProbe = fDalitzmapProbe [track.globalIndex ()];
385- if (!filterMap && !filterMapProbe) {
386- continue ;
447+ uint8_t filterMap;
448+ uint8_t filterMapProbe;
449+ if constexpr (isReassoc) {
450+ auto const & fullTrack = track.template track_as <MyBarrelTracks>();
451+ filterMap = fDalitzmap [fullTrack.globalIndex ()];
452+ filterMapProbe = fDalitzmapProbe [fullTrack.globalIndex ()];
453+ if (fConfigOptions .fRemoveDoubleCounting ) {
454+ // we remove track selections which were already selected before
455+ uint8_t previousFilterMap = fDalitzmapAmbiguity [fullTrack.globalIndex ()];
456+ uint8_t previousFilterMapProbe = fDalitzmapProbeAmbiguity [fullTrack.globalIndex ()];
457+ filterMap &= ~previousFilterMap;
458+ filterMapProbe &= ~previousFilterMapProbe;
459+ }
460+
461+ if (!filterMap && !filterMapProbe) {
462+ continue ;
463+ }
464+
465+ VarManager::FillTrack<TTrackFillMap>(fullTrack);
466+ // The caveat here is that we only fill the DCA to the first selected collision
467+ VarManager::FillTrackCollision<TTrackFillMap>(fullTrack, collision);
468+ }
469+ else {
470+ filterMap = fDalitzmap [track.globalIndex ()];
471+ filterMapProbe = fDalitzmapProbe [track.globalIndex ()];
472+
473+ if (!filterMap && !filterMapProbe) {
474+ continue ;
475+ }
476+
477+ VarManager::FillTrack<TTrackFillMap>(track);
387478 }
388- VarManager::FillTrack<TTrackFillMap>(track);
389479
390480 int icut = 0 ;
391481 auto trackCut = fTrackCuts .begin ();
@@ -403,7 +493,7 @@ struct DalitzSelection {
403493 }
404494 }
405495
406- void processFullTracks (MyEvents const & collisions, aod::BCsWithTimestamps const &, soa::Filtered<MyBarrelTracks> const & filteredTracks, MyBarrelTracks const & tracks)
496+ void processFullTracks (MyEventsWithCent const & collisions, aod::BCsWithTimestamps const &, soa::Filtered<MyBarrelTracks> const & filteredTracks, MyBarrelTracks const & tracks)
407497 {
408498 const int pairType = VarManager::kDecayToEE ;
409499 fDalitzmap .clear ();
@@ -413,7 +503,7 @@ struct DalitzSelection {
413503 fTrackmap .clear ();
414504 fTrackmapProbe .clear ();
415505 VarManager::ResetValues (VarManager::kNRunWiseVariables , VarManager::kNBarrelTrackVariables );
416- VarManager::FillEvent<EventFillMap >(collision);
506+ VarManager::FillEvent<EventFillMapWithCent >(collision);
417507 bool isEventSelected = fEventCut ->IsSelected (VarManager::fgValues);
418508
419509 if (isEventSelected) {
@@ -456,20 +546,89 @@ struct DalitzSelection {
456546 }
457547
458548 auto groupedFilteredTracks = filteredTracks.sliceBy (perCollision, collision.globalIndex ());
459- runTrackSelection<TrackFillMap>(groupedFilteredTracks);
460- runDalitzPairing<pairType, TrackFillMap>(groupedFilteredTracks, groupedFilteredTracks);
549+ runTrackSelection<false , TrackFillMap>(groupedFilteredTracks, nullptr );
550+ runDalitzPairing<false , pairType, TrackFillMap>(groupedFilteredTracks, groupedFilteredTracks, nullptr );
551+ }
552+ }
553+
554+ for (const auto & track : tracks) { // Fill dalitz bits
555+ dalitzbits (fIsTagAndProbe ? fDalitzmapProbe [track.globalIndex ()] : fDalitzmap [track.globalIndex ()]);
556+ }
557+ }
558+
559+ void processFullTracksWithAssoc (MyEventsWithCent const & collisions, aod::BCsWithTimestamps const &, MyBarrelTracks const & tracks, TrackAssoc const & trackAssocs)
560+ {
561+
562+ const int pairType = VarManager::kDecayToEE ;
563+ fDalitzmap .clear ();
564+ fDalitzmapProbe .clear ();
565+ fDalitzmapAmbiguity .clear ();
566+ fDalitzmapProbeAmbiguity .clear ();
567+ fAmbiguousPairs .clear ();
568+
569+ for (const auto & collision : collisions) {
570+ fTrackmap .clear ();
571+ fTrackmapProbe .clear ();
572+ VarManager::ResetValues (VarManager::kNRunWiseVariables , VarManager::kNBarrelTrackVariables );
573+ VarManager::FillEvent<EventFillMapWithCent>(collision);
574+ bool isEventSelected = fEventCut ->IsSelected (VarManager::fgValues);
575+
576+ if (isEventSelected) {
577+
578+ reinterpret_cast <TH1I*>(fStatsList ->At (0 ))->Fill (0 );
579+
580+ auto bc = collision.template bc_as <aod::BCsWithTimestamps>();
581+
582+ if (fCurrentRun != bc.runNumber ()) {
583+ VarManager::ResetValues (0 , VarManager::kNRunWiseVariables );
584+
585+ // We setup the magnetic field, because the conversion rejection cut might depend on it
586+ float magField = 0 .;
587+ if (fConfigOptions .fUseRemoteField .value ) {
588+ grpmag = fCCDB ->getForTimeStamp <o2::parameters::GRPMagField>(fConfigOptions .grpmagPath , bc.timestamp ());
589+ if (grpmag != nullptr ) {
590+ magField = grpmag->getNominalL3Field ();
591+ } else {
592+ LOGF (fatal, " GRP object is not available in CCDB at timestamp=%llu" , bc.timestamp ());
593+ }
594+ } else {
595+ magField = fConfigOptions .fConfigMagField .value ;
596+ }
597+ LOGF (info, " setting mag field to %f" , magField);
598+ if (magField == 0 .) {
599+ LOGF (fatal, " magnetic field not set correctly, please check" );
600+ }
601+ VarManager::SetMagneticField (magField);
602+
603+ if (fConfigOptions .fConfigComputeTPCpostCalib ) {
604+ auto calibList = fCCDB ->getForTimeStamp <TList>(fConfigOptions .fConfigCcdbPathTPC .value , bc.timestamp ());
605+ VarManager::SetCalibrationObject (VarManager::kTPCElectronMean , calibList->FindObject (" mean_map_electron" ));
606+ VarManager::SetCalibrationObject (VarManager::kTPCElectronSigma , calibList->FindObject (" sigma_map_electron" ));
607+ VarManager::SetCalibrationObject (VarManager::kTPCPionMean , calibList->FindObject (" mean_map_pion" ));
608+ VarManager::SetCalibrationObject (VarManager::kTPCPionSigma , calibList->FindObject (" sigma_map_pion" ));
609+ VarManager::SetCalibrationObject (VarManager::kTPCProtonMean , calibList->FindObject (" mean_map_proton" ));
610+ VarManager::SetCalibrationObject (VarManager::kTPCProtonSigma , calibList->FindObject (" sigma_map_proton" ));
611+ }
612+ fCurrentRun = bc.runNumber ();
613+ }
614+
615+ auto groupedTracksAssoc = trackAssocs.sliceBy (trackIndicesPerCollision, collision.globalIndex ());
616+ runTrackSelection<true , TrackFillMap>(groupedTracksAssoc, collision);
617+ runDalitzPairing<true , pairType, TrackFillMap>(groupedTracksAssoc, groupedTracksAssoc, collision);
461618 }
462619 }
463620
464621 for (const auto & track : tracks) { // Fill dalitz bits
465622 dalitzbits (fIsTagAndProbe ? fDalitzmapProbe [track.globalIndex ()] : fDalitzmap [track.globalIndex ()]);
466623 }
624+
467625 }
468626
469- void processDummy (MyEvents const &)
627+ void processDummy (MyEventsWithCent const &)
470628 {
471629 }
472630
631+ PROCESS_SWITCH (DalitzSelection, processFullTracksWithAssoc, " Run Dalitz selection on AO2D tables with reassociation" , false );
473632 PROCESS_SWITCH (DalitzSelection, processFullTracks, " Run Dalitz selection on AO2D tables" , false );
474633 PROCESS_SWITCH (DalitzSelection, processDummy, " Do nothing" , false );
475634};
0 commit comments