-
Notifications
You must be signed in to change notification settings - Fork 613
[PWGHF] Add UPC process function and QA hists #13328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -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" | ||||
|
|
@@ -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> | ||||
|
|
@@ -47,6 +49,7 @@ | |||
| #include <array> | ||||
| #include <cmath> | ||||
| #include <numeric> | ||||
| #include <string> | ||||
| #include <vector> // std::vector | ||||
|
|
||||
| using namespace o2; | ||||
|
|
@@ -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 { | ||||
|
|
@@ -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>; | ||||
|
|
@@ -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.}}}); | ||||
|
|
@@ -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})"}; | ||||
|
|
@@ -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; | ||||
|
|
@@ -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) | ||||
|
|
@@ -859,6 +888,60 @@ struct HfTaskLc { | |||
| } | ||||
| } | ||||
|
|
||||
| template <bool fillMl, typename CollType, typename CandType, typename BCsType> | ||||
| 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
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this supposed to be done by the SG selector?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @vkucera, yes, similar logic in the trueGap: O2Physics/PWGUD/Core/SGSelector.h Line 141 in 41d60bb
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> | ||||
|
|
@@ -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, | ||||
|
|
||||
There was a problem hiding this comment.
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?There was a problem hiding this comment.
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