Skip to content

Commit fb572ba

Browse files
ChiaraDeMartin95Chiara De Martin
andauthored
Add process function to compute efficiency of cascades for flow correction (#7884)
* add process function to analyse MC reco particles for efficiency calculation * add process function for MC generated cascades * fix clang --------- Co-authored-by: Chiara De Martin <chiara.de.martin@cern.ch>
1 parent 23111aa commit fb572ba

2 files changed

Lines changed: 178 additions & 5 deletions

File tree

PWGLF/DataModel/cascqaanalysis.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ DECLARE_SOA_TABLE(CascTraining, "AOD", "CascTraining", o2::soa::Index<>,
160160
mycascades::DCABachToPV, mycascades::DCACascDaughters, mycascades::DCAV0Daughters, mycascades::DCAV0ToPV, mycascades::BachBaryonCosPA, mycascades::BachBaryonDCAxyToPV, mycascades::McPdgCode);
161161

162162
DECLARE_SOA_TABLE(CascAnalysis, "AOD", "CascAnalysis", o2::soa::Index<>,
163-
cascadesflow::CentFT0C, cascadesflow::Sign, cascadesflow::Pt, cascadesflow::Eta, cascadesflow::Phi, cascadesflow::MassXi, cascadesflow::MassOmega, cascadesflow::V2CSP, cascadesflow::V2CEP, cascadesflow::PsiT0C, cascadesflow::BDTResponseXi, cascadesflow::BDTResponseOmega, cascadesflow::CosThetaStarLambdaFromOmega, cascadesflow::CosThetaStarLambdaFromXi, cascadesflow::CosThetaStarProton);
163+
cascadesflow::CentFT0C, cascadesflow::Sign, cascadesflow::Pt, cascadesflow::Eta, cascadesflow::Phi, cascadesflow::MassXi, cascadesflow::MassOmega, cascadesflow::V2CSP, cascadesflow::V2CEP, cascadesflow::PsiT0C, cascadesflow::BDTResponseXi, cascadesflow::BDTResponseOmega, cascadesflow::CosThetaStarLambdaFromOmega, cascadesflow::CosThetaStarLambdaFromXi, cascadesflow::CosThetaStarProton, mycascades::McPdgCode);
164164

165165
namespace myMCcascades
166166
{

PWGLF/TableProducer/Strangeness/cascadeflow.cxx

Lines changed: 177 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ static const std::vector<std::string> labelsCutScore = {"Background score", "Sig
120120

121121
struct cascadeFlow {
122122

123+
PresliceUnsorted<soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraCollLabels>> perMcCollision = aod::v0data::straMCCollisionId;
124+
123125
// axes
124126
ConfigurableAxis axisQVs{"axisQVs", {500, -10.f, 10.f}, "axisQVs"};
125127
ConfigurableAxis axisQVsNorm{"axisQVsNorm", {200, -1.f, 1.f}, "axisQVsNorm"};
@@ -144,6 +146,7 @@ struct cascadeFlow {
144146
Configurable<float> nsigmatpcPr{"nsigmatpcPr", 5, "nsigmatpcPr"};
145147
Configurable<float> nsigmatpcPi{"nsigmatpcPi", 5, "nsigmatpcPi"};
146148
Configurable<float> mintpccrrows{"mintpccrrows", 70, "mintpccrrows"};
149+
Configurable<float> etaCascMCGen{"etaCascMCGen", 0.8, "etaCascMCGen"};
147150

148151
Configurable<std::string> ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"};
149152
Configurable<std::vector<std::string>> modelPathsCCDBXi{"modelPathsCCDBXi", std::vector<std::string>{"Users/c/chdemart/CascadesFlow"}, "Paths of models on CCDB"};
@@ -255,6 +258,7 @@ struct cascadeFlow {
255258
}
256259

257260
HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject};
261+
HistogramRegistry histosMCGen{"histosMCGen", {}, OutputObjHandlingPolicy::AnalysisObject};
258262
HistogramRegistry resolution{"resolution", {}, OutputObjHandlingPolicy::AnalysisObject};
259263

260264
// Tables to produce
@@ -298,7 +302,7 @@ struct cascadeFlow {
298302
}
299303

300304
template <class collision_t, class cascade_t>
301-
void fillAnalysedTable(collision_t coll, cascade_t casc, float v2CSP, float v2CEP, float PsiT0C, float BDTresponseXi, float BDTresponseOmega)
305+
void fillAnalysedTable(collision_t coll, cascade_t casc, float v2CSP, float v2CEP, float PsiT0C, float BDTresponseXi, float BDTresponseOmega, int pdgCode)
302306
{
303307
double masses[2]{o2::constants::physics::MassXiMinus, o2::constants::physics::MassOmegaMinus};
304308
ROOT::Math::PxPyPzMVector cascadeVector[2], lambdaVector, protonVector;
@@ -333,7 +337,8 @@ struct cascadeFlow {
333337
BDTresponseOmega,
334338
cosThetaStarLambda[0],
335339
cosThetaStarLambda[1],
336-
cosThetaStarProton);
340+
cosThetaStarProton,
341+
pdgCode);
337342
}
338343

339344
void init(InitContext const&)
@@ -380,6 +385,11 @@ struct cascadeFlow {
380385
histos.add("hcascminuspsiT0C", "hcascminuspsiT0C", HistType::kTH1F, {{100, 0, TMath::Pi()}});
381386
histos.add("hv2CEPvsFT0C", "hv2CEPvsFT0C", HistType::kTH2F, {CentAxis, {100, -1, 1}});
382387
histos.add("hv2CEPvsv2CSP", "hv2CEPvsV2CSP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}});
388+
389+
histosMCGen.add("h2DGenXi", "h2DGenXi", HistType::kTH2F, {{100, 0, 00}, {200, 0, 20}});
390+
histosMCGen.add("h2DGenOmega", "h2DGenOmega", HistType::kTH2F, {{100, 0, 100}, {200, 0, 20}});
391+
histosMCGen.add("hGenEta", "hGenEta", HistType::kTH1F, {{100, -1, 1}});
392+
383393
for (int iS{0}; iS < 2; ++iS) {
384394
cascadev2::hMassBeforeSelVsPt[iS] = histos.add<TH2>(Form("hMassBeforeSelVsPt%s", cascadev2::speciesNames[iS].data()), "hMassBeforeSelVsPt", HistType::kTH2F, {massCascAxis[iS], ptAxis});
385395
cascadev2::hMassAfterSelVsPt[iS] = histos.add<TH2>(Form("hMassAfterSelVsPt%s", cascadev2::speciesNames[iS].data()), "hMassAfterSelVsPt", HistType::kTH2F, {massCascAxis[iS], ptAxis});
@@ -610,7 +620,7 @@ struct cascadeFlow {
610620
BDTresponse[1] = bdtScore[1][1];
611621
}
612622
if (isSelectedCasc[0] || isSelectedCasc[1])
613-
fillAnalysedTable(coll, casc, v2CSP, v2CEP, PsiT0C, BDTresponse[0], BDTresponse[1]);
623+
fillAnalysedTable(coll, casc, v2CSP, v2CEP, PsiT0C, BDTresponse[0], BDTresponse[1], 0);
614624
}
615625
}
616626

@@ -738,14 +748,177 @@ struct cascadeFlow {
738748
BDTresponse[1] = bdtScore[1][1];
739749
}
740750
if (isSelectedCasc[0] || isSelectedCasc[1])
741-
fillAnalysedTable(coll, casc, v2CSP, v2CEP, PsiT0C, BDTresponse[0], BDTresponse[1]);
751+
fillAnalysedTable(coll, casc, v2CSP, v2CEP, PsiT0C, BDTresponse[0], BDTresponse[1], 0);
752+
}
753+
}
754+
755+
void processAnalyseMC(soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraRawCents>::iterator const& coll, CascMCCandidates const& Cascades, DauTracks const&, soa::Join<aod::CascMCCores, aod::CascMCCollRefs> const&)
756+
{
757+
758+
if (!AcceptEvent(coll)) {
759+
return;
760+
}
761+
762+
histos.fill(HIST("hNEvents"), 7.5);
763+
histos.fill(HIST("hEventNchCorrelationAfterEP"), coll.multNTracksPVeta1(), coll.multNTracksGlobal());
764+
histos.fill(HIST("hEventPVcontributorsVsCentralityAfterEP"), coll.centFT0C(), coll.multNTracksPVeta1());
765+
histos.fill(HIST("hEventGlobalTracksVsCentralityAfterEP"), coll.centFT0C(), coll.multNTracksGlobal());
766+
histos.fill(HIST("hEventCentrality"), coll.centFT0C());
767+
histos.fill(HIST("hEventVertexZ"), coll.posZ());
768+
769+
std::vector<float> bdtScore[2];
770+
for (auto& casc : Cascades) {
771+
772+
if (!casc.has_cascMCCore())
773+
continue;
774+
775+
auto cascMC = casc.cascMCCore_as<soa::Join<aod::CascMCCores, aod::CascMCCollRefs>>();
776+
int pdgCode{cascMC.pdgCode()};
777+
if (!(std::abs(pdgCode) == 3312 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 211) // Xi
778+
&& !(std::abs(pdgCode) == 3334 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 321)) // Omega
779+
{
780+
pdgCode = 0;
781+
}
782+
783+
/// Add some minimal cuts for single track variables (min number of TPC clusters)
784+
auto negExtra = casc.negTrackExtra_as<DauTracks>();
785+
auto posExtra = casc.posTrackExtra_as<DauTracks>();
786+
auto bachExtra = casc.bachTrackExtra_as<DauTracks>();
787+
788+
int counter = 0;
789+
IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter);
790+
histos.fill(HIST("hCascade"), counter);
791+
792+
// ML selections
793+
bool isSelectedCasc[2]{false, false};
794+
795+
std::vector<float> inputFeaturesCasc{casc.cascradius(),
796+
casc.v0radius(),
797+
casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()),
798+
casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()),
799+
casc.dcapostopv(),
800+
casc.dcanegtopv(),
801+
casc.dcabachtopv(),
802+
casc.dcacascdaughters(),
803+
casc.dcaV0daughters(),
804+
casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ()),
805+
casc.bachBaryonCosPA(),
806+
casc.bachBaryonDCAxyToPV()};
807+
808+
float massCasc[2]{casc.mXi(), casc.mOmega()};
809+
810+
// inv mass loose cut
811+
if (casc.pt() < MinPt || casc.pt() > MaxPt) {
812+
continue;
813+
}
814+
815+
cascadev2::hMassBeforeSelVsPt[0]->Fill(massCasc[0], casc.pt());
816+
cascadev2::hMassBeforeSelVsPt[1]->Fill(massCasc[1], casc.pt());
817+
818+
if (isApplyML) {
819+
// Retrieve model output and selection outcome
820+
isSelectedCasc[0] = mlResponseXi.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[0]);
821+
isSelectedCasc[1] = mlResponseOmega.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[1]);
822+
823+
for (int iS{0}; iS < 2; ++iS) {
824+
// Fill BDT score histograms before selection
825+
cascadev2::hSignalScoreBeforeSel[iS]->Fill(bdtScore[0][1]);
826+
cascadev2::hBkgScoreBeforeSel[iS]->Fill(bdtScore[1][0]);
827+
828+
// Fill histograms for selected candidates
829+
if (isSelectedCasc[iS]) {
830+
cascadev2::hSignalScoreAfterSel[iS]->Fill(bdtScore[0][1]);
831+
cascadev2::hBkgScoreAfterSel[iS]->Fill(bdtScore[1][0]);
832+
cascadev2::hMassAfterSelVsPt[iS]->Fill(massCasc[iS], casc.pt());
833+
}
834+
}
835+
} else {
836+
isSelectedCasc[0] = true;
837+
isSelectedCasc[1] = true;
838+
}
839+
840+
histos.fill(HIST("hCascadePhi"), casc.phi());
841+
842+
float BDTresponse[2]{0.f, 0.f};
843+
const float PsiT0C = 0; // not defined in MC for now
844+
auto v2CSP = 0; // not defined in MC for now
845+
auto v2CEP = 0; // not defined in MC for now
846+
847+
if (isApplyML) {
848+
BDTresponse[0] = bdtScore[0][1];
849+
BDTresponse[1] = bdtScore[1][1];
850+
}
851+
if (isSelectedCasc[0] || isSelectedCasc[1])
852+
fillAnalysedTable(coll, casc, v2CSP, v2CEP, PsiT0C, BDTresponse[0], BDTresponse[1], pdgCode);
853+
}
854+
}
855+
void processMCGen(soa::Join<aod::StraMCCollisions, aod::StraMCCollMults>::iterator const& mcCollision, soa::Join<aod::StraCollisions, aod::StraCents, aod::StraEvSels, aod::StraCollLabels> const& collisions, soa::Join<aod::CascMCCores, aod::CascMCCollRefs> const& CascMCCores)
856+
{
857+
// Generated with accepted z vertex
858+
if (TMath::Abs(mcCollision.posZ()) > cutzvertex) {
859+
return;
860+
}
861+
862+
// Check if there is at least one of the reconstructed collisions associated to this MC collision
863+
auto groupedCollisions = collisions.sliceBy(perMcCollision, mcCollision.globalIndex());
864+
int biggestNContribs = -1;
865+
int bestCollisionIndex = -1;
866+
float centrality = 100.5f;
867+
int nCollisions = 0;
868+
for (auto const& collision : groupedCollisions) {
869+
870+
if (!AcceptEvent(collision)) {
871+
continue;
872+
}
873+
if (biggestNContribs < collision.multPVTotalContributors()) {
874+
biggestNContribs = collision.multPVTotalContributors();
875+
bestCollisionIndex = collision.globalIndex();
876+
centrality = collision.centFT0C();
877+
}
878+
nCollisions++;
879+
}
880+
if (nCollisions < 1) {
881+
return;
882+
}
883+
for (auto const& cascMC : CascMCCores) {
884+
if (!cascMC.has_straMCCollision())
885+
continue;
886+
887+
if (!cascMC.isPhysicalPrimary())
888+
continue;
889+
890+
float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC());
891+
892+
float theta = std::atan(ptmc / cascMC.pzMC()); //-pi/2 < theta < pi/2
893+
894+
float theta1 = 0;
895+
896+
// if pz is positive (i.e. positive rapidity): 0 < theta < pi/2
897+
if (theta > 0)
898+
theta1 = theta; // 0 < theta1/2 < pi/4 --> 0 < tan (theta1/2) < 1 --> positive eta
899+
// if pz is negative (i.e. negative rapidity): -pi/2 < theta < 0 --> we need 0 < theta1/2 < pi/2 for the ln to be defined
900+
else
901+
theta1 = TMath::Pi() + theta; // pi/2 < theta1 < pi --> pi/4 < theta1/2 < pi/2 --> 1 < tan (theta1/2) --> negative eta
902+
903+
float cascMCeta = -log(std::tan(theta1 / 2));
904+
if (TMath::Abs(cascMCeta) > etaCascMCGen)
905+
continue;
906+
histosMCGen.fill(HIST("hGenEta"), cascMCeta);
907+
908+
if (TMath::Abs(cascMC.pdgCode()) == 3312) {
909+
histosMCGen.fill(HIST("h2dGenXi"), centrality, ptmc);
910+
} else if (TMath::Abs(cascMC.pdgCode() == 3334)) {
911+
histosMCGen.fill(HIST("h2dGenOmega"), centrality, ptmc);
912+
}
742913
}
743914
}
744915

745916
PROCESS_SWITCH(cascadeFlow, processTrainingBackground, "Process to create the training dataset for the background", true);
746917
PROCESS_SWITCH(cascadeFlow, processTrainingSignal, "Process to create the training dataset for the signal", false);
747918
PROCESS_SWITCH(cascadeFlow, processAnalyseData, "Process to apply ML model to the data", false);
748919
PROCESS_SWITCH(cascadeFlow, processAnalyseDataEPCentralFW, "Process to apply ML model to the data - event plane calibration from central framework", false);
920+
PROCESS_SWITCH(cascadeFlow, processAnalyseMC, "Process to apply ML model to the MC", false);
921+
PROCESS_SWITCH(cascadeFlow, processMCGen, "Process to store MC generated particles", false);
749922
};
750923

751924
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)

0 commit comments

Comments
 (0)