Skip to content
Merged
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
121 changes: 102 additions & 19 deletions PWGHF/Tasks/taskMcValidation.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,92 @@
o2::constants::physics::Pdg::kLambdaCPlus, o2::constants::physics::Pdg::kLambdaCPlus,
o2::constants::physics::Pdg::kXiCPlus, o2::constants::physics::Pdg::kXiCPlus, o2::constants::physics::Pdg::kXiC0,
o2::constants::physics::Pdg::kOmegaC0, o2::constants::physics::Pdg::kOmegaC0};
constexpr std::array<unsigned int, NChannels> NDaughters = {2, 3, 3, 3, 3, 3, 5, 5, 4, 4, 4, 3, 4, 3, 3, 3, 5, 4, 4, 4};
constexpr std::array<int, NChannels> MaxDepthForSearch = {1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 3, 2, 3, 2, 4, 3, 3, 3};
constexpr std::array<unsigned int, NChannels> NDaughters = {
2, // DzeroToKPi
3, // DstarToDzeroPi
3, // DplusToPiKPi
3, // DplusToPhiPiToKKPi
3, // DsToPhiPiToKKPi
3, // DsToK0starKToKKPi
5, // Ds1ToDStarK0s
5, // Ds2StarToDPlusK0s
4, // D10ToDStarPi
4, // D2Star0ToDPlusPi
4, // B0ToDminusPi
3, // BplusToD0Pi
4, // BsToDsPi
3, // LcToPKPi
3, // LcToPiK0s
3, // XiCplusToPKPi
5, // XiCplusToXiPiPi
4, // XiCzeroToXiPi
4, // OmegaCToOmegaPi
4 // OmegaCToXiPi
};
constexpr std::array<int, NChannels> MaxDepthForSearch = {
1, // DzeroToKPi
2, // DstarToDzeroPi
2, // DplusToPiKPi
2, // DplusToPhiPiToKKPi
2, // DsToPhiPiToKKPi
2, // DsToK0starKToKKPi
3, // Ds1ToDStarK0s
3, // Ds2StarToDPlusK0s
3, // D10ToDStarPi
3, // D2Star0ToDPlusPi
3, // B0ToDminusPi
2, // BplusToD0Pi
3, // BsToDsPi
2, // LcToPKPi
3, // LcToPiK0s
2, // XiCplusToPKPi
4, // XiCplusToXiPiPi
3, // XiCzeroToXiPi
3, // OmegaCToOmegaPi
3 // OmegaCToXiPi
};
// keep coherent indexing with PDGArrayParticle
// FIXME: look for a better solution
constexpr std::array<std::array<int, 2>, NChannels> ArrPdgFinal2Prong = {{{+kPiPlus, -kKPlus}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}};
constexpr std::array<std::array<int, 3>, NChannels> ArrPdgFinal3Prong = {{{}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {+kKPlus, -kKPlus, +kPiPlus}, {}, {}, {}, {}, {}, {-kPiPlus, +kKPlus, +kPiPlus}, {}, {+kProton, -kKPlus, +kPiPlus}, {+kProton, -kPiPlus, +kPiPlus}, {+kProton, -kKPlus, +kPiPlus}, {}, {}, {}, {}}};
constexpr std::array<std::array<int, 4>, NChannels> ArrPdgFinal4Prong = {{{}, {}, {}, {}, {}, {}, {}, {}, {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}, {-kPiPlus, +kKPlus, -kPiPlus, +kPiPlus}, {}, {-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, {}, {}, {}, {}, {+kPiPlus, -kPiPlus, -kPiPlus, +kProton}, {+kPiPlus, -kKPlus, -kPiPlus, +kProton}, {+kPiPlus, -kPiPlus, -kPiPlus, +kProton}}};
constexpr std::array<std::array<int, 5>, NChannels> ArrPdgFinal5Prong = {{{}, {}, {}, {}, {}, {}, {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, {}, {}, {}, {}, {}, {}, {}, {}, {+kPiPlus, +kPiPlus, -kPiPlus, -kPiPlus, +kProton}, {}, {}, {}}};
constexpr auto ArrPdgFinal2Prong = []() {
std::array<std::array<int, 2>, NChannels> arr{};
arr[DzeroToKPi] = {+kPiPlus, -kKPlus};
return arr;
}();

constexpr auto ArrPdgFinal3Prong = []() {
std::array<std::array<int, 3>, NChannels> arr{};
arr[DstarToDzeroPi] = {+kPiPlus, -kKPlus, +kPiPlus};
arr[DplusToPiKPi] = {+kPiPlus, -kKPlus, +kPiPlus};
arr[DplusToPhiPiToKKPi] = {+kKPlus, -kKPlus, +kPiPlus};
arr[DsToPhiPiToKKPi] = {+kKPlus, -kKPlus, +kPiPlus};
arr[DsToK0starKToKKPi] = {+kKPlus, -kKPlus, +kPiPlus};
arr[BplusToD0Pi] = {-kPiPlus, +kKPlus, +kPiPlus};
arr[LcToPKPi] = {+kProton, -kKPlus, +kPiPlus};
arr[LcToPiK0s] = {+kProton, -kPiPlus, +kPiPlus};
arr[XiCplusToPKPi] = {+kProton, -kKPlus, +kPiPlus};
return arr;
}();

constexpr auto ArrPdgFinal4Prong = []() {
std::array<std::array<int, 4>, NChannels> arr{};
arr[D10ToDStarPi] = {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus};
arr[D2Star0ToDPlusPi] = {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus};
arr[B0ToDminusPi] = {-kPiPlus, +kKPlus, -kPiPlus, +kPiPlus};
arr[BsToDsPi] = {-kKPlus, +kKPlus, -kPiPlus, +kPiPlus};
arr[XiCzeroToXiPi] = {+kPiPlus, -kPiPlus, -kPiPlus, +kProton};
arr[OmegaCToOmegaPi] = {+kPiPlus, -kKPlus, -kPiPlus, +kProton};
arr[OmegaCToXiPi] = {+kPiPlus, -kPiPlus, -kPiPlus, +kProton};
return arr;
}();

constexpr auto ArrPdgFinal5Prong = []() {
std::array<std::array<int, 5>, NChannels> arr{};
arr[Ds1ToDStarK0s] = {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus};
arr[Ds2StarToDPlusK0s] = {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus};
arr[XiCplusToXiPiPi] = {+kPiPlus, +kPiPlus, -kPiPlus, -kPiPlus, +kProton};
return arr;
}();

constexpr std::string_view Labels[NChannels] = {"D^{0} #rightarrow K#pi", "D*^{+} #rightarrow D^{0}#pi", "D^{+} #rightarrow K#pi#pi", "D^{+} #rightarrow KK#pi", "D_{s}^{+} #rightarrow #Phi#pi #rightarrow KK#pi",
"D_{s}^{+} #rightarrow #bar{K}^{*0}K #rightarrow KK#pi", "D_{s}1 #rightarrow D*^{+}K^{0}_{s}", "D_{s}2* #rightarrow D^{+}K^{0}_{s}", "D1^{0} #rightarrow D*^{+}#pi",
"D2^{*} #rightarrow D^{+}#pi",
Expand Down Expand Up @@ -219,7 +297,7 @@
}

// add per species histograms
for (auto originName : OriginNames) {

Check failure on line 300 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[const-ref-in-for-loop]

Use constant references for non-modified iterators in range-based for loops.
for (int iChannel = 0; iChannel < NCharmMesonChannels; iChannel++) { // Charm mesons
registry.add(Form("%sCharmMesons/hCount%s%s", originName.data(), originName.data(), ParticleNames[iChannel].data()),
Form("Event counter - %s %s; Events Per Collision; entries", originName.data(), Labels[iChannel].data()), {HistType::kTH1F, {axisNhadrons}});
Expand Down Expand Up @@ -279,7 +357,9 @@
}

template <o2::hf_centrality::CentralityEstimator CentEstimator, typename GenColl, typename Particles, typename RecoColls>
void runCheckGenParticles(GenColl const& mcCollision, Particles const& mcParticles, RecoColls const& recoCollisions, BCsInfo const&, std::array<int, NChannels>& counterPrompt, std::array<int, NChannels>& counterNonPrompt)
void runCheckGenParticles(
GenColl const& mcCollision, Particles const& mcParticles, RecoColls const& recoCollisions,
BCsInfo const&, std::array<int, NChannels>& counterPrompt, std::array<int, NChannels>& counterNonPrompt, std::array<int, NChannels>& counterBeauty)
{
if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) {
return;
Expand Down Expand Up @@ -354,13 +434,13 @@
std::vector<int> listDaughters{};

// Check that the decay channel is correct and retrieve the daughters
if (NDaughters[iD] == 2) {

Check failure on line 437 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
if (!RecoDecay::isMatchedMCGen(mcParticles, particle, PDGArrayParticle[iD], ArrPdgFinal2Prong[iD], true, nullptr, MaxDepthForSearch[iD], &listDaughters)) {
continue;
}
}

if (NDaughters[iD] == 3) {

Check failure on line 443 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
if (!RecoDecay::isMatchedMCGen<false, true>(mcParticles, particle, PDGArrayParticle[iD], ArrPdgFinal3Prong[iD], true, nullptr, MaxDepthForSearch[iD], &listDaughters)) {
continue;
}
Expand Down Expand Up @@ -388,7 +468,7 @@
}
}

if (NDaughters[iD] == 4) {

Check failure on line 471 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
if (iD != B0ToDminusPi) {
if (!RecoDecay::isMatchedMCGen<false, true>(mcParticles, particle, PDGArrayParticle[iD], ArrPdgFinal4Prong[iD], true, nullptr, MaxDepthForSearch[iD], &listDaughters)) {
continue;
Expand Down Expand Up @@ -424,7 +504,7 @@
}
}

if (NDaughters[iD] == 5) {

Check failure on line 507 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
if (!RecoDecay::isMatchedMCGen<false, true>(mcParticles, particle, PDGArrayParticle[iD], ArrPdgFinal5Prong[iD], true, nullptr, MaxDepthForSearch[iD], &listDaughters)) {
continue;
}
Expand All @@ -449,7 +529,7 @@
double sumPyDau = 0.;
double sumPzDau = 0.;
bool momentumCheck = true;
for (const int listDaughter : listDaughters) {

Check failure on line 532 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[const-ref-in-for-loop]

Use constant references for non-modified iterators in range-based for loops.
auto daughter = mcParticles.rawIteratorAt(listDaughter - mcParticles.offset());
sumPxDau += daughter.px();
sumPyDau += daughter.py();
Expand All @@ -458,7 +538,7 @@
auto pxDiff = particle.px() - sumPxDau;
auto pyDiff = particle.py() - sumPyDau;
auto pzDiff = particle.pz() - sumPzDau;
if (std::abs(pxDiff) > 0.001 || std::abs(pyDiff) > 0.001 || std::abs(pzDiff) > 0.001) {

Check failure on line 541 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
momentumCheck = false;
}
double const pDiff = RecoDecay::p(pxDiff, pyDiff, pzDiff);
Expand All @@ -478,6 +558,8 @@
} else if (origin == RecoDecay::OriginType::NonPrompt) {
counterNonPrompt[iD]++;
}
} else { // Beauty hadrons
counterBeauty[iD]++; // Matched already, no need to check origin for beauty hadrons
}

auto daughter0 = particle.template daughters_as<Particles>().begin();
Expand All @@ -486,7 +568,7 @@
auto decayLength = RecoDecay::distance(vertexPrimary, vertexDau);
if (iD < NCharmMesonChannels) {
if (origin == RecoDecay::OriginType::Prompt) { // Prompt charm mesons
if (std::abs(particle.y()) < 0.5) {

Check failure on line 571 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
registry.fill(HIST("PromptCharmMesons/hPromptMesonsPtDistr"), iD, particle.pt());
registry.fill(HIST("PromptCharmMesons/hPromptMesonsPtCentDistr"), iD, particle.pt(), centrality);
if (storeOccupancy) {
Expand All @@ -496,7 +578,7 @@
registry.fill(HIST("PromptCharmMesons/hPromptMesonsYDistr"), iD, particle.y());
registry.fill(HIST("PromptCharmMesons/hPromptMesonsDecLenDistr"), iD, decayLength * 10000);
} else if (origin == RecoDecay::OriginType::NonPrompt) {
if (std::abs(particle.y()) < 0.5) {

Check failure on line 581 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
registry.fill(HIST("NonPromptCharmMesons/hNonPromptMesonsPtDistr"), iD, particle.pt());
registry.fill(HIST("NonPromptCharmMesons/hNonPromptMesonsPtCentDistr"), iD, particle.pt(), centrality);
if (storeOccupancy) {
Expand All @@ -507,7 +589,7 @@
registry.fill(HIST("NonPromptCharmMesons/hNonPromptMesonsDecLenDistr"), iD, decayLength * 10000);
}
} else if (iD < NCharmMesonChannels + NBeautyChannels) { // Beauty mesons
if (std::abs(particle.y()) < 0.5) {

Check failure on line 592 in PWGHF/Tasks/taskMcValidation.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
registry.fill(HIST("Beauty/hPtDistr"), iD - NCharmMesonChannels, particle.pt());
registry.fill(HIST("Beauty/hPtCentDistr"), iD - NCharmMesonChannels, particle.pt(), centrality);
}
Expand Down Expand Up @@ -553,16 +635,16 @@
for (const auto& mcCollision : mcCollisions) {
const auto recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollision, mcCollision.globalIndex());
const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex());
std::array<int, NChannels> counterPrompt{0}, counterNonPrompt{0};
runCheckGenParticles<o2::hf_centrality::CentralityEstimator::None>(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt);
std::array<int, NChannels> counterPrompt{0}, counterNonPrompt{0}, counterBeauty{0};
runCheckGenParticles<o2::hf_centrality::CentralityEstimator::None>(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt, counterBeauty);
static_for<0, NCharmMesonChannels - 1>([&](auto i) { // Charm mesons
constexpr int Index = i.value;
registry.fill(HIST("PromptCharmMesons/hCountPrompt") + HIST(ParticleNames[Index]), counterPrompt[Index]);
registry.fill(HIST("NonPromptCharmMesons/hCountNonPrompt") + HIST(ParticleNames[Index]), counterNonPrompt[Index]);
});
static_for<NCharmMesonChannels, NCharmMesonChannels + NBeautyChannels - 1>([&](auto i) { // Beauty hadrons
constexpr int Index = i.value;
registry.fill(HIST("Beauty/hCount") + HIST(ParticleNames[Index]), counterPrompt[Index]);
registry.fill(HIST("Beauty/hCount") + HIST(ParticleNames[Index]), counterBeauty[Index]);
});
static_for<NCharmMesonChannels + NBeautyChannels, NChannels - 1>([&](auto i) { // Charm baryons
constexpr int Index = i.value;
Expand All @@ -581,16 +663,16 @@
for (const auto& mcCollision : mcCollisions) {
const auto recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex());
const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex());
std::array<int, NChannels> counterPrompt{0}, counterNonPrompt{0};
runCheckGenParticles<o2::hf_centrality::CentralityEstimator::FT0C>(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt);
std::array<int, NChannels> counterPrompt{0}, counterNonPrompt{0}, counterBeauty{0};
runCheckGenParticles<o2::hf_centrality::CentralityEstimator::FT0C>(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt, counterBeauty);
static_for<0, NCharmMesonChannels - 1>([&](auto i) { // Charm mesons
constexpr int Index = i.value;
registry.fill(HIST("PromptCharmMesons/hCountPrompt") + HIST(ParticleNames[Index]), counterPrompt[Index]);
registry.fill(HIST("NonPromptCharmMesons/hCountNonPrompt") + HIST(ParticleNames[Index]), counterNonPrompt[Index]);
});
static_for<NCharmMesonChannels, NCharmMesonChannels + NBeautyChannels - 1>([&](auto i) { // Beauty
constexpr int Index = i.value;
registry.fill(HIST("Beauty/hCount") + HIST(ParticleNames[Index]), counterPrompt[Index]);
registry.fill(HIST("Beauty/hCount") + HIST(ParticleNames[Index]), counterBeauty[Index]);
});
static_for<NCharmMesonChannels + NBeautyChannels, NChannels - 1>([&](auto i) { // Charm baryons
constexpr int Index = i.value;
Expand All @@ -609,16 +691,16 @@
for (const auto& mcCollision : mcCollisions) {
const auto recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex());
const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex());
std::array<int, NChannels> counterPrompt{0}, counterNonPrompt{0};
runCheckGenParticles<o2::hf_centrality::CentralityEstimator::FT0M>(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt);
std::array<int, NChannels> counterPrompt{0}, counterNonPrompt{0}, counterBeauty{0};
runCheckGenParticles<o2::hf_centrality::CentralityEstimator::FT0M>(mcCollision, mcParticlesPerMcColl, recoCollsPerMcColl, bcInfo, counterPrompt, counterNonPrompt, counterBeauty);
static_for<0, NCharmMesonChannels - 1>([&](auto i) { // Charm mesons
constexpr int Index = i.value;
registry.fill(HIST("PromptCharmMesons/hCountPrompt") + HIST(ParticleNames[Index]), counterPrompt[Index]);
registry.fill(HIST("NonPromptCharmMesons/hCountNonPrompt") + HIST(ParticleNames[Index]), counterNonPrompt[Index]);
});
static_for<NCharmMesonChannels, NCharmMesonChannels + NBeautyChannels - 1>([&](auto i) { // Beauty mesons
constexpr int Index = i.value;
registry.fill(HIST("Beauty/hCount") + HIST(ParticleNames[Index]), counterPrompt[Index]);
registry.fill(HIST("Beauty/hCount") + HIST(ParticleNames[Index]), counterBeauty[Index]);
});
static_for<NCharmMesonChannels + NBeautyChannels, NChannels - 1>([&](auto i) { // Charm baryons
constexpr int Index = i.value;
Expand All @@ -639,6 +721,7 @@
Preslice<aod::Tracks> perCol = aod::track::collisionId;

Configurable<int> eventGeneratorType{"eventGeneratorType", -1, "If positive, enable event selection using subGeneratorId information. The value indicates which events to keep (0 = MB, 4 = charm triggered, 5 = beauty triggered)"};
Configurable<bool> searchUpToQuark{"searchUpToQuark", true, "Search up to quark level when determining the origin of a particle (prompt vs non-prompt)"};
Configurable<bool> storeOccupancy{"storeOccupancy", false, "Store collision occupancy for dedicated studies"};

std::array<std::shared_ptr<TH1>, NChannels> histDeltaPt, histDeltaPx, histDeltaPy, histDeltaPz, histDeltaSecondaryVertexX, histDeltaSecondaryVertexY, histDeltaSecondaryVertexZ, histDeltaDecayLength;
Expand Down Expand Up @@ -921,7 +1004,7 @@
for (const auto& trackColl1 : tracksColl1) {
if (trackColl1.has_mcParticle() && trackColl1.isPVContributor()) {
auto particleColl1 = trackColl1.mcParticle();
auto origin = RecoDecay::getCharmHadronOrigin(mcParticles, particleColl1, true);
auto origin = RecoDecay::getParticleOrigin(mcParticles, particleColl1, searchUpToQuark);
if (origin == RecoDecay::NonPrompt) {
nFromBeautyColl1++;
}
Expand All @@ -931,7 +1014,7 @@
for (const auto& trackColl2 : tracksColl2) {
if (trackColl2.has_mcParticle() && trackColl2.isPVContributor()) {
auto particleColl2 = trackColl2.mcParticle();
auto origin = RecoDecay::getCharmHadronOrigin(mcParticles, particleColl2, true);
auto origin = RecoDecay::getParticleOrigin(mcParticles, particleColl2, searchUpToQuark);
if (origin == RecoDecay::NonPrompt) {
nFromBeautyColl2++;
}
Expand Down Expand Up @@ -960,7 +1043,7 @@
if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) {
continue;
}
auto origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, true);
auto origin = RecoDecay::getParticleOrigin(mcParticles, particle, searchUpToQuark);
histTracks->Fill(origin, track.pt());
bool const isAmbiguous = (track.compatibleCollIds().size() != 1);
if (isAmbiguous) {
Expand Down
Loading