Skip to content
448 changes: 448 additions & 0 deletions PWGCF/Femto/Core/charmHadronBuilder.h

Large diffs are not rendered by default.

495 changes: 495 additions & 0 deletions PWGCF/Femto/Core/charmHadronHistManager.h

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions PWGCF/Femto/Core/closePairRejection.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct ConfCpr : o2::framework::ConfigurableGroup {

constexpr const char PrefixCprTrackTrack[] = "CprTrackTrack";
constexpr const char PrefixCprTrackV0Daughter[] = "CprTrackV0Daughter";
constexpr const char PrefixCprTrackD0Daughter[] = "CprTrackD0Daughter";
constexpr const char PrefixCprTrackResonanceDaughter[] = "CprTrackResonanceDaughter";
constexpr const char PrefixCprTrackKinkDaughter[] = "CprTrackKinkDaughter";
constexpr const char PrefixCprV0DaughterV0DaughterPos[] = "CprV0DaughterV0DaughterPos";
Expand All @@ -94,6 +95,7 @@ constexpr const char PrefixCprTrackCascadeBachelor[] = "CprTrackCascadeBachelor"
// pairs
using ConfCprTrackTrack = ConfCpr<PrefixCprTrackTrack>;
using ConfCprTrackV0Daughter = ConfCpr<PrefixCprTrackV0Daughter>;
using ConfCprTrackD0Daughter = ConfCpr<PrefixCprTrackD0Daughter>;
using ConfCprTrackResonanceDaughter = ConfCpr<PrefixCprTrackResonanceDaughter>;
using ConfCprTrackKinkDaughter = ConfCpr<PrefixCprTrackKinkDaughter>;
using ConfCprV0DaugherV0DaughterPos = ConfCpr<PrefixCprV0DaughterV0DaughterPos>;
Expand All @@ -111,6 +113,8 @@ constexpr char PrefixTrackTrackSe[] = "CPR_TrackTrack/SE/";
constexpr char PrefixTrackTrackMe[] = "CPR_TrackTrack/ME/";
constexpr char PrefixTrackV0DaughterSe[] = "CPR_TrackV0Dau/SE/";
constexpr char PrefixTrackV0DaughterMe[] = "CPR_TrackV0Dau/ME/";
constexpr char PrefixTrackD0DaughterSe[] = "CPR_TrackD0Dau/SE/";
constexpr char PrefixTrackD0DaughterMe[] = "CPR_TrackD0Dau/ME/";
constexpr char PrefixV0V0PosSe[] = "CPR_V0V0_PosDau/SE/";
constexpr char PrefixV0V0NegSe[] = "CPR_V0V0_NegDau/SE/";
constexpr char PrefixV0V0PosMe[] = "CPR_V0V0_PosDau/ME/";
Expand Down
4 changes: 4 additions & 0 deletions PWGCF/Femto/Core/dataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ using ParticleType = uint16_t;
using MomentumType = uint16_t;
using TransverseMassType = uint16_t;

// datatype for charm hadrons
using CharmHadronMaskType = uint32_t;
using CharmHadronType = uint16_t;

} // namespace o2::analysis::femto::datatypes

#endif // PWGCF_FEMTO_CORE_DATATYPES_H_
3 changes: 3 additions & 0 deletions PWGCF/Femto/Core/femtoUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ inline double getPdgMass(int pdgCode)
case o2::constants::physics::Pdg::kLambdaCPlus:
mass = o2::constants::physics::MassLambdaCPlus;
break;
case o2::constants::physics::Pdg::kD0:
mass = o2::constants::physics::MassD0;
break;
case o2::constants::physics::Pdg::kDeuteron:
mass = o2::constants::physics::MassDeuteron;
break;
Expand Down
71 changes: 69 additions & 2 deletions PWGCF/Femto/Core/mcBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
#include "PWGCF/Femto/Core/modes.h"
#include "PWGCF/Femto/DataModel/FemtoTables.h"

#include "Common/Core/RecoDecay.h"

#include <CommonConstants/MathConstants.h>
#include <CommonConstants/PhysicsConstants.h>
#include <Framework/AnalysisHelpers.h>
#include <Framework/Configurable.h>
#include <Framework/Logger.h>

#include <TPDGCode.h>

#include <array>
#include <cmath>
#include <cstdint>
#include <string>
Expand All @@ -44,6 +48,7 @@ struct ConfMc : o2::framework::ConfigurableGroup {
o2::framework::Configurable<bool> passThrough{"passThrough", false, "Passthrough all MC collisions and particles"};
o2::framework::Configurable<bool> findLastPartonicMother{"findLastPartonicMother", true, "If true, the partonic mother will be the first parton directly after the initial collision. If false, the partonic mother will be the last parton before hadronization"};
o2::framework::Configurable<float> etaAcceptanceMcOnly{"etaAcceptanceMcOnly", 0.8, "For MC ONLY processing. |eta| acceptance for estimating primary track multiplicity"};
o2::framework::Configurable<float> charmYGenMax{"charmYGenMax", 0.8f, "Max |y| (rapidity) for generated charm hadrons (mc-only truth acceptance)"};
};

struct McBuilderProducts : o2::framework::ProducesGroup {
Expand All @@ -57,6 +62,7 @@ struct McBuilderProducts : o2::framework::ProducesGroup {
o2::framework::Produces<o2::aod::FTrackLabels> producedTrackLabels;
o2::framework::Produces<o2::aod::FLambdaLabels> producedLambdaLabels;
o2::framework::Produces<o2::aod::FK0shortLabels> producedK0shortLabels;
o2::framework::Produces<o2::aod::FD0Labels> producedD0Labels;
o2::framework::Produces<o2::aod::FSigmaLabels> producedSigmaLabels;
o2::framework::Produces<o2::aod::FSigmaPlusLabels> producedSigmaPlusLabels;
o2::framework::Produces<o2::aod::FXiLabels> producedXiLabels;
Expand All @@ -75,6 +81,7 @@ struct ConfMcTables : o2::framework::ConfigurableGroup {
o2::framework::Configurable<int> producedTrackLabels{"producedTrackLabels", -1, "Produce track labels (-1: auto; 0 off; 1 on)"};
o2::framework::Configurable<int> producedLambdaLabels{"producedLambdaLabels", -1, "Produce lambda labels (-1: auto; 0 off; 1 on)"};
o2::framework::Configurable<int> producedK0shortLabels{"producedK0shortLabels", -1, "Produce k0short labels (-1: auto; 0 off; 1 on)"};
o2::framework::Configurable<int> producedD0Labels{"producedD0Labels", -1, "Produce D0 labels (-1: auto; 0 off; 1 on)"};
o2::framework::Configurable<int> producedSigmaLabels{"producedSigmaLabels", -1, "Produce k0short labels (-1: auto; 0 off; 1 on)"};
o2::framework::Configurable<int> producedSigmaPlusLabels{"producedSigmaPlusLabels", -1, "Produce k0short labels (-1: auto; 0 off; 1 on)"};
o2::framework::Configurable<int> producedXiLabels{"producedXiLabels", -1, "Produce xi labels (-1: auto; 0 off; 1 on)"};
Expand Down Expand Up @@ -134,6 +141,7 @@ class McBuilder
mProduceTrackLabels = utils::enableTable("FTrackLabels", table.producedTrackLabels.value, initContext);
mProduceLambdaLabels = utils::enableTable("FLambdaLabels", table.producedLambdaLabels.value, initContext);
mProduceK0shortLabels = utils::enableTable("FK0shortLabels", table.producedK0shortLabels.value, initContext);
mProduceD0Labels = utils::enableTable("FD0Labels", table.producedD0Labels.value, initContext);
mProduceSigmaLabels = utils::enableTable("FSigmaLabels", table.producedSigmaLabels.value, initContext);
mProduceSigmaPlusLabels = utils::enableTable("FSigmaPlusLabels", table.producedSigmaPlusLabels.value, initContext);
mProduceXiLabels = utils::enableTable("FXiLabels", table.producedXiLabels.value, initContext);
Expand All @@ -155,6 +163,7 @@ class McBuilder
mPassThrough = config.passThrough.value;
mEtaAcceptanceMcOnly = config.etaAcceptanceMcOnly.value;
mFindLastPartonicMother = config.findLastPartonicMother.value;
mCharmYGenMax = config.charmYGenMax.value;
LOG(info) << "Initialization done...";
}

Expand Down Expand Up @@ -229,6 +238,19 @@ class McBuilder
template <modes::System system, typename T1, typename T2, typename T3, typename T4>
void fillMcParticle(T1 const& mcParticle, T2 const& mcParticles, T3 const& mcCol, T4& 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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

// all other particles use the generic getOrigin inside getOrCreateMcParticleRow
if (std::abs(mcParticle.pdgCode()) == o2::constants::physics::Pdg::kD0) {
// truth-level acceptance for the efficiency denominator: keep only
// generated D0 -> K pi decays inside the rapidity acceptance
int8_t sign = 0;
if (!RecoDecay::isMatchedMCGen(mcParticles, mcParticle, o2::constants::physics::Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) {
return;
}
if (std::abs(mcParticle.y()) > mCharmYGenMax) {
return;
}
}
this->getOrCreateMcParticleRow<system>(mcParticle, mcParticles, mcCol, mcProducts);
}

Expand Down Expand Up @@ -262,6 +284,36 @@ class McBuilder
fillMcLabelGeneric<system>(col, mcCols, k0short, mcParticles, mcProducts, [](auto& prod, int64_t p) { prod.producedK0shortLabels(p); });
}

// D0 has no direct MC label (2-prong hypothesis built by PWGHF), so fillMcLabelGeneric
// cannot be reused. Both prongs are matched to a generated D0 -> K pi decay with
// RecoDecay::getMatchedMCRec, which returns the index of the generated mother;
// unmatched candidates get -1.
template <modes::System system, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
void fillMcD0WithLabel(T1 const& /*col*/, T2 const& /*mcCols*/, T3 const& d0candidate, T4 const& /*tracks*/, T5 const& mcParticles, T6& mcProducts)
{
if (!mProduceD0Labels) {
mcProducts.producedD0Labels(-1);
return;
}

auto prong0 = d0candidate.template prong0_as<T4>();
auto prong1 = d0candidate.template prong1_as<T4>();
auto arrayDaughters = std::array{prong0, prong1};
int8_t sign = 0;
const int indexMcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, o2::constants::physics::Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign);

if (indexMcRec < 0) {
mcProducts.producedD0Labels(-1);
return;
}

auto mcParticle = mcParticles.rawIteratorAt(indexMcRec);
auto mcCol = mcParticle.template mcCollision_as<T2>();
int64_t mcParticleRow = this->getOrCreateMcParticleRow<system>(mcParticle, mcParticles, mcCol, mcProducts);

mcProducts.producedD0Labels(mcParticleRow);
}

template <modes::System system, typename T1, typename T2, typename T3, typename T4, typename T5>
void fillMcSigmaWithLabel(T1 const& col, T2 const& mcCols, T3 const& sigmaDaughter, T4 const& mcParticles, T5& mcProducts)
{
Expand Down Expand Up @@ -331,6 +383,15 @@ class McBuilder
}

private:
// classify a charm hadron as prompt (charm from a c quark) or non-prompt (charm from a
// beauty decay) from the mc decay tree; shared by the reco-matched and generator-level paths
template <typename T1, typename T2>
modes::McOrigin getHeavyFlavourOrigin(T1 const& mcParticle, T2 const& mcParticles)
{
const int charmOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle);
return (charmOrigin == RecoDecay::OriginType::NonPrompt) ? modes::McOrigin::kNonPrompt : modes::McOrigin::kPrompt;
}

template <typename T1, typename T2, typename T3>
modes::McOrigin getOrigin(T1 const& col, T2 const& /*mcCols*/, T3 const& mcParticle)
{
Expand Down Expand Up @@ -389,7 +450,9 @@ class McBuilder
template <modes::System system, typename T1, typename T2, typename T3, typename T4>
int64_t getOrCreateMcParticleRow(T1 const& mcParticle, T2 const& mcParticles, T3 const& mcCol, T4& mcProducts)
{
auto origin = this->getOrigin(mcParticle);
auto origin = std::abs(mcParticle.pdgCode()) == o2::constants::physics::Pdg::kD0
? this->getHeavyFlavourOrigin(mcParticle, mcParticles)
: this->getOrigin(mcParticle);
return this->buildMcParticleRow<system>(mcParticle, mcParticles, mcCol, origin, mcProducts);
}

Expand All @@ -398,7 +461,9 @@ class McBuilder
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);
auto origin = std::abs(mcParticle.pdgCode()) == o2::constants::physics::Pdg::kD0
? this->getHeavyFlavourOrigin(mcParticle, mcParticles)
: this->getOrigin(col, mcCols, mcParticle);
return this->buildMcParticleRow<system>(mcParticle, mcParticles, mcCol, origin, mcProducts);
}

Expand Down Expand Up @@ -612,11 +677,13 @@ class McBuilder
bool mProduceTrackLabels = false;
bool mProduceLambdaLabels = false;
bool mProduceK0shortLabels = false;
bool mProduceD0Labels = false;
bool mProduceSigmaLabels = false;
bool mProduceSigmaPlusLabels = false;
bool mProduceXiLabels = false;
bool mProduceOmegaLabels = false;
bool mProduceMcMotherLabels = false;
float mCharmYGenMax = 0.8;

float mEtaAcceptanceMcOnly = 0.8;

Expand Down
19 changes: 17 additions & 2 deletions PWGCF/Femto/Core/modes.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ enum class Particle : o2::analysis::femto::datatypes::ParticleType {
kV0 = 3,
kKink = 4,
kCascade = 5,
kCharmHadron = 6,
};

enum class McOrigin : o2::analysis::femto::datatypes::McOriginType {
Expand All @@ -106,7 +107,9 @@ enum class McOrigin : o2::analysis::femto::datatypes::McOriginType {
kFromSecondaryDecay = 3, // particle from secondary decay
kFromMaterial = 4, // partilce orginates from material
kMissidentified = 5, // partilce was kMissidentified (also know as fake)
kMcOriginLast = 6
kPrompt = 6, // HF only: charm hadron produced promptly (from c quark)
kNonPrompt = 7, // HF only: charm hadron from beauty decay
kMcOriginLast = 8
// kFromFakeRecoCollision,
// kFromUnkown
};
Expand All @@ -126,6 +129,10 @@ constexpr const char* mcOriginToString(McOrigin origin)
return "FromMaterial";
case McOrigin::kMissidentified:
return "Missidentified";
case McOrigin::kPrompt:
return "Prompt";
case McOrigin::kNonPrompt:
return "NonPrompt";
default:
return "UnknownMcOrigin";
}
Expand All @@ -136,7 +143,8 @@ enum class Track : o2::analysis::femto::datatypes::TrackType {
kV0Daughter,
kCascadeBachelor,
kResonanceDaughter,
kKinkDaughter
kKinkDaughter,
kCharmDaughter
};

enum class V0 : o2::analysis::femto::datatypes::V0Type {
Expand All @@ -163,5 +171,12 @@ enum class TwoTrackResonance : o2::analysis::femto::datatypes::TwoTrackResonance
kKstar0Bar
};

enum class CharmHadron : o2::analysis::femto::datatypes::CharmHadronType {
kD0,
kD0Bar,
kDplus,
kLc
};

}; // namespace o2::analysis::femto::modes
#endif // PWGCF_FEMTO_CORE_MODES_H_
Loading
Loading