Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PWGHF/D2H/Tasks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2019-2020 CERN and copyright holders of ALICE O2.

Check failure on line 1 in PWGHF/D2H/Tasks/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Use kebab-case for names of workflows and match the name of the workflow file.
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
# All rights not expressly granted are reserved.
#
Expand Down Expand Up @@ -106,7 +106,7 @@

o2physics_add_dpl_workflow(task-lc
SOURCES taskLc.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::EventFilteringUtils
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(task-lc-to-k0s-p
Expand All @@ -114,7 +114,7 @@
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(task-omegac0-to-omega-pi

Check failure on line 117 in PWGHF/D2H/Tasks/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name task-omegac0-to-omega-pi does not match its file name taskOmegac0ToOmegapi.cxx. (Matches taskOmegac0ToOmegaPi.cxx.)
SOURCES taskOmegac0ToOmegapi.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
COMPONENT_NAME Analysis)
Expand Down
102 changes: 99 additions & 3 deletions PWGHF/D2H/Tasks/taskLc.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/// \author Vít Kučera <vit.kucera@cern.ch>, CERN
/// \author Annalena Kalteyer <annalena.sophie.kalteyer@cern.ch>, GSI Darmstadt
/// \author Biao Zhang <biao.zhang@cern.ch>, Heidelberg University
/// \author Ran Tu <ran.tu@cern.ch>, Fudan University

#include "PWGHF/Core/CentralityEstimation.h"
#include "PWGHF/Core/DecayChannels.h"
Expand All @@ -30,6 +31,7 @@
#include "Common/DataModel/Centrality.h"
#include "Common/DataModel/EventSelection.h"

#include <CCDB/BasicCCDBManager.h>
#include <CommonConstants/PhysicsConstants.h>
#include <Framework/ASoA.h>
#include <Framework/AnalysisDataModel.h>
Expand All @@ -47,6 +49,7 @@
#include <array>
#include <cmath>
#include <numeric>
#include <string>
#include <vector> // std::vector

using namespace o2;
Expand All @@ -55,6 +58,13 @@ using namespace o2::framework;
using namespace o2::framework::expressions;
using namespace o2::hf_centrality;
using namespace o2::hf_occupancy;
using namespace o2::hf_evsel;

enum class GapType {
GapA = 0,
GapC = 1,
DoubleGap = 2,
};

/// Λc± → p± K∓ π± analysis task
struct HfTaskLc {
Expand All @@ -77,9 +87,15 @@ struct HfTaskLc {
MlClassNonPrompt,
NumberOfMlClasses
};
Configurable<std::string> ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"};
Configurable<std::string> ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"};
Configurable<std::string> ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"};

HfEventSelection hfEvSel; // event selection and monitoring

HfHelper hfHelper;
SliceCache cache;
Service<o2::ccdb::BasicCCDBManager> ccdb;

using Collisions = soa::Join<aod::Collisions, aod::EvSels>;
using CollisionsMc = soa::Join<aod::Collisions, aod::McCollisionLabels, aod::EvSels>;
Expand Down Expand Up @@ -205,13 +221,14 @@ struct HfTaskLc {
{"MC/generated/prompt/hPhiGenPrompt", "MC particles (matched, prompt);#it{#Phi};entries", {HistType::kTH1F, {{100, 0., 6.3}}}},
{"MC/generated/nonprompt/hPhiGenNonPrompt", "MC particles (matched, non-prompt);#it{#Phi};entries", {HistType::kTH1F, {{100, 0., 6.3}}}}}};

HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject};

void init(InitContext&)
{
std::array<bool, 12> doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M};
std::array<bool, 13> doprocess{doprocessDataStd, doprocessDataStdWithFT0C, doprocessDataStdWithFT0M, doprocessDataWithMl, doprocessDataWithMlWithFT0C, doprocessDataWithMlWithFT0M, doprocessMcStd, doprocessMcStdWithFT0C, doprocessMcStdWithFT0M, doprocessMcWithMl, doprocessMcWithMlWithFT0C, doprocessMcWithMlWithFT0M, doprocessDataWithMlWithUpc};
if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) {
LOGP(fatal, "no or more than one process function enabled! Please check your configuration!");
}

auto vbins = (std::vector<double>)binsPt;
/// mass candidate
registry.add("Data/hMassVsPtVsNPvContributors", "3-prong candidates;inv. mass (p K #pi) (GeV/#it{c}^{2}); p_{T}; Number of PV contributors", {HistType::kTH3F, {{600, 1.98, 2.58}, {vbins, "#it{p}_{T} (GeV/#it{c})"}, {5000, 0., 10000.}}});
Expand Down Expand Up @@ -312,6 +329,12 @@ struct HfTaskLc {
registry.add("MC/reconstructed/prompt/hDecLenErrSigPrompt", "3-prong candidates (matched, prompt);decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}});
registry.add("MC/reconstructed/nonprompt/hDecLenErrSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}});

qaRegistry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{2500, 0., 250}, {2500, 0., 250}}});
qaRegistry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{200, 0., 20}, {200, 0., 20}}});
qaRegistry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap side;Counts", {HistType::kTH1F, {{3, -0.5, 2.5}}});
qaRegistry.get<TH1>(HIST("Data/hUpcGapAfterSelection"))->GetXaxis()->SetBinLabel(static_cast<int>(GapType::GapA) + 1, "A");
qaRegistry.get<TH1>(HIST("Data/hUpcGapAfterSelection"))->GetXaxis()->SetBinLabel(static_cast<int>(GapType::GapC) + 1, "C");
qaRegistry.get<TH1>(HIST("Data/hUpcGapAfterSelection"))->GetXaxis()->SetBinLabel(static_cast<int>(GapType::DoubleGap) + 1, "Double");
if (fillTHn) {
const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (p K #pi) (GeV/#it{c}^{2})"};
const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})"};
Expand All @@ -332,7 +355,7 @@ struct HfTaskLc {
const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, "Occupancy"};
const AxisSpec thnAxisProperLifetime{thnConfigAxisProperLifetime, "T_{proper} (ps)"};

bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M;
bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M || doprocessDataWithMlWithUpc;
bool const isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M;
bool const isDataStd = doprocessDataStd || doprocessDataStdWithFT0C || doprocessDataStdWithFT0M;
bool const isMcStd = doprocessMcStd || doprocessMcStdWithFT0C || doprocessMcStdWithFT0M;
Expand Down Expand Up @@ -382,6 +405,12 @@ struct HfTaskLc {
registry.add("hnLcVarsGen", "THn for Generated Lambdac", HistType::kTHnSparseF, axesGen);
}
}

hfEvSel.addHistograms(qaRegistry); // collision monitoring

ccdb->setURL(ccdbUrl);
ccdb->setCaching(true);
ccdb->setLocalObjectValidityChecking();
}

/// Evaluate centrality/multiplicity percentile (centrality estimator is automatically selected based on the used table)
Expand Down Expand Up @@ -859,6 +888,60 @@ struct HfTaskLc {
}
}

template <bool fillMl, typename CollType, typename CandType, typename BCsType>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you call this function only once, with fillMl = true, why do you need this parameter? Or do you foresee in future cases when this function should be called with false?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @lubynets, indeed, maybe we can consider adding one process function without ML in the future

void runAnalysisPerCollisionDataWithUpc(CollType const& collisions,
CandType const& candidates,
BCsType const& bcs,
aod::FT0s const& ft0s,
aod::FV0As const& fv0as,
aod::FDDs const& fdds

)
{

for (const auto& collision : collisions) {

uint32_t rejectionMask{0}; // 32 bits, in case new ev. selections will be added
float centrality{-1.f};
rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc<true, CentralityEstimator::None, BCsType>(collision, centrality, ccdb, qaRegistry, bcs);
Comment on lines +904 to +906
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not hard-code the types of values that you receive from functions. I removed these cases from HF some time ago. Where did you take this piece from?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rrantu, could you open a new PR to fix the comment from @vkucera and @lubynets? Thanks a lot!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed that point. I’ll update the code accordingly and submit a new PR.

if (rejectionMask != 0) {
/// at least one event selection not satisfied --> reject the candidate
continue;
}
auto bc = collision.template bc_as<BCsType>();
upchelpers::FITInfo fitInfo{};
udhelpers::getFITinfo(fitInfo, bc, bcs, ft0s, fv0as, fdds);

GapType gap = GapType::DoubleGap;
if (bc.has_zdc()) {
auto zdc = bc.zdc();
qaRegistry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C);
qaRegistry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdc.energyCommonZNA(), zdc.energyCommonZNC());
gap = determineGapType(fitInfo.ampFT0A, fitInfo.ampFT0C, zdc.energyCommonZNA(), zdc.energyCommonZNC());
qaRegistry.fill(HIST("Data/hUpcGapAfterSelection"), static_cast<int>(gap));
}
if (gap == GapType::GapA || gap == GapType::GapC) {
fillHistosData<fillMl>(collision, candidates);
} else {
continue;
}
}
}

GapType determineGapType(float FT0A, float FT0C, float ZNA, float ZNC)
{
constexpr float FT0AThreshold = 100.0;
constexpr float FT0CThreshold = 50.0;
constexpr float ZDCThreshold = 1.0;
if (FT0A < FT0AThreshold && FT0C > FT0CThreshold && ZNA < ZDCThreshold && ZNC > ZDCThreshold) {
return GapType::GapA;
}
if (FT0A > FT0AThreshold && FT0C < FT0CThreshold && ZNA > ZDCThreshold && ZNC < ZDCThreshold) {
return GapType::GapC;
}
return GapType::DoubleGap;
}
Comment on lines +931 to +943
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this supposed to be done by the SG selector?

Copy link
Collaborator

@zhangbiao-phy zhangbiao-phy Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @vkucera, yes, similar logic in the trueGap:

int trueGap(CC const& collision, const float fv0, const float ft0a, const float ft0c, const float zdc_cut)

But we can't use the UD collision table. So we define the function in our HF task now


/// Run the analysis on MC data
/// \tparam fillMl switch to fill ML histograms
template <bool FillMl, typename CollType, typename CandType, typename CandLcMcGen>
Expand Down Expand Up @@ -922,6 +1005,19 @@ struct HfTaskLc {
}
PROCESS_SWITCH(HfTaskLc, processDataWithMlWithFT0M, "Process real data with the ML method and with FT0M centrality", false);

void processDataWithMlWithUpc(soa::Join<aod::Collisions, aod::EvSels> const& collisions,
aod::BcFullInfos const& bcs,
LcCandidatesMl const& selectedLcCandidatesMl,
aod::Tracks const&,
aod::FT0s const& ft0s,
aod::FV0As const& fv0as,
aod::FDDs const& fdds,
aod::Zdcs const& /*zdcs*/)
{
runAnalysisPerCollisionDataWithUpc<true>(collisions, selectedLcCandidatesMl, bcs, ft0s, fv0as, fdds);
}
PROCESS_SWITCH(HfTaskLc, processDataWithMlWithUpc, "Process real data with the ML method with UPC", false);

void processMcStd(CollisionsMc const& collisions,
LcCandidatesMc const& selectedLcCandidatesMc,
McParticles3ProngMatched const& mcParticles,
Expand Down
Loading