@@ -1350,6 +1350,223 @@ struct AnalysisPrefilterSelection {
13501350 PROCESS_SWITCH (AnalysisPrefilterSelection, processDummy, " Do nothing" , true );
13511351};
13521352
1353+ // Single-track selection on the barrel tracks after the prefilter decisions (which are not visible in the
1354+ // AnalysisTrackSelection histograms): fills track-level histograms separately for surviving and vetoed tracks,
1355+ // per track cut and per MC signal.
1356+ // NOTE: Histograms are filled per association, regardless of whether the association is the correct one.
1357+ struct AnalysisPostPrefilterTrackSelection {
1358+ OutputObj<THashList> fOutputList {" output" };
1359+
1360+ Configurable<std::string> fConfigTrackCuts {" cfgTrackCuts" , " " , " Comma separated list of track cuts (among those of analysis-track-selection) for which to fill histograms" };
1361+ Configurable<std::string> fConfigAddTrackHistogram {" cfgAddTrackHistogram" , " " , " Comma separated list of histograms" };
1362+ Configurable<std::string> fConfigAddJSONHistograms {" cfgAddJSONHistograms" , " " , " Histograms in JSON format" };
1363+ Configurable<std::string> fConfigMCSignals {" cfgTrackMCSignals" , " " , " Comma separated list of MC signals" };
1364+ Configurable<std::string> fConfigMCSignalsJSON {" cfgTrackMCsignalsJSON" , " " , " Additional list of MC signals via JSON" };
1365+ Configurable<std::string> fConfigCcdbUrl {" ccdb-url" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository" };
1366+ Configurable<std::string> grpmagPath{" grpmagPath" , " GLO/Config/GRPMagField" , " CCDB path of the GRPMagField object" };
1367+
1368+ Service<o2::ccdb::BasicCCDBManager> fCCDB {};
1369+
1370+ HistogramManager* fHistMan = nullptr ;
1371+ std::vector<MCSignal*> fMCSignals ;
1372+ std::vector<int > fCutBits ; // bit positions of the requested cuts in the track-selection task cut list
1373+ std::vector<TString> fHistNamesSurvived ; // [icut]
1374+ std::vector<TString> fHistNamesVetoed ; // [icut]
1375+ std::vector<TString> fHistNamesMCSurvived ; // [icut * nSignals + isig]
1376+ std::vector<TString> fHistNamesMCVetoed ; // [icut * nSignals + isig]
1377+
1378+ int fCurrentRun = 0 ; // current run (needed to detect run changes for loading CCDB parameters)
1379+
1380+ void init (o2::framework::InitContext& context)
1381+ {
1382+ if (context.mOptions .get <bool >(" processDummy" )) {
1383+ return ;
1384+ }
1385+ VarManager::SetDefaultVarNames ();
1386+
1387+ fCurrentRun = 0 ;
1388+ TString trackCutsStr = fConfigTrackCuts .value ;
1389+ std::unique_ptr<TObjArray> objArrayCuts (trackCutsStr.Tokenize (" ," ));
1390+ if (objArrayCuts == nullptr || objArrayCuts->GetEntries () == 0 ) {
1391+ LOG (fatal) << " No track cuts specified! Check the cfgTrackCuts configurable" ;
1392+ }
1393+ // get the full list of cuts computed by the track-selection task and resolve the requested cuts to bit positions
1394+ std::string trackCuts;
1395+ getTaskOptionValue<std::string>(context, " analysis-track-selection" , " cfgTrackCuts" , trackCuts, false );
1396+ TString allTrackCutsStr = trackCuts;
1397+ // check also the cuts added via JSON and add them to the string of cuts
1398+ getTaskOptionValue<std::string>(context, " analysis-track-selection" , " cfgBarrelTrackCutsJSON" , trackCuts, false );
1399+ TString addTrackCutsStr = trackCuts;
1400+ if (addTrackCutsStr != " " ) {
1401+ std::vector<AnalysisCut*> addTrackCuts = dqcuts::GetCutsFromJSON (addTrackCutsStr.Data ());
1402+ for (auto const & t : addTrackCuts) {
1403+ allTrackCutsStr += Form (" ,%s" , t->GetName ());
1404+ }
1405+ }
1406+ std::unique_ptr<TObjArray> objArrayAllCuts (allTrackCutsStr.Tokenize (" ," ));
1407+ if (objArrayAllCuts == nullptr ) {
1408+ LOG (fatal) << " Not getting any track cuts from the barrel-track-selection " ;
1409+ }
1410+ std::vector<TString> cutNames;
1411+ for (int icut = 0 ; icut < objArrayCuts->GetEntries (); ++icut) {
1412+ TString cutName = objArrayCuts->At (icut)->GetName ();
1413+ if (objArrayAllCuts->FindObject (cutName.Data ()) == nullptr ) {
1414+ LOG (fatal) << " Track cut " << cutName << " not among the cuts calculated by the track-selection task! " ;
1415+ }
1416+ for (int jcut = 0 ; jcut < objArrayAllCuts->GetEntries (); ++jcut) {
1417+ if (cutName.CompareTo (objArrayAllCuts->At (jcut)->GetName ()) == 0 ) {
1418+ fCutBits .push_back (jcut);
1419+ }
1420+ }
1421+ cutNames.push_back (cutName);
1422+ }
1423+
1424+ // Setting the MC signals
1425+ TString configSigNamesStr = fConfigMCSignals .value ;
1426+ std::unique_ptr<TObjArray> sigNamesArray (configSigNamesStr.Tokenize (" ," ));
1427+ for (int isig = 0 ; isig < sigNamesArray->GetEntries (); ++isig) {
1428+ MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal (sigNamesArray->At (isig)->GetName ());
1429+ if (sig) {
1430+ if (sig->GetNProngs () != 1 ) { // NOTE: only 1 prong signals
1431+ continue ;
1432+ }
1433+ fMCSignals .push_back (sig);
1434+ }
1435+ }
1436+ // Add the MCSignals from the JSON config
1437+ TString addMCSignalsStr = fConfigMCSignalsJSON .value ;
1438+ if (addMCSignalsStr != " " ) {
1439+ std::vector<MCSignal*> addMCSignals = dqmcsignals::GetMCSignalsFromJSON (addMCSignalsStr.Data ());
1440+ for (auto const & mcIt : addMCSignals) {
1441+ if (mcIt->GetNProngs () != 1 ) { // NOTE: only 1 prong signals
1442+ continue ;
1443+ }
1444+ fMCSignals .push_back (mcIt);
1445+ }
1446+ }
1447+
1448+ fHistMan = new HistogramManager (" analysisHistos" , " aa" , VarManager::kNVars );
1449+ fHistMan ->SetUseDefaultVariableNames (kTRUE );
1450+ fHistMan ->SetDefaultVarNames (dqefficiency_helpers::varNames (), dqefficiency_helpers::varUnits ());
1451+
1452+ // Configure histogram classes for each track cut, separately for prefilter-surviving and prefilter-vetoed tracks,
1453+ // and for each requested MC signal (reconstructed tracks with MC truth)
1454+ TString histClasses = " " ;
1455+ for (auto const & cutName : cutNames) {
1456+ TString nameStr = Form (" TrackBarrelPostPrefilter_%s" , cutName.Data ());
1457+ fHistNamesSurvived .push_back (nameStr);
1458+ histClasses += Form (" %s;" , nameStr.Data ());
1459+ nameStr = Form (" TrackBarrelPrefilterVetoed_%s" , cutName.Data ());
1460+ fHistNamesVetoed .push_back (nameStr);
1461+ histClasses += Form (" %s;" , nameStr.Data ());
1462+ for (auto const & sig : fMCSignals ) {
1463+ TString nameStr2 = Form (" TrackBarrelPostPrefilter_%s_%s" , cutName.Data (), sig->GetName ());
1464+ fHistNamesMCSurvived .push_back (nameStr2);
1465+ histClasses += Form (" %s;" , nameStr2.Data ());
1466+ nameStr2 = Form (" TrackBarrelPrefilterVetoed_%s_%s" , cutName.Data (), sig->GetName ());
1467+ fHistNamesMCVetoed .push_back (nameStr2);
1468+ histClasses += Form (" %s;" , nameStr2.Data ());
1469+ }
1470+ }
1471+
1472+ DefineHistograms (fHistMan , histClasses.Data (), fConfigAddTrackHistogram .value .data ());
1473+ dqhistograms::AddHistogramsFromJSON (fHistMan , fConfigAddJSONHistograms .value .c_str ()); // ad-hoc histograms via JSON
1474+ VarManager::SetUseVars (fHistMan ->GetUsedVars ()); // provide the list of required variables so that VarManager knows what to fill
1475+ fOutputList .setObject (fHistMan ->GetMainHistogramList ());
1476+
1477+ fCCDB ->setURL (fConfigCcdbUrl .value );
1478+ fCCDB ->setCaching (true );
1479+ fCCDB ->setLocalObjectValidityChecking ();
1480+ }
1481+
1482+ template <uint32_t TEventFillMap, uint32_t TTrackFillMap, typename TEvents, typename TTracks, typename TTracksMC>
1483+ void runPostPrefilterTrackSelection (soa::Join<aod::ReducedTracksAssoc, aod::BarrelTrackCuts, aod::Prefilter> const & assocs,
1484+ TEvents const & events, TTracks const & /* tracks*/ , TTracksMC const & tracksMC)
1485+ {
1486+ // load the magnetic field (needed to recompute the DCA with respect to the associated collision)
1487+ if (events.size () > 0 && fCurrentRun != events.begin ().runNumber ()) {
1488+ auto grpmag = fCCDB ->getForTimeStamp <o2::parameters::GRPMagField>(grpmagPath, events.begin ().timestamp ());
1489+ if (grpmag != nullptr ) {
1490+ VarManager::SetMagneticField (grpmag->getNominalL3Field ());
1491+ } else {
1492+ LOGF (fatal, " GRP object is not available in CCDB at timestamp=%llu" , events.begin ().timestamp ());
1493+ }
1494+ fCurrentRun = events.begin ().runNumber ();
1495+ }
1496+
1497+ // Loop over associations
1498+ for (auto const & assoc : assocs) {
1499+ auto event = assoc.template reducedevent_as <TEvents>();
1500+ if (!event.isEventSelected_bit (0 )) {
1501+ continue ;
1502+ }
1503+
1504+ // check which of the requested cuts are fulfilled by this association and which of those are prefilter-vetoed
1505+ uint32_t selectedMap = 0 ;
1506+ uint32_t vetoMap = 0 ;
1507+ for (std::size_t icut = 0 ; icut < fCutBits .size (); ++icut) {
1508+ if (assoc.isBarrelSelected_bit (fCutBits [icut])) {
1509+ selectedMap |= (static_cast <uint32_t >(1 ) << icut);
1510+ if (!assoc.isBarrelSelectedPrefilter_bit (fCutBits [icut])) {
1511+ vetoMap |= (static_cast <uint32_t >(1 ) << icut);
1512+ }
1513+ }
1514+ }
1515+ if (selectedMap == 0 ) {
1516+ continue ;
1517+ }
1518+
1519+ VarManager::ResetValues (0 , VarManager::kNBarrelTrackVariables );
1520+ // fill event information which might be needed in histograms that combine track and event properties
1521+ VarManager::FillEvent<TEventFillMap>(event);
1522+ if (event.has_reducedMCevent ()) {
1523+ VarManager::FillEvent<VarManager::ObjTypes::ReducedEventMC>(event.reducedMCevent ());
1524+ }
1525+
1526+ auto track = assoc.template reducedtrack_as <TTracks>();
1527+ VarManager::FillTrack<TTrackFillMap>(track);
1528+ // compute quantities which depend on the associated collision, such as DCA
1529+ VarManager::FillTrackCollision<TTrackFillMap>(track, event);
1530+ if (track.has_reducedMCTrack ()) {
1531+ VarManager::FillTrackMC (tracksMC, track.reducedMCTrack ());
1532+ }
1533+
1534+ for (std::size_t icut = 0 ; icut < fCutBits .size (); ++icut) {
1535+ if (!(selectedMap & (static_cast <uint32_t >(1 ) << icut))) {
1536+ continue ;
1537+ }
1538+ bool isVetoed = (vetoMap & (static_cast <uint32_t >(1 ) << icut)) > 0 ;
1539+ fHistMan ->FillHistClass ((isVetoed ? fHistNamesVetoed [icut] : fHistNamesSurvived [icut]).Data (), dqefficiency_helpers::varValues ());
1540+ if (track.has_reducedMCTrack ()) {
1541+ int isig = 0 ;
1542+ for (auto sig = fMCSignals .begin (); sig != fMCSignals .end (); sig++, isig++) {
1543+ if ((*sig)->CheckSignal (true , track.reducedMCTrack ())) {
1544+ fHistMan ->FillHistClass ((isVetoed ? fHistNamesMCVetoed : fHistNamesMCSurvived )[icut * fMCSignals .size () + isig].Data (), dqefficiency_helpers::varValues ());
1545+ }
1546+ }
1547+ }
1548+ } // end loop over cuts
1549+ } // end loop over associations
1550+ }
1551+
1552+ void processSkimmed (soa::Join<aod::ReducedTracksAssoc, aod::BarrelTrackCuts, aod::Prefilter> const & assocs, MyEventsSelected const & events, MyBarrelTracks const & tracks, ReducedMCEvents const & /* eventsMC*/ , ReducedMCTracks const & tracksMC)
1553+ {
1554+ runPostPrefilterTrackSelection<gkEventFillMap, gkTrackFillMap>(assocs, events, tracks, tracksMC);
1555+ }
1556+ void processSkimmedWithCov (soa::Join<aod::ReducedTracksAssoc, aod::BarrelTrackCuts, aod::Prefilter> const & assocs, MyEventsVtxCovSelected const & events, MyBarrelTracksWithCov const & tracks, ReducedMCEvents const & /* eventsMC*/ , ReducedMCTracks const & tracksMC)
1557+ {
1558+ runPostPrefilterTrackSelection<gkEventFillMapWithCov, gkTrackFillMapWithCov>(assocs, events, tracks, tracksMC);
1559+ }
1560+ void processDummy (MyEvents const &)
1561+ {
1562+ // do nothing
1563+ }
1564+
1565+ PROCESS_SWITCH (AnalysisPostPrefilterTrackSelection, processSkimmed, " Run barrel track post-prefilter selection on DQ skimmed track associations" , false );
1566+ PROCESS_SWITCH (AnalysisPostPrefilterTrackSelection, processSkimmedWithCov, " Run barrel track post-prefilter selection on DQ skimmed track associations w/ cov matrix" , false );
1567+ PROCESS_SWITCH (AnalysisPostPrefilterTrackSelection, processDummy, " Dummy function" , true );
1568+ };
1569+
13531570// Run the same-event pairing
13541571// This task assumes that both legs of the resonance fulfill the same cuts (symmetric decay channel)
13551572// Runs combinatorics for barrel-barrel, muon-muon and barrel-muon combinations
@@ -5183,6 +5400,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
51835400 adaptAnalysisTask<AnalysisTrackSelection>(cfgc),
51845401 adaptAnalysisTask<AnalysisMuonSelection>(cfgc),
51855402 adaptAnalysisTask<AnalysisPrefilterSelection>(cfgc),
5403+ adaptAnalysisTask<AnalysisPostPrefilterTrackSelection>(cfgc),
51865404 adaptAnalysisTask<AnalysisSameEventPairing>(cfgc),
51875405 adaptAnalysisTask<AnalysisAsymmetricPairing>(cfgc),
51885406 adaptAnalysisTask<AnalysisDileptonTrack>(cfgc)};
0 commit comments