Skip to content

[PWGCF] Femto: Add D0 meson support to the femto framework - #17253

Open
IgorPtak wants to merge 8 commits into
AliceO2Group:masterfrom
IgorPtak:charm-hadrons
Open

[PWGCF] Femto: Add D0 meson support to the femto framework#17253
IgorPtak wants to merge 8 commits into
AliceO2Group:masterfrom
IgorPtak:charm-hadrons

Conversation

@IgorPtak

Copy link
Copy Markdown
Contributor

Adds D0 mesons as a new particle species to the unified femto framework, enabling D0-hadron femtoscopic correlations.

What is added

Data model - three new tables:

  • FD0s - kinematics, mass of the accepted hypothesis and daughter indices
  • FD0Masks - selection bitmask
  • FD0Extras - QA/debug: both mass hypotheses, topological variables, BDT scores and the PWGHF selection flags
  • FD0Labels - MC labels

Core: charmHadronBuilder.h and charmHadronHistManager.h, following the structure of the existing V0/cascade builders. D0 candidates are taken from PWGHF (HfCand2Prong), with the acceptance applied as a rapidity cut via HfHelper. The D0/D0bar hypothesis is encoded in the sign of the stored signed pT.

Tasks: two new workflows:

  • femto-d0-qa - QA for D0 candidates and their daughters
  • femto-pair-track-d0 - D0-hadron correlations, same and mixed event

MC: D0 candidates have no direct MC label, so both prongs are matched to a generated D0 -> K pi decay with RecoDecay::getMatchedMCRec. Charm hadrons are additionally classified as prompt or non-prompt, which required extending the McOrigin enum.

@github-actions

Copy link
Copy Markdown

O2 linter results: ❌ 0 errors, ⚠️ 0 warnings, 🔕 0 disabled

@alibuild

Copy link
Copy Markdown
Collaborator

Error while checking build/O2Physics/code-check for e6b7555 at 2026-07-29 19:46:

## sw/BUILD/O2Physics-code-check-latest/log
--
========== List of issues found ==========
++ echo 'Found 9 errors and 2 warnings.'
Found 9 errors and 2 warnings.
++ [[ 9 -gt 0 ]]
++ cat /sw/BUILD/0f9cdfd2185751249e7c2c145bfdaaf9ce837c70/O2Physics-code-check/errors.txt
PWGCF/Femto/Core/charmHadronBuilder.h:25:1: error: included header CandidateReconstructionTables.h is not used directly [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/charmHadronBuilder.h:67:36: error: no header providing "std::vector" is directly included [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/charmHadronBuilder.h:166:92: error: no header providing "o2::analysis::femto::limits::kLowerLimit" is directly included [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/charmHadronBuilder.h:168:149: error: no header providing "o2::analysis::femto::limits::kUpperLimit" is directly included [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/charmHadronBuilder.h:169:119: error: no header providing "o2::analysis::femto::limits::kAbsUpperLimit" is directly included [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/charmHadronBuilder.h:318:49: error: no header providing "int64_t" is directly included [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/charmHadronBuilder.h:348:21: error: no header providing "int8_t" is directly included [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/charmHadronHistManager.h:34:1: error: included header cstddef is not used directly [misc-include-cleaner,-warnings-as-errors]
PWGCF/Femto/Core/mcBuilder.h:246:102: error: no header providing "std::array" is directly included [misc-include-cleaner,-warnings-as-errors]
++ [[ 2 -gt 0 ]]
++ cat /sw/BUILD/0f9cdfd2185751249e7c2c145bfdaaf9ce837c70/O2Physics-code-check/warnings.txt
PWGCF/Femto/TableProducer/femtoProducer.cxx:389:71: warning: statement should be inside braces [readability-braces-around-statements]
PWGCF/Femto/TableProducer/femtoProducer.cxx:403:73: warning: statement should be inside braces [readability-braces-around-statements]
++ [[ 9 -gt 0 ]]
++ exit 1
--

Full log here.

@alibuild

Copy link
Copy Markdown
Collaborator

Error while checking build/O2Physics/o2 for 06079ed at 2026-07-30 02:27:

## sw/BUILD/O2Physics-latest/log
c++: fatal error: Killed signal terminated program cc1plus
c++: fatal error: Killed signal terminated program cc1plus
ninja: build stopped: subcommand failed.

Full log here.

@alibuild

Copy link
Copy Markdown
Collaborator

Error while checking build/O2Physics/o2 for 250a654 at 2026-07-30 14:23:

## sw/BUILD/O2Physics-latest/log
c++: fatal error: Killed signal terminated program cc1plus
c++: fatal error: Killed signal terminated program cc1plus
c++: fatal error: Killed signal terminated program cc1plus
ninja: build stopped: subcommand failed.

Full log here.

using Run3RecoVzeros = o2::soa::Join<o2::aod::V0Datas, o2::aod::McV0Labels>;

using Run3D0Candidates = soa::Join<aod::HfCand2Prong, aod::HfSelD0, aod::HfMlD0>;
using Run3McD0Candidates = soa::Join<aod::HfCand2Prong, aod::HfSelD0, aod::HfMlD0, aod::HfCand2ProngMcRec>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

can be made simpler

using Run3McD0Candidates = soa::Join<Run3D0Candidates, aod::HfCand2ProngMcRec>;

constexpr const char PrefixV01NegDauBinning[] = "V01NegDauBinning";
constexpr const char PrefixV02PosDauBinning[] = "V02PosDauBinning";
constexpr const char PrefixV02NegDauBinning[] = "V02NegDauBinning";
constexpr const char PrefixD0PosDauBinning[] = "D0PosDauBinning";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In case there will be a D0-D0 correlation task or similar, it would be good start enumerating them already
Can you rename prefixes like this

constexpr const char PrefixD01PosDauBinning[] = "D01PosDauBinning";

Similar to how it is also done for the V0s now

using ConfV01NegDauBinning = ConfTrackBinning<PrefixV01NegDauBinning>;
using ConfV02PosDauBinning = ConfTrackBinning<PrefixV02PosDauBinning>;
using ConfV02NegDauBinning = ConfTrackBinning<PrefixV02NegDauBinning>;
using ConfD0PosDauBinning = ConfTrackBinning<PrefixD0PosDauBinning>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same comment, please renmae D0->D01

constexpr const char PrefixV01NegDauQaBinning[] = "V01NegDauQaBinning";
constexpr const char PrefixV02PosDauQaBinning[] = "V02PosDauQaBinning";
constexpr const char PrefixV02NegDauQaBinning[] = "V02NegDauQaBinning";
constexpr const char PrefixD0PosDauQaBinning[] = "D0PosDauQaBinning";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same comment, please renmae D0->D01

using ConfV01NegDauQaBinning = ConfTrackQaBinning<PrefixV01NegDauQaBinning>;
using ConfV02PosDauQaBinning = ConfTrackQaBinning<PrefixV02PosDauQaBinning>;
using ConfV02NegDauQaBinning = ConfTrackQaBinning<PrefixV02NegDauQaBinning>;
using ConfD0PosDauQaBinning = ConfTrackQaBinning<PrefixD0PosDauQaBinning>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same comment, please renmae D0->D01

continue;
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

so in summary, all prefilters should be in checkFilters function, so here you can just call

if checkFilter() ...
applySelections()
if passesMinimalSelection() ...

Fill tables

auto prong0 = candidate.template prong0_as<T7>();
auto prong1 = candidate.template prong1_as<T7>();
int64_t posDauIndex = trackBuilder.template getDaughterIndex<modes::Track::kCharmDaughter>(prong0, trackProducts, collisionBuilder);
int64_t negDauIndex = trackBuilder.template getDaughterIndex<modes::Track::kCharmDaughter>(prong1, trackProducts, collisionBuilder);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It is better style to decalre the indices outside of the loop

continue;
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same comments as the function for data

void fillMcParticle(T1 const& mcParticle, T2 const& mcParticles, T3 const& mcCol, T4& mcProducts)
{
this->getOrCreateMcParticleRow<system>(mcParticle, mcParticles, mcCol, mcProducts);
// charm hadrons get a prompt/non-prompt origin, consistent with the reco-matched path;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it would more elegant to have this resolved in here

  template <modes::System system, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
  int64_t getOrCreateMcParticleRow(T1 const& col, T2 const& mcCols, T3 const& mcParticle, T4 const& mcParticles, T5 const& mcCol, T6& mcProducts)
  {
    auto origin = this->getOrigin(col, mcCols, mcParticle);
    return this->buildMcParticleRow<system>(mcParticle, mcParticles, mcCol, origin, mcProducts);
  }

here you add the check for the PID and then call a custom getHeavyFlavourOrigin function and set the correct origin for the D meson, the the new function overlaod can be avoided

return this->buildMcParticleRow<system>(mcParticle, mcParticles, mcCol, origin, mcProducts);
}

/// \brief Overload for a caller-provided origin, e.g. prompt vs non-prompt for a charm

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

see comment above, I think this overload is not needed

@ariedel-cern

Copy link
Copy Markdown
Collaborator

Hi @IgorPtak ,
many thanks for all this work! I left some comments that should improve the code a bit here and there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants