1919// / \author Biao Zhang <[email protected] >, CCNU2020// / \author Federica Zanone <[email protected] >, Heidelberg University2121
22+ #include < array>
23+ #include < memory>
24+ #include < string>
25+ #include < vector>
26+
2227#include " TRandom3.h"
2328
2429#include " CommonConstants/PhysicsConstants.h"
2530#include " CCDB/BasicCCDBManager.h"
2631#include " DataFormatsParameters/GRPMagField.h"
2732#include " DataFormatsParameters/GRPObject.h"
33+ #include " DCAFitter/DCAFitterN.h"
2834#include " DetectorsBase/Propagator.h"
2935#include " Framework/AnalysisDataModel.h"
3036#include " Framework/AnalysisTask.h"
3137#include " Framework/ASoAHelpers.h"
3238#include " Framework/HistogramRegistry.h"
3339#include " Framework/runDataProcessing.h"
40+ #include " ReconstructionDataFormats/DCA.h"
3441
42+ #include " Common/Core/RecoDecay.h"
3543#include " Common/Core/trackUtilities.h"
3644#include " Common/DataModel/CollisionAssociationTables.h"
3745#include " Common/DataModel/EventSelection.h"
4149
4250#include " EventFiltering/filterTables.h"
4351#include " EventFiltering/PWGHF/HFFilterHelpers.h"
52+ #include " PWGHF/Utils/utilsTrkCandHf.h"
4453
4554using namespace o2 ;
4655using namespace o2 ::analysis;
@@ -59,6 +68,7 @@ struct HfFilter { // Main struct for HF triggers
5968 Configurable<int > activateQA{" activateQA" , 0 , " flag to enable QA histos (0 no QA, 1 basic QA, 2 extended QA, 3 very extended QA)" };
6069 Configurable<bool > applyEventSelection{" applyEventSelection" , true , " flag to enable event selection (sel8 + Zvt and possibly time-frame border cut)" };
6170 Configurable<bool > applyTimeFrameBorderCut{" applyTimeFrameBorderCut" , true , " flag to enable time-frame border cut" };
71+ Configurable<bool > activateSecVtx{" activateSecVtx" , false , " flag to enable 2nd vertex fitting - only beauty hadrons" };
6272
6373 // parameters for all triggers
6474 // nsigma PID (except for V0 and cascades)
@@ -76,6 +86,8 @@ struct HfFilter { // Main struct for HF triggers
7686 Configurable<LabeledArray<double >> cutsTrackBeauty4Prong{" cutsTrackBeauty4Prong" , {hf_cuts_single_track::cutsTrack[0 ], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, " Single-track selections per pT bin for 4-prong beauty candidates" };
7787 Configurable<std::string> paramCharmMassShape{" paramCharmMassShape" , " 2023_pass3" , " Parametrisation of charm-hadron mass shape (options: 2023_pass3)" };
7888 Configurable<float > numSigmaDeltaMassCharmHad{" numSigmaDeltaMassCharmHad" , 2.5 , " Number of sigma for charm-hadron delta mass cut in B and D resonance triggers" };
89+ Configurable<std::vector<double >> pTBinsBHadron{" pTBinsBHadron" , std::vector<double >{hf_trigger_cuts_presel_beauty::vecBinsPt}, " pT bin limits for beauty hadrons preselections" };
90+ Configurable<LabeledArray<double >> cutsBplus{" cutsBplus" , {hf_trigger_cuts_presel_beauty::cuts[0 ], hf_trigger_cuts_presel_beauty::nBinsPt, hf_trigger_cuts_presel_beauty::nCutVars, hf_trigger_cuts_presel_beauty::labelsPt, hf_trigger_cuts_presel_beauty::labelsRowsTopolBeauty}, " B+ candidate selection per pT bin" };
7991
8092 // parameters for femto triggers
8193 Configurable<float > femtoMaxRelativeMomentum{" femtoMaxRelativeMomentum" , 2 ., " Maximal allowed value for relative momentum between charm-proton pairs in GeV/c" };
@@ -135,6 +147,9 @@ struct HfFilter { // Main struct for HF triggers
135147 // array of BDT thresholds
136148 std::array<LabeledArray<double >, kNCharmParticles > thresholdBDTScores;
137149
150+ o2::vertexing::DCAFitterN<2 > df2; // fitter for Charm Hadron vertex (2-prong vertex fitter)
151+ o2::vertexing::DCAFitterN<2 > dfB; // fitter for Beauty Hadron vertex (2-prong vertex fitter)
152+
138153 HistogramRegistry registry{" registry" };
139154 std::shared_ptr<TH1> hProcessedEvents;
140155
@@ -151,6 +166,9 @@ struct HfFilter { // Main struct for HF triggers
151166 std::array<std::shared_ptr<TH2>, kNV0 > hArmPod{};
152167 std::shared_ptr<TH2> hV0Selected;
153168 std::shared_ptr<TH1> hMassXi;
169+ std::array<std::shared_ptr<TH2>, kNBeautyParticles > hCpaVsPtB{};
170+ std::array<std::shared_ptr<TH2>, kNBeautyParticles > hDecayLengthVsPtB{};
171+ std::array<std::shared_ptr<TH2>, kNBeautyParticles > hImpactParamProductVsPtB{};
154172
155173 // material correction for track propagation
156174 o2::base::MatLayerCylSet* lut;
@@ -164,12 +182,14 @@ struct HfFilter { // Main struct for HF triggers
164182 {
165183 helper.setHighPtTriggerThresholds (ptThresholds->get (0u , 0u ), ptThresholds->get (0u , 1u ));
166184 helper.setPtBinsSingleTracks (pTBinsTrack);
185+ helper.setPtBinsBeautyHadrons (pTBinsBHadron);
167186 helper.setPtLimitsBeautyBachelor (ptCuts->get (0u , 0u ), ptCuts->get (1u , 0u ));
168187 helper.setPtLimitsDstarSoftPion (ptCuts->get (0u , 1u ), ptCuts->get (1u , 1u ));
169188 helper.setPtLimitsProtonForFemto (ptCuts->get (0u , 2u ), ptCuts->get (1u , 2u ));
170189 helper.setPtLimitsCharmBaryonBachelor (ptCuts->get (0u , 3u ), ptCuts->get (1u , 3u ));
171190 helper.setCutsSingleTrackBeauty (cutsTrackBeauty3Prong, cutsTrackBeauty4Prong);
172191 helper.setCutsSingleTrackCharmBaryonBachelor (cutsTrackCharmBaryonBachelor);
192+ helper.setCutsBplus (cutsBplus);
173193 helper.setPtThresholdPidStrategyForFemto (ptThresholdForFemtoPid);
174194 helper.setNsigmaProtonCutsForFemto (std::array{nSigmaPidCuts->get (0u , 3u ), nSigmaPidCuts->get (1u , 3u ), nSigmaPidCuts->get (2u , 3u )});
175195 helper.setNsigmaProtonCutsForCharmBaryons (nSigmaPidCuts->get (0u , 0u ), nSigmaPidCuts->get (1u , 0u ));
@@ -184,7 +204,10 @@ struct HfFilter { // Main struct for HF triggers
184204 helper.setPtRangeSoftPiSigmaC (ptCuts->get (0u , 4u ), ptCuts->get (1u , 4u ));
185205 helper.setPtDeltaMassRangeSigmaC (cutsPtDeltaMassCharmReso->get (0u , 6u ), cutsPtDeltaMassCharmReso->get (1u , 6u ), cutsPtDeltaMassCharmReso->get (0u , 7u ), cutsPtDeltaMassCharmReso->get (1u , 7u ), cutsPtDeltaMassCharmReso->get (0u , 8u ), cutsPtDeltaMassCharmReso->get (1u , 8u ), cutsPtDeltaMassCharmReso->get (0u , 9u ), cutsPtDeltaMassCharmReso->get (1u , 9u ), cutsPtDeltaMassCharmReso->get (2u , 6u ), cutsPtDeltaMassCharmReso->get (2u , 7u ), cutsPtDeltaMassCharmReso->get (2u , 8u ), cutsPtDeltaMassCharmReso->get (2u , 9u ));
186206 helper.setPtRangeSoftKaonXicResoToSigmaC (ptCuts->get (0u , 5u ), ptCuts->get (1u , 5u ));
187-
207+ if (activateSecVtx) {
208+ helper.setVtxConfiguration (df2, false ); // (DCAFitterN, useAbsDCA)
209+ helper.setVtxConfiguration (dfB, true );
210+ }
188211 hProcessedEvents = registry.add <TH1>(" fProcessedEvents" , " HF - event filtered;;counts" , HistType::kTH1F , {{kNtriggersHF + 2 , -0.5 , +kNtriggersHF + 1.5 }});
189212 for (auto iBin = 0 ; iBin < kNtriggersHF + 2 ; ++iBin) {
190213 if (iBin < 2 )
@@ -230,7 +253,21 @@ struct HfFilter { // Main struct for HF triggers
230253
231254 for (int iBeautyPart{0 }; iBeautyPart < kNBeautyParticles ; ++iBeautyPart) {
232255 hMassVsPtB[iBeautyPart] = registry.add <TH2>(Form (" fMassVsPt%s" , beautyParticleNames[iBeautyPart].data ()), Form (" #it{M} vs. #it{p}_{T} distribution of triggered %s candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts" , beautyParticleNames[iBeautyPart].data ()), HistType::kTH2F , {ptAxis, massAxisB[iBeautyPart]});
256+ hCpaVsPtB[iBeautyPart] = registry.add <TH2>(Form (" fCpaVsPt%s" , beautyParticleNames[iBeautyPart].data ()), Form (" CPA vs. #it{p}_{T} distribution of triggered %s candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts" , beautyParticleNames[iBeautyPart].data ()), HistType::kTH2F , {ptAxis, {100 , -1 , 1 }});
257+ hDecayLengthVsPtB[iBeautyPart] = registry.add <TH2>(Form (" fDecayLengthVsPt%s" , beautyParticleNames[iBeautyPart].data ()), Form (" DecayLength vs. #it{p}_{T} distribution of triggered %s candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts" , beautyParticleNames[iBeautyPart].data ()), HistType::kTH2F , {ptAxis, {100 , 0 , 20 }});
258+ hImpactParamProductVsPtB[iBeautyPart] = registry.add <TH2>(Form (" fImpactParamProductVsPt%s" , beautyParticleNames[iBeautyPart].data ()), Form (" ImpactParamProduct vs. #it{p}_{T} distribution of triggered %s candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts" , beautyParticleNames[iBeautyPart].data ()), HistType::kTH2F , {ptAxis, {100 , -2.5 , +2.5 }});
259+ }
260+ constexpr int kNBinsHfVtxStages = kNHfVtxStage ;
261+ std::string labels[kNBinsHfVtxStages ];
262+ labels[HfVtxStage::Skimmed] = " Skimm CharmHad-Pi pairs" ;
263+ labels[HfVtxStage::BeautyVertex] = " vertex CharmHad-Pi pairs" ;
264+ labels[HfVtxStage::CharmHadPiSelected] = " selected CharmHad-Pi pairs" ;
265+ static const AxisSpec axisHfVtxStages = {kNBinsHfVtxStages , 0.5 , kNBinsHfVtxStages + 0.5 , " " };
266+ registry.add (" fHfVtxStages" , " HfVtxStages;;entries" , HistType::kTH1F , {axisHfVtxStages});
267+ for (int iBin = 0 ; iBin < kNBinsHfVtxStages ; iBin++) {
268+ registry.get <TH1>(HIST (" fHfVtxStages" ))->GetXaxis ()->SetBinLabel (iBin + 1 , labels[iBin].data ());
233269 }
270+
234271 for (int iV0{kPhoton }; iV0 < kNV0 ; ++iV0) {
235272 hArmPod[iV0] = registry.add <TH2>(Form (" fArmPod%s" , v0Names[iV0].data ()), Form (" Armenteros Podolanski plot for selected %s;#it{#alpha};#it{q}_{T} (GeV/#it{c})" , v0Labels[iV0].data ()), HistType::kTH2F , {alphaAxis, qtAxis});
236273 }
@@ -267,7 +304,7 @@ struct HfFilter { // Main struct for HF triggers
267304 }
268305
269306 using BigTracksMCPID = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::pidTPCFullPi, aod::pidTOFFullPi, aod::pidTPCFullKa, aod::pidTOFFullKa, aod::pidTPCFullPr, aod::pidTOFFullPr, aod::McTrackLabels>;
270- using BigTracksPID = soa::Join<aod::Tracks, aod::TracksExtra , aod::TracksDCA, aod::TrackSelection, aod::pidTPCFullPi, aod::pidTOFFullPi, aod::pidTPCFullKa, aod::pidTOFFullKa, aod::pidTPCFullPr, aod::pidTOFFullPr>;
307+ using BigTracksPID = soa::Join<aod::Tracks, aod::TracksWCovDcaExtra , aod::TracksDCA, aod::TrackSelection, aod::pidTPCFullPi, aod::pidTOFFullPi, aod::pidTPCFullKa, aod::pidTOFFullKa, aod::pidTPCFullPr, aod::pidTOFFullPr>;
271308 using CollsWithEvSel = soa::Join<aod::Collisions, aod::EvSels>;
272309
273310 using Hf2ProngsWithMl = soa::Join<aod::Hf2Prongs, aod::Hf2ProngMlProbs>;
@@ -342,8 +379,8 @@ struct HfFilter { // Main struct for HF triggers
342379 continue ;
343380 }
344381
345- auto trackParPos = getTrackPar (trackPos);
346- auto trackParNeg = getTrackPar (trackNeg);
382+ auto trackParPos = getTrackParCov (trackPos);
383+ auto trackParNeg = getTrackParCov (trackNeg);
347384 o2::gpu::gpustd::array<float , 2 > dcaPos{trackPos.dcaXY (), trackPos.dcaZ ()};
348385 o2::gpu::gpustd::array<float , 2 > dcaNeg{trackNeg.dcaXY (), trackNeg.dcaZ ()};
349386 std::array<float , 3 > pVecPos{trackPos.pVector ()};
@@ -418,7 +455,7 @@ struct HfFilter { // Main struct for HF triggers
418455 continue ;
419456 }
420457
421- auto trackParThird = getTrackPar (track);
458+ auto trackParThird = getTrackParCov (track);
422459 o2::gpu::gpustd::array<float , 2 > dcaThird{track.dcaXY (), track.dcaZ ()};
423460 std::array<float , 3 > pVecThird = track.pVector ();
424461 if (track.collisionId () != thisCollId) {
@@ -432,14 +469,52 @@ struct HfFilter { // Main struct for HF triggers
432469 auto massCand = RecoDecay::m (std::array{pVec2Prong, pVecThird}, std::array{massD0, massPi});
433470 auto pVecBeauty3Prong = RecoDecay::pVec (pVec2Prong, pVecThird);
434471 auto ptCand = RecoDecay::pt (pVecBeauty3Prong);
435- if (TESTBIT (isTrackSelected, kForBeauty ) && std::fabs (massCand - massBPlus) <= deltaMassBeauty->get (0u , 0u )) {
436- keepEvent[kBeauty3P ] = true ;
437- // fill optimisation tree for D0
438- if (applyOptimisation) {
439- optimisationTreeBeauty (thisCollId, o2::constants::physics::Pdg::kD0 , pt2Prong, scores[0 ], scores[1 ], scores[2 ], dcaThird[0 ]);
440- }
472+ if (TESTBIT (isTrackSelected, kForBeauty ) && helper.isSelectedBplusInMassRange (ptCand, massCand)) {
441473 if (activateQA) {
442- hMassVsPtB[kBplus ]->Fill (ptCand, massCand);
474+ registry.fill (HIST (" fHfVtxStages" ), 1 + HfVtxStage::Skimmed);
475+ }
476+ if (!activateSecVtx) {
477+ keepEvent[kBeauty3P ] = true ;
478+ // fill optimisation tree for D0
479+ if (applyOptimisation) {
480+ optimisationTreeBeauty (thisCollId, o2::constants::physics::Pdg::kD0 , pt2Prong, scores[0 ], scores[1 ], scores[2 ], dcaThird[0 ]);
481+ }
482+ if (activateQA) {
483+ hMassVsPtB[kBplus ]->Fill (ptCand, massCand);
484+ }
485+ } else {
486+ df2.process (trackParPos, trackParNeg);
487+ df2.getTrack (0 ).getPxPyPzGlo (pVecPos);
488+ df2.getTrack (1 ).getPxPyPzGlo (pVecNeg);
489+ auto trackParD = df2.createParentTrackParCov ();
490+ trackParD.setAbsCharge (0 ); // to be sure
491+ auto pVec2Prong = RecoDecay::pVec (pVecPos, pVecNeg);
492+ if (dfB.process (trackParD, trackParThird) != 0 ) {
493+ if (activateQA) {
494+ registry.fill (HIST (" fHfVtxStages" ), 1 + HfVtxStage::BeautyVertex);
495+ }
496+ const auto & secondaryVertexBplus = dfB.getPCACandidate ();
497+ dfB.propagateTracksToVertex ();
498+ dfB.getTrack (0 ).getPxPyPzGlo (pVec2Prong);
499+ dfB.getTrack (1 ).getPxPyPzGlo (pVecThird);
500+ o2::gpu::gpustd::array<float , 2 > dca2Prong; // {trackParD.dcaXY(), trackParD.dcaZ()};
501+ o2::base::Propagator::Instance ()->propagateToDCABxByBz ({collision.posX (), collision.posY (), collision.posZ ()}, trackParD, 2 .f , noMatCorr, &dca2Prong);
502+ bool isBplus = helper.isSelectedBplus (pVec2Prong, pVecThird, dca2Prong, dcaThird, std::array<double , 3 >{static_cast <double >(collision.posX ()), static_cast <double >(collision.posY ()), static_cast <double >(collision.posZ ())}, std::array{secondaryVertexBplus[0 ], secondaryVertexBplus[1 ], secondaryVertexBplus[2 ]});
503+ if (isBplus) {
504+ keepEvent[kBeauty3P ] = true ;
505+ // fill optimisation tree for D0
506+ if (applyOptimisation) {
507+ optimisationTreeBeauty (thisCollId, o2::constants::physics::Pdg::kD0 , pt2Prong, scores[0 ], scores[1 ], scores[2 ], dcaThird[0 ]);
508+ }
509+ if (activateQA) {
510+ registry.fill (HIST (" fHfVtxStages" ), 1 + HfVtxStage::CharmHadPiSelected);
511+ hCpaVsPtB[kBplus ]->Fill (RecoDecay::pt (RecoDecay::pVec (pVec2Prong, pVecThird)), RecoDecay::cpa (std::array<double , 3 >{static_cast <double >(collision.posX ()), static_cast <double >(collision.posY ()), static_cast <double >(collision.posZ ())}, std::array{secondaryVertexBplus[0 ], secondaryVertexBplus[1 ], secondaryVertexBplus[2 ]}, RecoDecay::pVec (pVec2Prong, pVecThird)));
512+ hDecayLengthVsPtB[kBplus ]->Fill (RecoDecay::pt (RecoDecay::pVec (pVec2Prong, pVecThird)), RecoDecay::distance (std::array<double , 3 >{static_cast <double >(collision.posX ()), static_cast <double >(collision.posY ()), static_cast <double >(collision.posZ ())}, std::array{secondaryVertexBplus[0 ], secondaryVertexBplus[1 ], secondaryVertexBplus[2 ]}));
513+ hImpactParamProductVsPtB[kBplus ]->Fill (RecoDecay::pt (RecoDecay::pVec (pVec2Prong, pVecThird)), dca2Prong[0 ] * dcaThird[0 ]);
514+ hMassVsPtB[kBplus ]->Fill (ptCand, massCand);
515+ }
516+ }
517+ }
443518 }
444519 }
445520 }
@@ -990,9 +1065,9 @@ struct HfFilter { // Main struct for HF triggers
9901065 }
9911066 }
9921067 } // end SigmaC++ candidate
993- } // end loop over tracks (soft pi)
994- } // end candidate Lc->pKpi
995- } // end loop over tracks
1068+ } // end loop over tracks (soft pi)
1069+ } // end candidate Lc->pKpi
1070+ } // end loop over tracks
9961071
9971072 // Ds with photon
9981073 bool isGoodDsToKKPi = (isSignalTagged[kDs - 1 ]) && TESTBIT (is3ProngInMass[kDs - 1 ], 0 );
0 commit comments