diff --git a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx index 0c6a0b843a2..18d854aa1f6 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx @@ -337,6 +337,7 @@ struct lambdakzeroBuilder { // Helper struct to do bookkeeping of building parameters struct { std::array v0stats; + std::array v0statsUnassociated; std::array posITSclu; std::array negITSclu; int32_t exceptions; @@ -408,8 +409,10 @@ struct lambdakzeroBuilder { { statisticsRegistry.exceptions = 0; statisticsRegistry.eventCounter = 0; - for (Int_t ii = 0; ii < kNV0Steps; ii++) + for (Int_t ii = 0; ii < kNV0Steps; ii++) { statisticsRegistry.v0stats[ii] = 0; + statisticsRegistry.v0statsUnassociated[ii] = 0; + } for (Int_t ii = 0; ii < 10; ii++) { statisticsRegistry.posITSclu[ii] = 0; statisticsRegistry.negITSclu[ii] = 0; @@ -420,8 +423,10 @@ struct lambdakzeroBuilder { { registry.fill(HIST("hEventCounter"), 0.0, statisticsRegistry.eventCounter); registry.fill(HIST("hCaughtExceptions"), 0.0, statisticsRegistry.exceptions); - for (Int_t ii = 0; ii < kNV0Steps; ii++) + for (Int_t ii = 0; ii < kNV0Steps; ii++) { registry.fill(HIST("hV0Criteria"), ii, statisticsRegistry.v0stats[ii]); + registry.fill(HIST("hV0CriteriaUnassociated"), ii, statisticsRegistry.v0statsUnassociated[ii]); + } if (qaConfigurations.d_doTrackQA) { for (Int_t ii = 0; ii < 10; ii++) { registry.fill(HIST("hPositiveITSClusters"), ii, statisticsRegistry.posITSclu[ii]); @@ -450,6 +455,17 @@ struct lambdakzeroBuilder { h->GetXaxis()->SetBinLabel(8, "Count: Standard V0"); h->GetXaxis()->SetBinLabel(9, "Count: V0 exc. for casc"); + auto h2 = registry.add("hV0CriteriaUnassociated", "hV0CriteriaUnassociated", kTH1D, {{10, -0.5f, 9.5f}}); + h2->GetXaxis()->SetBinLabel(1, "All sel"); + h2->GetXaxis()->SetBinLabel(2, "TPC requirement"); + h2->GetXaxis()->SetBinLabel(3, "DCAxy Dau to PV"); + h2->GetXaxis()->SetBinLabel(4, "DCA V0 Dau"); + h2->GetXaxis()->SetBinLabel(5, "CosPA"); + h2->GetXaxis()->SetBinLabel(6, "Radius"); + h2->GetXaxis()->SetBinLabel(7, "Within momentum range"); + h2->GetXaxis()->SetBinLabel(8, "Count: Standard V0"); + h2->GetXaxis()->SetBinLabel(9, "Count: V0 exc. for casc"); + randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); // Optionally, add extra QA histograms to processing chain @@ -801,6 +817,9 @@ struct lambdakzeroBuilder { // value 0.5: any considered V0 statisticsRegistry.v0stats[kV0All]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kV0All]++; + if (tpcrefit) { if (!(posTrack.trackType() & o2::aod::track::TPCrefit)) { return false; @@ -812,6 +831,8 @@ struct lambdakzeroBuilder { // Passes TPC refit statisticsRegistry.v0stats[kV0TPCrefit]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kV0TPCrefit]++; // Calculate DCA with respect to the collision associated to the V0, not individual tracks gpu::gpustd::array dcaInfo; @@ -834,6 +855,8 @@ struct lambdakzeroBuilder { // passes DCAxy statisticsRegistry.v0stats[kV0DCAxy]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kV0DCAxy]++; // Change strangenessBuilder tracks lPositiveTrack = getTrackParCov(posTrack); @@ -881,6 +904,8 @@ struct lambdakzeroBuilder { // Passes DCA between daughters check statisticsRegistry.v0stats[kV0DCADau]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kV0DCADau]++; v0candidate.cosPA = RecoDecay::cpa(array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, array{v0candidate.pos[0], v0candidate.pos[1], v0candidate.pos[2]}, array{v0candidate.posP[0] + v0candidate.negP[0], v0candidate.posP[1] + v0candidate.negP[1], v0candidate.posP[2] + v0candidate.negP[2]}); if (v0candidate.cosPA < v0cospa) { @@ -896,6 +921,8 @@ struct lambdakzeroBuilder { // Passes CosPA check statisticsRegistry.v0stats[kV0CosPA]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kV0CosPA]++; v0candidate.V0radius = RecoDecay::sqrtSumOfSquares(v0candidate.pos[0], v0candidate.pos[1]); if (v0candidate.V0radius < v0radius) { @@ -904,6 +931,8 @@ struct lambdakzeroBuilder { // Passes radius check statisticsRegistry.v0stats[kV0Radius]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kV0Radius]++; // Return OK: passed all v0 candidate selecton criteria auto px = v0candidate.posP[0] + v0candidate.negP[0]; @@ -931,6 +960,8 @@ struct lambdakzeroBuilder { // Passes momentum window check statisticsRegistry.v0stats[kWithinMomentumRange]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kWithinMomentumRange]++; // Calculate masses auto lGammaMass = RecoDecay::m(array{array{v0candidate.posP[0], v0candidate.posP[1], v0candidate.posP[2]}, array{v0candidate.negP[0], v0candidate.negP[1], v0candidate.negP[2]}}, array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); @@ -1164,6 +1195,9 @@ struct lambdakzeroBuilder { // populates the various tables for analysis statisticsRegistry.v0stats[kCountStandardV0]++; + if (!V0.has_collision()) + statisticsRegistry.v0statsUnassociated[kCountStandardV0]++; + v0indices(V0.posTrackId(), V0.negTrackId(), V0.collisionId(), V0.globalIndex()); v0trackXs(v0candidate.posTrackX, v0candidate.negTrackX); diff --git a/PWGLF/TableProducer/Strangeness/lambdakzeromcfinder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzeromcfinder.cxx index 70e04d3f88f..86e71a80ae2 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzeromcfinder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzeromcfinder.cxx @@ -83,7 +83,8 @@ struct lambdakzeromcfinder { Configurable requireTPC{"requireTPC", true, "require TPC"}; Configurable skipTPConly{"skipTPConly", false, "skip tracks that are TPC-only"}; Configurable storeSingleTPCOnlyProng{"storeSingleTPCOnlyProng", false, "in case a TPC-only track is found, do not allow another TPC-only for the same mcParticle. Works only in MC particle path."}; - Configurable doUnassociatedV0s{"doUnassociatedV0s", true, "generate also unassociated V0s (for cascades!)"}; + Configurable doAssociatedV0s{"doAssociatedV0s", true, "generate collision-associated V0s (for cascades!)"}; + Configurable doUnassociatedV0s{"doUnassociatedV0s", true, "generate also unassociated V0s (for cascades, UPC)"}; Configurable doSameCollisionOnly{"doSameCollisionOnly", false, "stick to decays in which tracks are assoc to same collision"}; Configurable qaNbins{"qaNbins", 200, "qa plots: binning"}; Configurable yPreFilter{"yPreFilter", 2.5, "broad y pre-filter for speed"}; @@ -109,6 +110,9 @@ struct lambdakzeromcfinder { histos.add("hNTimesCollRecoed", "hNTimesCollRecoed", kTH1F, {axisNTimesRecoed}); + // store number of recoed V0s and number of recoed V0s with no collision association + histos.add("hNCollisionAssociation", "hNCollisionAssociation", kTH1F, {axisNTimesRecoed}); + // warning: this stores (composite) number of copies of tracks histos.add("hNTimesRecoedGamma", "hNTimesRecoedGamma", kTH2F, {axisNTimesRecoed, axisPtQA}); histos.add("hNTimesRecoedK0Short", "hNTimesRecoedK0Short", kTH2F, {axisNTimesRecoed, axisPtQA}); @@ -302,7 +306,15 @@ struct lambdakzeromcfinder { // V0 list established, populate for (auto ic : sortedIndices) { - if (v0collisionId[ic] >= 0 || doUnassociatedV0s) { + histos.fill(HIST("hNCollisionAssociation"), 0.0f); // any correctly recoed + if (v0collisionId[ic] >= 0) + histos.fill(HIST("hNCollisionAssociation"), 1.0f); // reconstructed with a collision associated to it + + if (v0collisionId[ic] < 0 && doUnassociatedV0s) { + v0(v0collisionId[ic], v0positiveIndex[ic], v0negativeIndex[ic], 1); + fullv0labels(v0mcLabel[ic]); + } + if (v0collisionId[ic] >= 0 && doAssociatedV0s) { v0(v0collisionId[ic], v0positiveIndex[ic], v0negativeIndex[ic], 1); fullv0labels(v0mcLabel[ic]); } diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index ef8d077f0ec..28a36c3560c 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -81,6 +81,8 @@ struct derivedlambdakzeroanalysis { Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", true, "require events with at least one of vertex contributors matched to TRD"}; Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; + Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + // Selection criteria: acceptance Configurable rapidityCut{"rapidityCut", 0.5, "rapidity"}; Configurable daughterEtaCut{"daughterEtaCut", 0.8, "max eta for daughters"}; @@ -128,6 +130,10 @@ struct derivedlambdakzeroanalysis { Configurable doMCAssociation{"doMCAssociation", true, "if MC, do MC association"}; Configurable doCollisionAssociationQA{"doCollisionAssociationQA", true, "check collision association"}; + // fast check on occupancy + Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; + Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + static constexpr float defaultLifetimeCuts[1][2] = {{30., 20.}}; Configurable> lifetimecut{"lifetimecut", {defaultLifetimeCuts[0], 2, {"lifetimecutLambda", "lifetimecutK0S"}}, "lifetimecut"}; @@ -295,7 +301,7 @@ struct derivedlambdakzeroanalysis { secondaryMaskSelectionAntiLambda = maskTopological | maskTrackProperties | maskAntiLambdaSpecific; // Event Counters - histos.add("hEventSelection", "hEventSelection", kTH1F, {{10, -0.5f, +9.5f}}); + histos.add("hEventSelection", "hEventSelection", kTH1F, {{12, -0.5f, +11.5f}}); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(3, "posZ cut"); @@ -306,6 +312,8 @@ struct derivedlambdakzeroanalysis { histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(11, "Below min occup."); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(12, "Above max occup."); histos.add("hEventCentrality", "hEventCentrality", kTH1F, {{100, 0.0f, +100.0f}}); histos.add("hCentralityVsNch", "hCentralityVsNch", kTH2F, {axisCentrality, {500, 0.0f, +2000.0f}}); @@ -1066,6 +1074,15 @@ struct derivedlambdakzeroanalysis { } histos.fill(HIST("hEventSelection"), 9 /* Not at same bunch pile-up */); + if (minOccupancy > 0 && collision.trackOccupancyInTimeRange() < minOccupancy) { + return; + } + histos.fill(HIST("hEventSelection"), 10 /* Below min occupancy */); + if (maxOccupancy > 0 && collision.trackOccupancyInTimeRange() > maxOccupancy) { + return; + } + histos.fill(HIST("hEventSelection"), 11 /* Above max occupancy */); + float centrality = collision.centFT0C(); if (qaCentrality) { auto hRawCentrality = histos.get(HIST("hRawCentrality")); @@ -1082,6 +1099,9 @@ struct derivedlambdakzeroanalysis { if (std::abs(v0.negativeeta()) > daughterEtaCut || std::abs(v0.positiveeta()) > daughterEtaCut) continue; // remove acceptance that's badly reproduced by MC / superfluous in future + if (v0.v0Type() != v0TypeSelection && v0TypeSelection > -1) + continue; // skip V0s that are not standard + // fill AP plot for all V0s histos.fill(HIST("GeneralQA/h2dArmenterosAll"), v0.alpha(), v0.qtarm());