8#include <ecl/modules/eclChargedPIDDataAnalysisExpert/ECLChargedPIDDataAnalysisValidationModule.h>
10#include <ecl/dataobjects/ECLPidLikelihood.h>
11#include <mdst/dataobjects/ECLCluster.h>
12#include <mdst/dataobjects/MCParticle.h>
13#include <mdst/dataobjects/Track.h>
15#include <TEfficiency.h>
23REG_MODULE(ECLChargedPIDDataAnalysisValidation);
32 setDescription(
"This module dumps a set of histograms with ECL charged PID-related info used for validation, starting from an input file w/ particle-gun-generated charged stable particles (and antiparticles).");
35 std::vector<int> defaultChargedPdgIds;
37 defaultChargedPdgIds.push_back(hypo.getPDGCode());
38 defaultChargedPdgIds.push_back(-hypo.getPDGCode());
42 "The list of (signed) pdgIds of the charged stable particles for which validation plots should be produced. Default is ALL charged stable particles.",
43 defaultChargedPdgIds);
45 "The list of (unsigned) pdgIds of the charged stable particles for which particle and antiparticle should be merged together in the plots. Default is no merging, meaning separate plots are generated for +/- charged particles for each input pdgId.",
46 std::vector<unsigned int>());
48 "The base name of the output file. The pdgId of the charged particle is appended to the name.",
49 std::string(
"ECLChargedPid"));
51 "If this flag is set to True, save also the validation TTree. Default is False.",
62 B2INFO(
"Initialising ROOT objects...");
73 B2WARNING(
"For (unsigned) hypothesis " << hypo.getPDGCode() <<
", validation plots will be merged for +/- charged particles.");
78 std::string chargedPdgIdStr;
85 B2FATAL(
"PDG: " << chargedPdgId <<
" in m_inputPdgIdSet is not that of a valid particle in Const::chargedStableSet! Aborting...");
95 auto chargedIdx = chargedHypo.
getIndex();
97 if (chargedPdgId > 0) {
98 chargedPdgIdStr = std::to_string(chargedPdgId);
100 chargedPdgIdStr =
"anti" + std::to_string(std::abs(chargedPdgId));
107 m_outputFile[chargedIdx] =
new TFile(fname.c_str(),
"RECREATE");
109 m_tree[chargedIdx] =
new TTree(
"ECLChargedPid",
"ECLChargedPid");
110 m_tree[chargedIdx]->Branch(
"p", &
m_p[chargedIdx],
"p/F");
111 m_tree[chargedIdx]->Branch(
"pt", &
m_pt[chargedIdx],
"pt/F");
112 m_tree[chargedIdx]->Branch(
"trkTheta", &
m_trkTheta[chargedIdx],
"trkTheta/F");
113 m_tree[chargedIdx]->Branch(
"trkPhi", &
m_trkPhi[chargedIdx],
"trkPhi/F");
118 m_tree[chargedIdx]->Branch(
"logl_sig", &
m_logl_sig[chargedIdx],
"logl_sig/F");
119 m_tree[chargedIdx]->Branch(
"logl_bkg", &
m_logl_bkg[chargedIdx],
"logl_bkg/F");
142 auto chargedIdx = chargedHypo.
getIndex();
144 if (chargedPdgId < 0) {
150 m_p[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
151 m_pt[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
152 m_trkTheta[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
153 m_trkPhi[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
154 m_clusterTheta[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
155 m_clusterPhi[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
156 m_clusterReg[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
158 m_logl_sig[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
159 m_logl_bkg[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
162 m_pids_glob[chargedIdx][chargedStable.getIndex()] = std::numeric_limits<float>::quiet_NaN();
175 if (std::abs(particle.getPDG()) != std::abs(chargedPdgId))
continue;
178 if (particle.getPDG() != chargedPdgId)
continue;
184 double p_max(-999.0);
185 for (
const auto& track : particle.getRelationsFrom<
Track>()) {
186 const auto fitRes = track.getTrackFitResultWithClosestMass(
Const::pion);
187 if (!fitRes)
continue;
188 if (fitRes->getMomentum().R() > p_max) {
189 p_max = fitRes->getMomentum().R();
194 if (itrack_max < 0)
continue;
196 const auto track = particle.getRelationsFrom<
Track>()[itrack_max];
197 const auto fitRes = track->getTrackFitResultWithClosestMass(
Const::pion);
199 m_p[chargedIdx] = p_max;
200 m_pt[chargedIdx] = fitRes->get4Momentum().Pt();
201 m_trkTheta[chargedIdx] = fitRes->get4Momentum().Theta();
202 m_trkPhi[chargedIdx] = fitRes->get4Momentum().Phi();
205 int icluster_match(-1);
206 auto eclClusters = track->getRelationsTo<
ECLCluster>();
207 for (
unsigned int icluster(0); icluster < eclClusters.size(); ++icluster) {
208 const auto eclCluster = eclClusters[icluster];
210 if (!eclCluster->isTrack())
continue;
211 icluster_match = icluster;
215 if (icluster_match < 0) {
220 const auto eclCluster = eclClusters[icluster_match];
224 m_clusterReg[chargedIdx] = eclCluster->getDetectorRegion();
237 if (not eclLikelihood)
240 double lh_sig = eclLikelihood->
getLikelihood(chargedStableSig);
241 double lh_bkg = eclLikelihood->getLikelihood(chargedStableBkg);
250 lh_all += eclLikelihood->getLikelihood(chargedStable);
253 m_pids_glob[chargedIdx][chargedStable.getIndex()] = eclLikelihood->getLikelihood(chargedStable) / lh_all;
258 m_tree[chargedIdx]->Fill();
278 if (mergeCharge && chargedPdgId <= 0)
continue;
281 const auto chargeSign =
static_cast<int>(chargedPdgId / std::abs(chargedPdgId));
284 const auto chargedStableSig = chargedStableSample;
291 auto chargedSampleIdx = (chargeSign > 0) ? chargedStableSig.
getIndex() : chargedStableSig.getIndex() +
296 auto pdgIdDesc = (mergeCharge) ? std::to_string(chargedPdgId) +
" and -" + std::to_string(chargedPdgId) : std::to_string(
300 TNamed(
"Description", TString::Format(
"ECL Charged PID control plots for charged stable particles/antiparticles ; Sample PDG = %s",
301 pdgIdDesc.c_str()).Data()).Write();
304 dumpPIDVars(
m_tree[chargedSampleIdx], chargedStableSig, chargeSign, chargedStableBkg, mergeCharge);
317 m_tree[chargedSampleIdx]->Write();
331 const auto sigHypoIdx = sigHypo.
getIndex();
332 const auto sigHypoPdgId = sigHypo.
getPDGCode();
335 const auto bkgHypoPdgId = bkgHypo.
getPDGCode();
339 TString pidSigBranch = TString::Format(
"pids_glob[%i]", sigHypoIdx);
342 TString h_pid_name = TString::Format(
"h_pid_sig_%i", sigHypoPdgId);
343 TH1F* h_pid =
new TH1F(h_pid_name.Data(), h_pid_name.Data(), 50, -0.5, 1.2);
344 h_pid->GetXaxis()->SetTitle(TString::Format(
"Likelihood ratio (%i/ALL) (ECL)", sigHypoPdgId).Data());
347 TString h_deltalogl_name = TString::Format(
"h_deltalogl_bkg_%i_sig_%i", bkgHypoPdgId, sigHypoPdgId);
348 double deltalogl_min = -20.0;
349 double deltalogl_max = 20.0;
350 TH1F* h_deltalogl =
new TH1F(h_deltalogl_name.Data(), h_deltalogl_name.Data(), 40, deltalogl_min, deltalogl_max);
351 h_deltalogl->GetXaxis()->SetTitle(TString::Format(
"#Deltaln(L) (%i/%i) (ECL)", bkgHypoPdgId, sigHypoPdgId).Data());
354 TString h_trkclusmatch_name = TString::Format(
"h_trkclusmatch_sig_%i", sigHypoPdgId);
355 TH1F* h_trkclusmatch =
new TH1F(h_trkclusmatch_name.Data(), h_trkclusmatch_name.Data(), 4, -1.5, 2.5);
356 h_trkclusmatch->GetXaxis()->SetTitle(TString::Format(
"Track-ECLCluster match (%i)", sigHypoPdgId).Data());
359 sampleTree->Project(h_pid_name.Data(), pidSigBranch.Data());
360 sampleTree->Project(h_deltalogl_name.Data(),
"deltalogl_sig_bkg");
361 sampleTree->Project(h_trkclusmatch_name.Data(),
"trackClusterMatch");
368 h_pid->SetOption(
"HIST");
369 h_deltalogl->SetOption(
"HIST");
370 h_trkclusmatch->SetOption(
"HIST");
373 std::string metaopts(
"pvalue-warn=0.1,pvalue-error=0.01");
374 std::string shifteropt(
"");
377 shifteropt =
"shifter,";
380 auto pdgIdDesc = (!mergeSigCharge) ? std::to_string(sigHypoPdgId * sigCharge) : std::to_string(
381 sigHypoPdgId) +
" and -" + std::to_string(sigHypoPdgId);
384 h_pid->GetListOfFunctions()->Add(
new TNamed(
"Description",
385 TString::Format(
"Sample PDG = %s ; ECL global PID(%i) distribution. U/O flow is added to first (last) bin.",
387 sigHypoPdgId).Data()));
388 h_pid->GetListOfFunctions()->Add(
new TNamed(
"Check",
389 "The more peaked at 1, the better. Non-zero O-flow indicates either failure of MC matching for reco tracks (unlikely), or failure of track-ECL-cluster matching (more likely). Both cases result in PID=nan."));
390 h_pid->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marcel Hohmann. mhohmann@student.unimelb.edu.au"));
391 h_pid->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
393 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"Description",
394 TString::Format(
"Sample PDG = %s ; ECL distribution of binary $\\Delta log(L)$ = log(L(%i)) - log(L(%i)). U/O flow is added to first (last) bin.",
397 sigHypoPdgId).Data()));
398 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"Check",
399 "Basic metric for signal/bkg separation. The more negative, the better separation is achieved. Non-zero U-flow indicates a non-normal PDF value (of sig OR bkg) for some p,clusterTheta range, which might be due to a non-optimal definition of the x-axis range of the PDF templates. Non-zero O-flow indicates either failure of MC matching for reco tracks (unlikely), or failure of track-ECL-cluster matching (more likely)."));
400 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marcel Hohmann. mhohmann@student.unimelb.edu.au"));
401 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
403 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"Description",
404 TString::Format(
"Sample PDG = %s ; Track-ECLCluster match flag distribution.",
405 pdgIdDesc.c_str()).Data()));
406 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"Check",
407 "The more peaked at 1, the better. Non-zero population in the bins w/ flag != 0|1 indicates failure of MC matching for reco tracks. In such cases, flag=nan."));
408 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Priyanka Cheema. pche3675@uni.sydney.edu.au"));
409 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", metaopts.c_str()));
412 h_deltalogl->Write();
413 h_trkclusmatch->Write();
417 delete h_trkclusmatch;
427 const std::string ratioType = (sampleHypo == sigHypo) ?
"Efficiency" :
"FakeRate";
430 const int sampleHypoPdgId = sampleHypo.
getPDGCode() * sampleCharge;
433 const auto sigHypoIdx = sigHypo.
getIndex();
434 const auto sigHypoPdgId = sigHypo.
getPDGCode();
438 TString pidSigCut = TString::Format(
"pids_glob[%i] > %f", sigHypoIdx,
c_PID);
441 TString h_p_N_name = TString::Format(
"h_p_N_%i", sigHypoPdgId);
442 TString h_p_D_name = TString::Format(
"h_p_D_%i", sigHypoPdgId);
443 TH1F* h_p_N =
new TH1F(h_p_N_name.Data(),
"h_p_N", 10, 0.0, 5.0);
444 TH1F* h_p_D =
new TH1F(h_p_D_name.Data(),
"h_p_D", 10, 0.0, 5.0);
446 TString h_th_N_name = TString::Format(
"h_th_N_%i", sigHypoPdgId);
447 TString h_th_D_name = TString::Format(
"h_th_D_%i", sigHypoPdgId);
451 TString h_eclreg_N_name = TString::Format(
"h_eclreg_N_%i", sigHypoPdgId);
452 TString h_eclreg_D_name = TString::Format(
"h_eclreg_D_%i", sigHypoPdgId);
453 TH1F* h_eclreg_N =
new TH1F(h_eclreg_N_name.Data(),
"h_eclreg_N", 5, -0.5, 4.5);
454 TH1F* h_eclreg_D =
new TH1F(h_eclreg_D_name.Data(),
"h_eclreg_D", 5, -0.5, 4.5);
456 TString h_phi_N_name = TString::Format(
"h_phi_N_%i", sigHypoPdgId);
457 TString h_phi_D_name = TString::Format(
"h_phi_D_%i", sigHypoPdgId);
458 TH1F* h_phi_N =
new TH1F(h_phi_N_name.Data(),
"h_phi_N", 5, -3.14159, 3.14159);
459 TH1F* h_phi_D =
new TH1F(h_phi_D_name.Data(),
"h_phi_D", 5, -3.14159, 3.14159);
463 sampleTree->Project(h_p_N_name.Data(),
"p", pidSigCut.Data());
464 sampleTree->Project(h_p_D_name.Data(),
"p");
466 sampleTree->Project(h_th_N_name.Data(),
"clusterTheta", pidSigCut.Data());
467 sampleTree->Project(h_th_D_name.Data(),
"clusterTheta");
469 sampleTree->Project(h_eclreg_N_name.Data(),
"clusterReg", pidSigCut.Data());
470 sampleTree->Project(h_eclreg_D_name.Data(),
"clusterReg");
474 sampleTree->Project(h_phi_N_name.Data(),
"clusterPhi", pidSigCut.Data());
475 sampleTree->Project(h_phi_D_name.Data(),
"clusterPhi");
479 TString pid_glob_ratio_p_name = TString::Format(
"pid_glob_%i_%s__VS_p", sigHypoPdgId, ratioType.c_str());
480 TString pid_glob_ratio_th_name = TString::Format(
"pid_glob_%i_%s__VS_th", sigHypoPdgId, ratioType.c_str());
481 TString pid_glob_ratio_eclreg_name = TString::Format(
"pid_glob_%i_%s__VS_eclreg", sigHypoPdgId, ratioType.c_str());
482 TString pid_glob_ratio_phi_name = TString::Format(
"pid_glob_%i_%s__VS_phi", sigHypoPdgId, ratioType.c_str());
485 std::string metaopts(
"pvalue-warn=0.01,pvalue-error=0.001,nostats");
486 std::string shifteropt(
"");
489 shifteropt =
"shifter,";
492 auto pdgIdDesc = (!mergeSampleCharge) ? std::to_string(sampleHypoPdgId) : std::to_string(std::abs(
493 sampleHypoPdgId)) +
" and -" + std::to_string(std::abs(sampleHypoPdgId));
495 if (TEfficiency::CheckConsistency(*h_p_N, *h_p_D)) {
497 TEfficiency* t_pid_glob_ratio_p =
new TEfficiency(*h_p_N, *h_p_D);
498 t_pid_glob_ratio_p->SetName(pid_glob_ratio_p_name.Data());
499 t_pid_glob_ratio_p->SetTitle(TString::Format(
"%s;p [GeV/c];#varepsilon/f", pid_glob_ratio_p_name.Data()).Data());
501 t_pid_glob_ratio_p->SetConfidenceLevel(0.683);
502 t_pid_glob_ratio_p->SetStatisticOption(TEfficiency::kBUniform);
503 t_pid_glob_ratio_p->SetPosteriorMode();
505 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"Description",
506 TString::Format(
"Sample PDG = %s ; %s of ECL global PID(%i) > %.2f as a function of $p_{trk}$.",
511 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"Check",
512 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
513 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marcel Hohmann. mhohmann@student.unimelb.edu.au"));
514 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
516 t_pid_glob_ratio_p->Write();
518 delete t_pid_glob_ratio_p;
521 if (TEfficiency::CheckConsistency(*h_th_N, *h_th_D)) {
523 TEfficiency* t_pid_glob_ratio_th =
new TEfficiency(*h_th_N, *h_th_D);
524 t_pid_glob_ratio_th->SetName(pid_glob_ratio_th_name.Data());
525 t_pid_glob_ratio_th->SetTitle(TString::Format(
"%s;#theta_{cluster} [rad];#varepsilon/f", pid_glob_ratio_th_name.Data()).Data());
527 t_pid_glob_ratio_th->SetConfidenceLevel(0.683);
528 t_pid_glob_ratio_th->SetStatisticOption(TEfficiency::kBUniform);
529 t_pid_glob_ratio_th->SetPosteriorMode();
531 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"Description",
532 TString::Format(
"Sample PDG = %s ; %s of ECL global PID(%i) > %.2f as a function of $\\theta_{cluster}$.",
537 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"Check",
538 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
539 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marcel Hohmann. mhohmann@student.unimelb.edu.au"));
540 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
542 t_pid_glob_ratio_th->Write();
544 delete t_pid_glob_ratio_th;
546 if (TEfficiency::CheckConsistency(*h_eclreg_N, *h_eclreg_D)) {
548 TEfficiency* t_pid_glob_ratio_eclreg =
new TEfficiency(*h_eclreg_N, *h_eclreg_D);
549 t_pid_glob_ratio_eclreg->SetName(pid_glob_ratio_eclreg_name.Data());
550 t_pid_glob_ratio_eclreg->SetTitle(TString::Format(
"%s;ECL Region;#varepsilon/f", pid_glob_ratio_eclreg_name.Data()).Data());
552 t_pid_glob_ratio_eclreg->SetConfidenceLevel(0.683);
553 t_pid_glob_ratio_eclreg->SetStatisticOption(TEfficiency::kBUniform);
554 t_pid_glob_ratio_eclreg->SetPosteriorMode();
556 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"Description",
557 TString::Format(
"Sample PDG = %s ; %s of ECL global PID(%i) > %.2f as a function of ECL cluster region ($\\theta_{cluster}$). Regions are labelled: 0 (outside ECL acceptance), 1 (ECL FWD), 2 (ECL Barrel), 3 (ECL BWD), 4 (ECL FWD/BWD gaps).",
562 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"Check",
563 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
564 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marcel Hohmann. mhohmann@student.unimelb.edu.au"));
565 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", metaopts.c_str()));
567 t_pid_glob_ratio_eclreg->Write();
569 delete t_pid_glob_ratio_eclreg;
572 if (TEfficiency::CheckConsistency(*h_phi_N, *h_phi_D)) {
574 TEfficiency* t_pid_glob_ratio_phi =
new TEfficiency(*h_phi_N, *h_phi_D);
575 t_pid_glob_ratio_phi->SetName(pid_glob_ratio_phi_name.Data());
576 t_pid_glob_ratio_phi->SetTitle(TString::Format(
"%s;#phi_{cluster} [rad];#varepsilon/f", pid_glob_ratio_phi_name.Data()).Data());
578 t_pid_glob_ratio_phi->SetConfidenceLevel(0.683);
579 t_pid_glob_ratio_phi->SetStatisticOption(TEfficiency::kBUniform);
580 t_pid_glob_ratio_phi->SetPosteriorMode();
582 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"Description",
583 TString::Format(
"Sample PDG = %s ; %s of ECL global PID(%i) > %.2f as a function of $\\phi_{cluster}$.",
588 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"Check",
589 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
590 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marcel Hohmann. mhohmann@student.unimelb.edu.au"));
591 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
593 t_pid_glob_ratio_phi->Write();
595 delete t_pid_glob_ratio_phi;
611 const int sampleCharge,
bool mergeSampleCharge)
615 const auto sampleHypoPdgId = sampleHypo.
getPDGCode();
618 TString h_pt_N_name = TString::Format(
"h_pt_N_%i", sampleHypoPdgId);
619 TString h_pt_D_name = TString::Format(
"h_pt_D_%i", sampleHypoPdgId);
620 TH1F* h_pt_N =
new TH1F(h_pt_N_name.Data(),
"h_pt_N", 10, 0.0, 5.0);
621 TH1F* h_pt_D =
new TH1F(h_pt_D_name.Data(),
"h_pt_D", 10, 0.0, 5.0);
623 TString h_th_N_name = TString::Format(
"h_th_N_%i", sampleHypoPdgId);
624 TString h_th_D_name = TString::Format(
"h_th_D_%i", sampleHypoPdgId);
628 TString h_phi_N_name = TString::Format(
"h_phi_N_%i", sampleHypoPdgId);
629 TString h_phi_D_name = TString::Format(
"h_phi_D_%i", sampleHypoPdgId);
630 TH1F* h_phi_N =
new TH1F(h_phi_N_name.Data(),
"h_phi_N", 5, -3.14159, 3.14159);
631 TH1F* h_phi_D =
new TH1F(h_phi_D_name.Data(),
"h_phi_D", 5, -3.14159, 3.14159);
633 TString match_cut_N(
"trackClusterMatch == 1");
634 TString match_cut_D(
"trackClusterMatch >= 0");
638 tree->Project(h_pt_N_name.Data(),
"pt", match_cut_N.Data());
639 tree->Project(h_pt_D_name.Data(),
"pt", match_cut_D.Data());
641 tree->Project(h_th_N_name.Data(),
"trkTheta", match_cut_N.Data());
642 tree->Project(h_th_D_name.Data(),
"trkTheta", match_cut_D.Data());
644 tree->Project(h_phi_N_name.Data(),
"trkPhi", match_cut_N.Data());
645 tree->Project(h_phi_D_name.Data(),
"trkPhi", match_cut_D.Data());
649 TString match_eff_pt_name = TString::Format(
"trkclusmatch_%i_Efficiency__VS_pt", sampleHypoPdgId);
650 TString match_eff_th_name = TString::Format(
"trkclusmatch_%i_Efficiency__VS_th", sampleHypoPdgId);
651 TString match_eff_phi_name = TString::Format(
"trkclusmatch_%i_Efficiency__VS_phi", sampleHypoPdgId);
654 std::string metaopts(
"pvalue-warn=0.01,pvalue-error=0.001,nostats");
655 std::string shifteropt(
"");
658 shifteropt =
"shifter,";
661 auto pdgIdDesc = (!mergeSampleCharge) ? std::to_string(sampleHypoPdgId * sampleCharge) : std::to_string(
662 sampleHypoPdgId) +
" and -" + std::to_string(sampleHypoPdgId);
664 if (TEfficiency::CheckConsistency(*h_pt_N, *h_pt_D)) {
666 TEfficiency* t_match_eff_pt =
new TEfficiency(*h_pt_N, *h_pt_D);
667 t_match_eff_pt->SetName(match_eff_pt_name.Data());
668 t_match_eff_pt->SetTitle(TString::Format(
"%s;p_{T}^{trk} [GeV/c];#varepsilon", match_eff_pt_name.Data()).Data());
669 t_match_eff_pt->SetTitle(match_eff_pt_name.Data());
671 t_match_eff_pt->SetConfidenceLevel(0.683);
672 t_match_eff_pt->SetStatisticOption(TEfficiency::kBUniform);
673 t_match_eff_pt->SetPosteriorMode();
675 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"Description",
676 TString::Format(
"Sample PDG = %s ; Efficiency of track-ECL-cluster matching as a function of $p_{T}^{trk}$.",
677 pdgIdDesc.c_str()).Data()));
678 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"Check",
679 "Shape should be consistent. Obviously, check for decreasing efficiency."));
680 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Priyanka Cheema. pche3675@uni.sydney.edu.au"));
681 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
683 t_match_eff_pt->Write();
685 delete t_match_eff_pt;
688 if (TEfficiency::CheckConsistency(*h_th_N, *h_th_D)) {
690 TEfficiency* t_match_eff_th =
new TEfficiency(*h_th_N, *h_th_D);
691 t_match_eff_th->SetName(match_eff_th_name.Data());
692 t_match_eff_th->SetTitle(TString::Format(
"%s;#theta_{trk} [rad];#varepsilon", match_eff_th_name.Data()).Data());
693 t_match_eff_th->SetTitle(match_eff_th_name.Data());
695 t_match_eff_th->SetConfidenceLevel(0.683);
696 t_match_eff_th->SetStatisticOption(TEfficiency::kBUniform);
697 t_match_eff_th->SetPosteriorMode();
699 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"Description",
700 TString::Format(
"Sample PDG = %s ; Efficiency of track-ECL-cluster matching as a function of $\\theta_{trk}$.",
701 pdgIdDesc.c_str()).Data()));
702 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"Check",
703 "Shape should be consistent. Obviously, check for decreasing efficiency."));
704 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Priyanka Cheema. pche3675@uni.sydney.edu.au"));
705 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
707 t_match_eff_th->Write();
709 delete t_match_eff_th;
712 if (TEfficiency::CheckConsistency(*h_phi_N, *h_phi_D)) {
714 TEfficiency* t_match_eff_phi =
new TEfficiency(*h_phi_N, *h_phi_D);
715 t_match_eff_phi->SetName(match_eff_phi_name.Data());
716 t_match_eff_phi->SetTitle(TString::Format(
"%s;#phi_{trk} [rad];#varepsilon", match_eff_phi_name.Data()).Data());
718 t_match_eff_phi->SetConfidenceLevel(0.683);
719 t_match_eff_phi->SetStatisticOption(TEfficiency::kBUniform);
720 t_match_eff_phi->SetPosteriorMode();
722 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"Description",
723 TString::Format(
"Sample PDG = %s ; Efficiency of track-ECL-cluster matching as a function of $\\phi_{trk}$.",
724 pdgIdDesc.c_str()).Data()));
725 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"Check",
726 "Shape should be consistent. Obviously, check for decreasing efficiency."));
727 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Priyanka Cheema. pche3675@uni.sydney.edu.au"));
728 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
730 t_match_eff_phi->Write();
732 delete t_match_eff_phi;
748 auto nentries = h->GetEntries();
749 auto nbins_vis = h->GetNbinsX();
752 float bin_vis_first = h->GetBinContent(1);
753 float bin_vis_last = h->GetBinContent(nbins_vis);
754 float bin_vis_first_err = h->GetBinError(1);
755 float bin_vis_last_err = h->GetBinError(nbins_vis);
758 float bin_uflow = h->GetBinContent(0);
759 float bin_oflow = h->GetBinContent(nbins_vis + 1);
760 float bin_uflow_err = h->GetBinError(0);
761 float bin_oflow_err = h->GetBinError(nbins_vis + 1);
764 h->SetBinContent(1, bin_vis_first + bin_uflow);
765 h->SetBinError(1,
sqrt(bin_vis_first_err * bin_vis_first_err + bin_uflow_err * bin_uflow_err));
766 h->SetBinContent(nbins_vis, bin_vis_last + bin_oflow);
767 h->SetBinError(nbins_vis,
sqrt(bin_vis_last_err * bin_vis_last_err + bin_oflow_err * bin_oflow_err));
770 h->SetEntries(nentries);
Provides a type-safe way to pass members of the chargedStableSet set.
static const unsigned int c_SetSize
Number of elements (for use in array bounds etc.)
const ParticleType & find(int pdg) const
Returns particle in set with given PDG code, or invalidParticle if not found.
int getPDGCode() const
PDG code.
int getIndex() const
This particle's index in the associated set.
static const ChargedStable muon
muon particle
static const ParticleSet chargedStableSet
set of charged stable particles
static const ChargedStable pion
charged pion particle
static const ChargedStable kaon
charged kaon particle
static const ChargedStable electron
electron particle
std::vector< float > m_trackClusterMatch
Flag for track-cluster matching condition.
ECLChargedPIDDataAnalysisValidationModule()
Constructor of the module.
bool isValidChargedPdg(const int pdg) const
Check if the input pdgId is that of a valid charged stable particle.
std::vector< float > m_th_binedges
Binning w/ variable bin size for track polar angle (in [rad]).
std::set< int > m_inputPdgIdSet
The pdgId set of the charged stable particles of interest.
virtual void initialize() override
Initializes the module.
virtual void event() override
Called once for each event.
std::vector< float > m_p
Track momentum in [GeV/c].
virtual void endRun() override
Called once when a run ends.
std::vector< float > m_deltalogl_sig_bkg
Delta Log-likelihood "signal" vs.
void paintUnderOverflow(TH1F *h)
Draw u/oflow content on top of first/last visible bin.
virtual void terminate() override
Termination action.
static constexpr float c_PID
Definition of the PID cut threshold to compute the efficiency.
std::vector< float > m_pt
Track transverse momentum in [GeV/c].
void dumpPIDEfficiencyFakeRate(TTree *sampleTree, const Const::ChargedStable &sampleHypo, const int sampleCharge, const Const::ChargedStable &sigHypo, bool mergeSampleCharge=false)
Dump PID efficiency / fake rate vs clusterTheta, clusterPhi, p... for a fixed cut on PID as previousl...
bool m_saveValidationTree
Save the TTree in the output file alongside the histograms.
std::vector< float > m_logl_bkg
Log-likelihood for the "background" particle hypothesis.
virtual void beginRun() override
Called once before a new run begins.
std::vector< float > m_clusterPhi
Cluster azimuthal angle in [rad].
std::vector< TFile * > m_outputFile
Output ROOT::TFile that contains the info to plot.
std::vector< float > m_clusterTheta
Cluster polar angle in [rad].
std::map< Const::ChargedStable, bool > m_mergeChargeFlagByHypo
A map to tell for each charged stable particle hypothesis whether particle and antiparticle should be...
std::vector< TTree * > m_tree
A ROOT::TTree filled with the info to make control plots.
std::vector< unsigned int > m_mergeChargeOfPdgIds
The (unsigned) pdgId list of the charged stable particles for which particle and antiparticle should ...
void dumpPIDVars(TTree *sampleTree, const Const::ChargedStable &sigHypo, const int sigCharge, const Const::ChargedStable &bkgHypo, bool mergeSigCharge=false)
Dump PID vars.
virtual ~ECLChargedPIDDataAnalysisValidationModule()
Destructor of the module.
std::vector< std::vector< float > > m_pids_glob
List of global PIDs, defined by the likelihood ratio:
std::vector< float > m_clusterReg
Cluster ECL region.
void dumpTrkClusMatchingEfficiency(TTree *sampleTree, const Const::ChargedStable &sampleHypo, const int sampleCharge, bool mergeSampleCharge=false)
Dump track-to-ECL-cluster matching efficiency vs clusterTheta, clusterPhi, pt....
StoreArray< MCParticle > m_MCParticles
MCParticles.
std::vector< float > m_trkPhi
Track azimuthal angle in [rad].
std::vector< float > m_trkTheta
Track polar angle in [rad].
std::vector< float > m_logl_sig
Log-likelihood for the "signal" particle hypothesis.
std::string m_outputFileName
Base name of the output ROOT::TFile.
std::vector< int > m_inputPdgIdList
The pdgId list of the charged stable particles of interest.
@ c_nPhotons
CR is split into n photons (N1)
Container for likelihoods with ECL PID (ECLChargedPIDModule)
double getLikelihood(const Const::ChargedStable &type) const
returns exp(getLogLikelihood(type)) with sufficient precision.
@ c_Initial
bit 5: Particle is initial such as e+ or e- and not going to Geant4
@ c_PrimaryParticle
bit 0: Particle is primary particle.
@ c_IsVirtual
bit 4: Particle is virtual and not going to Geant4.
void setDescription(const std::string &description)
Sets the description of the module.
Class that bundles various TrackFitResults.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
double sqrt(double a)
sqrt for double
std::vector< std::vector< double > > merge(std::vector< std::vector< std::vector< double > > > toMerge)
merge { vector<double> a, vector<double> b} into {a, b}
Abstract base class for different kinds of events.