1 #include <ecl/modules/eclChargedPIDDataAnalysisExpert/ECLChargedPIDDataAnalysisValidationModule.h>
3 #include <ecl/dataobjects/ECLPidLikelihood.h>
4 #include <framework/datastore/StoreArray.h>
5 #include <mdst/dataobjects/ECLCluster.h>
6 #include <mdst/dataobjects/MCParticle.h>
7 #include <mdst/dataobjects/Track.h>
9 #include <TEfficiency.h>
17 REG_MODULE(ECLChargedPIDDataAnalysisValidation)
26 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).");
29 std::vector<int> defaultChargedPdgIds;
31 defaultChargedPdgIds.push_back(hypo.getPDGCode());
32 defaultChargedPdgIds.push_back(-hypo.getPDGCode());
35 addParam(
"inputPdgIdList", m_inputPdgIdList,
36 "The list of (signed) pdgIds of the charged stable particles for which validation plots should be produced. Default is ALL charged stable particles.",
37 defaultChargedPdgIds);
38 addParam(
"mergeChargeOfPdgIds", m_mergeChargeOfPdgIds,
39 "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.",
40 std::vector<unsigned int>());
41 addParam(
"outputFileName", m_outputFileName,
42 "The base name of the output file. The pdgId of the charged particle is appended to the name.",
43 std::string(
"ECLChargedPid"));
44 addParam(
"saveValidationTree", m_saveValidationTree,
45 "If this flag is set to True, save also the validation TTree. Default is False.",
56 B2INFO(
"Initialising ROOT objects...");
67 B2WARNING(
"For (unsigned) hypothesis " << hypo.getPDGCode() <<
", validation plots will be merged for +/- charged particles.");
72 std::string chargedPdgIdStr;
78 if (!isValidChargedPdg(std::abs(chargedPdgId))) {
79 B2FATAL(
"PDG: " << chargedPdgId <<
" in m_inputPdgIdSet is not that of a valid particle in Const::chargedStableSet! Aborting...");
89 auto chargedIdx = chargedHypo.
getIndex();
91 if (chargedPdgId > 0) {
92 chargedPdgIdStr = std::to_string(chargedPdgId);
94 chargedPdgIdStr =
"anti" + std::to_string(std::abs(chargedPdgId));
101 m_outputFile[chargedIdx] =
new TFile(fname.c_str(),
"RECREATE");
103 m_tree[chargedIdx] =
new TTree(
"ECLChargedPid",
"ECLChargedPid");
104 m_tree[chargedIdx]->Branch(
"p", &
m_p[chargedIdx],
"p/F");
105 m_tree[chargedIdx]->Branch(
"pt", &
m_pt[chargedIdx],
"pt/F");
106 m_tree[chargedIdx]->Branch(
"trkTheta", &
m_trkTheta[chargedIdx],
"trkTheta/F");
107 m_tree[chargedIdx]->Branch(
"trkPhi", &
m_trkPhi[chargedIdx],
"trkPhi/F");
112 m_tree[chargedIdx]->Branch(
"logl_sig", &
m_logl_sig[chargedIdx],
"logl_sig/F");
113 m_tree[chargedIdx]->Branch(
"logl_bkg", &
m_logl_bkg[chargedIdx],
"logl_bkg/F");
115 m_tree[chargedIdx]->Branch(
"pids_glob", &m_pids_glob[chargedIdx]);
127 std::string chargedPdgIdStr;
138 auto chargedIdx = chargedHypo.
getIndex();
140 if (chargedPdgId < 0) {
146 m_p[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
147 m_pt[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
148 m_trkTheta[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
149 m_trkPhi[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
150 m_clusterTheta[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
151 m_clusterPhi[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
152 m_clusterReg[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
154 m_logl_sig[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
155 m_logl_bkg[chargedIdx] = std::numeric_limits<float>::quiet_NaN();
158 m_pids_glob[chargedIdx][chargedStable.getIndex()] = std::numeric_limits<float>::quiet_NaN();
163 for (
const auto& particle : particles) {
173 if (std::abs(particle.getPDG()) != std::abs(chargedPdgId))
continue;
176 if (particle.getPDG() != chargedPdgId)
continue;
182 double p_max(-999.0);
183 for (
const auto& track : particle.getRelationsFrom<
Track>()) {
184 const auto fitRes = track.getTrackFitResultWithClosestMass(
Const::pion);
185 if (!fitRes)
continue;
186 if (fitRes->getMomentum().Mag() > p_max) {
187 p_max = fitRes->getMomentum().Mag();
192 if (itrack_max < 0)
continue;
194 const auto track = particle.getRelationsFrom<
Track>()[itrack_max];
195 const auto fitRes = track->getTrackFitResultWithClosestMass(
Const::pion);
197 m_p[chargedIdx] = p_max;
198 m_pt[chargedIdx] = fitRes->get4Momentum().Pt();
199 m_trkTheta[chargedIdx] = fitRes->get4Momentum().Theta();
200 m_trkPhi[chargedIdx] = fitRes->get4Momentum().Phi();
203 int icluster_match(-1);
204 auto eclClusters = track->getRelationsTo<
ECLCluster>();
205 for (
unsigned int icluster(0); icluster < eclClusters.size(); ++icluster) {
206 const auto eclCluster = eclClusters[icluster];
208 if (!eclCluster->isTrack())
continue;
209 icluster_match = icluster;
213 if (icluster_match < 0) {
218 const auto eclCluster = eclClusters[icluster_match];
222 m_clusterReg[chargedIdx] = eclCluster->getDetectorRegion();
234 double lh_sig = eclLikelihood->getLikelihood(chargedStableSig);
235 double lh_bkg = eclLikelihood->getLikelihood(chargedStableBkg);
244 lh_all += eclLikelihood->getLikelihood(chargedStable);
247 m_pids_glob[chargedIdx][chargedStable.getIndex()] = eclLikelihood->getLikelihood(chargedStable) / lh_all;
252 m_tree[chargedIdx]->Fill();
272 if (mergeCharge && chargedPdgId < 0)
continue;
275 const auto chargeSign =
static_cast<int>(chargedPdgId / std::abs(chargedPdgId));
278 const auto chargedStableSig = chargedStableSample;
285 auto chargedSampleIdx = (chargeSign > 0) ? chargedStableSig.
getIndex() : chargedStableSig.getIndex() +
290 auto pdgIdDesc = (mergeCharge) ? std::to_string(chargedPdgId) +
" and -" + std::to_string(chargedPdgId) : std::to_string(
294 TNamed(
"Description", TString::Format(
"ECL Charged PID control plots for charged stable particles/antiparticles ; Sample PDG = %s",
295 pdgIdDesc.c_str()).Data()).Write();
298 dumpPIDVars(
m_tree[chargedSampleIdx], chargedStableSig, chargeSign, chargedStableBkg, mergeCharge);
300 dumpPIDEfficiencyFakeRate(
m_tree[chargedSampleIdx], chargedStableSample, chargeSign, chargedStableSig, mergeCharge);
303 dumpPIDEfficiencyFakeRate(
m_tree[chargedSampleIdx], chargedStableSample, chargeSign,
Const::electron, mergeCharge);
304 dumpPIDEfficiencyFakeRate(
m_tree[chargedSampleIdx], chargedStableSample, chargeSign,
Const::muon, mergeCharge);
307 dumpTrkClusMatchingEfficiency(
m_tree[chargedSampleIdx], chargedStableSample, chargeSign, mergeCharge);
311 m_tree[chargedSampleIdx]->Write();
319 void ECLChargedPIDDataAnalysisValidationModule::dumpPIDVars(TTree* sampleTree,
const Const::ChargedStable& sigHypo,
325 const auto sigHypoIdx = sigHypo.
getIndex();
326 const auto sigHypoPdgId = sigHypo.
getPDGCode();
329 const auto bkgHypoPdgId = bkgHypo.
getPDGCode();
333 TString pidSigBranch = TString::Format(
"pids_glob[%i]", sigHypoIdx);
336 TString h_pid_name = TString::Format(
"h_pid_sig_%i", sigHypoPdgId);
337 TH1F* h_pid =
new TH1F(h_pid_name.Data(), h_pid_name.Data(), 50, -0.5, 1.2);
338 h_pid->GetXaxis()->SetTitle(TString::Format(
"Likelihood ratio (%i/ALL) (ECL)", sigHypoPdgId).Data());
341 TString h_deltalogl_name = TString::Format(
"h_deltalogl_bkg_%i_sig_%i", bkgHypoPdgId, sigHypoPdgId);
342 double deltalogl_min = -20.0;
343 double deltalogl_max = 20.0;
344 TH1F* h_deltalogl =
new TH1F(h_deltalogl_name.Data(), h_deltalogl_name.Data(), 40, deltalogl_min, deltalogl_max);
345 h_deltalogl->GetXaxis()->SetTitle(TString::Format(
"#Deltaln(L) (%i/%i) (ECL)", bkgHypoPdgId, sigHypoPdgId).Data());
348 TString h_trkclusmatch_name = TString::Format(
"h_trkclusmatch_sig_%i", sigHypoPdgId);
349 TH1F* h_trkclusmatch =
new TH1F(h_trkclusmatch_name.Data(), h_trkclusmatch_name.Data(), 4, -1.5, 2.5);
350 h_trkclusmatch->GetXaxis()->SetTitle(TString::Format(
"Track-ECLCluster match (%i)", sigHypoPdgId).Data());
353 sampleTree->Project(h_pid_name.Data(), pidSigBranch.Data());
354 sampleTree->Project(h_deltalogl_name.Data(),
"deltalogl_sig_bkg");
355 sampleTree->Project(h_trkclusmatch_name.Data(),
"trackClusterMatch");
358 paintUnderOverflow(h_pid);
359 paintUnderOverflow(h_deltalogl);
360 paintUnderOverflow(h_trkclusmatch);
362 h_pid->SetOption(
"HIST");
363 h_deltalogl->SetOption(
"HIST");
364 h_trkclusmatch->SetOption(
"HIST");
367 std::string metaopts(
"pvalue-warn=0.1,pvalue-error=0.01");
368 std::string shifteropt(
"");
371 shifteropt =
"shifter,";
374 auto pdgIdDesc = (!mergeSigCharge) ? std::to_string(sigHypoPdgId * sigCharge) : std::to_string(
375 sigHypoPdgId) +
" and -" + std::to_string(sigHypoPdgId);
378 h_pid->GetListOfFunctions()->Add(
new TNamed(
"Description",
379 TString::Format(
"Sample PDG = %s ; ECL global PID(%i) distribution. U/O flow is added to first (last) bin.",
381 sigHypoPdgId).Data()));
382 h_pid->GetListOfFunctions()->Add(
new TNamed(
"Check",
383 "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."));
384 h_pid->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marco Milesi. marco.milesi@desy.de"));
385 h_pid->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
387 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"Description",
388 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.",
391 sigHypoPdgId).Data()));
392 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"Check",
393 "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)."));
394 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marco Milesi. marco.milesi@desy.de"));
395 h_deltalogl->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
397 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"Description",
398 TString::Format(
"Sample PDG = %s ; Track-ECLCluster match flag distribution.",
399 pdgIdDesc.c_str()).Data()));
400 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"Check",
401 "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."));
402 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Frank Meier. frank.meier@desy.de"));
403 h_trkclusmatch->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", metaopts.c_str()));
406 h_deltalogl->Write();
407 h_trkclusmatch->Write();
411 delete h_trkclusmatch;
416 void ECLChargedPIDDataAnalysisValidationModule::dumpPIDEfficiencyFakeRate(TTree* sampleTree,
const Const::ChargedStable& sampleHypo,
421 const std::string ratioType = (sampleHypo == sigHypo) ?
"Efficiency" :
"FakeRate";
424 const int sampleHypoPdgId = sampleHypo.
getPDGCode() * sampleCharge;
427 const auto sigHypoIdx = sigHypo.
getIndex();
428 const auto sigHypoPdgId = sigHypo.
getPDGCode();
432 TString pidSigCut = TString::Format(
"pids_glob[%i] > %f", sigHypoIdx,
c_PID);
435 TString h_p_N_name = TString::Format(
"h_p_N_%i", sigHypoPdgId);
436 TString h_p_D_name = TString::Format(
"h_p_D_%i", sigHypoPdgId);
437 TH1F* h_p_N =
new TH1F(h_p_N_name.Data(),
"h_p_N", 10, 0.0, 5.0);
438 TH1F* h_p_D =
new TH1F(h_p_D_name.Data(),
"h_p_D", 10, 0.0, 5.0);
440 TString h_th_N_name = TString::Format(
"h_th_N_%i", sigHypoPdgId);
441 TString h_th_D_name = TString::Format(
"h_th_D_%i", sigHypoPdgId);
442 TH1F* h_th_N =
new TH1F(h_th_N_name.Data(),
"h_th_N", m_th_binedges.size() - 1, m_th_binedges.data());
443 TH1F* h_th_D =
new TH1F(h_th_D_name.Data(),
"h_th_D", m_th_binedges.size() - 1, m_th_binedges.data());
445 TString h_eclreg_N_name = TString::Format(
"h_eclreg_N_%i", sigHypoPdgId);
446 TString h_eclreg_D_name = TString::Format(
"h_eclreg_D_%i", sigHypoPdgId);
447 TH1F* h_eclreg_N =
new TH1F(h_eclreg_N_name.Data(),
"h_eclreg_N", 5, -0.5, 4.5);
448 TH1F* h_eclreg_D =
new TH1F(h_eclreg_D_name.Data(),
"h_eclreg_D", 5, -0.5, 4.5);
450 TString h_phi_N_name = TString::Format(
"h_phi_N_%i", sigHypoPdgId);
451 TString h_phi_D_name = TString::Format(
"h_phi_D_%i", sigHypoPdgId);
452 TH1F* h_phi_N =
new TH1F(h_phi_N_name.Data(),
"h_phi_N", 5, -3.14159, 3.14159);
453 TH1F* h_phi_D =
new TH1F(h_phi_D_name.Data(),
"h_phi_D", 5, -3.14159, 3.14159);
457 sampleTree->Project(h_p_N_name.Data(),
"p", pidSigCut.Data());
458 sampleTree->Project(h_p_D_name.Data(),
"p");
460 sampleTree->Project(h_th_N_name.Data(),
"clusterTheta", pidSigCut.Data());
461 sampleTree->Project(h_th_D_name.Data(),
"clusterTheta");
463 sampleTree->Project(h_eclreg_N_name.Data(),
"clusterReg", pidSigCut.Data());
464 sampleTree->Project(h_eclreg_D_name.Data(),
"clusterReg");
465 paintUnderOverflow(h_eclreg_N);
466 paintUnderOverflow(h_eclreg_D);
468 sampleTree->Project(h_phi_N_name.Data(),
"clusterPhi", pidSigCut.Data());
469 sampleTree->Project(h_phi_D_name.Data(),
"clusterPhi");
473 TString pid_glob_ratio_p_name = TString::Format(
"pid_glob_%i_%s__VS_p", sigHypoPdgId, ratioType.c_str());
474 TString pid_glob_ratio_th_name = TString::Format(
"pid_glob_%i_%s__VS_th", sigHypoPdgId, ratioType.c_str());
475 TString pid_glob_ratio_eclreg_name = TString::Format(
"pid_glob_%i_%s__VS_eclreg", sigHypoPdgId, ratioType.c_str());
476 TString pid_glob_ratio_phi_name = TString::Format(
"pid_glob_%i_%s__VS_phi", sigHypoPdgId, ratioType.c_str());
479 std::string metaopts(
"pvalue-warn=0.01,pvalue-error=0.001,nostats");
480 std::string shifteropt(
"");
483 shifteropt =
"shifter,";
486 auto pdgIdDesc = (!mergeSampleCharge) ? std::to_string(sampleHypoPdgId) : std::to_string(std::abs(
487 sampleHypoPdgId)) +
" and -" + std::to_string(std::abs(sampleHypoPdgId));
489 if (TEfficiency::CheckConsistency(*h_p_N, *h_p_D)) {
491 TEfficiency* t_pid_glob_ratio_p =
new TEfficiency(*h_p_N, *h_p_D);
492 t_pid_glob_ratio_p->SetName(pid_glob_ratio_p_name.Data());
493 t_pid_glob_ratio_p->SetTitle(TString::Format(
"%s;p [GeV/c];#varepsilon/f", pid_glob_ratio_p_name.Data()).Data());
495 t_pid_glob_ratio_p->SetConfidenceLevel(0.683);
496 t_pid_glob_ratio_p->SetStatisticOption(TEfficiency::kBUniform);
497 t_pid_glob_ratio_p->SetPosteriorMode();
499 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"Description",
500 TString::Format(
"Sample PDG = %s ; %s of ECL global PID(%i) > %.2f as a function of $p_{trk}$.",
505 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"Check",
506 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
507 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marco Milesi. marco.milesi@desy.de"));
508 t_pid_glob_ratio_p->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
510 t_pid_glob_ratio_p->Write();
512 delete t_pid_glob_ratio_p;
515 if (TEfficiency::CheckConsistency(*h_th_N, *h_th_D)) {
517 TEfficiency* t_pid_glob_ratio_th =
new TEfficiency(*h_th_N, *h_th_D);
518 t_pid_glob_ratio_th->SetName(pid_glob_ratio_th_name.Data());
519 t_pid_glob_ratio_th->SetTitle(TString::Format(
"%s;#theta_{cluster} [rad];#varepsilon/f", pid_glob_ratio_th_name.Data()).Data());
521 t_pid_glob_ratio_th->SetConfidenceLevel(0.683);
522 t_pid_glob_ratio_th->SetStatisticOption(TEfficiency::kBUniform);
523 t_pid_glob_ratio_th->SetPosteriorMode();
525 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"Description",
526 TString::Format(
"Sample PDG = %s ; %s of ECL global PID(%i) > %.2f as a function of $\\theta_{cluster}$.",
531 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"Check",
532 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
533 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marco Milesi. marco.milesi@desy.de"));
534 t_pid_glob_ratio_th->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
536 t_pid_glob_ratio_th->Write();
538 delete t_pid_glob_ratio_th;
540 if (TEfficiency::CheckConsistency(*h_eclreg_N, *h_eclreg_D)) {
542 TEfficiency* t_pid_glob_ratio_eclreg =
new TEfficiency(*h_eclreg_N, *h_eclreg_D);
543 t_pid_glob_ratio_eclreg->SetName(pid_glob_ratio_eclreg_name.Data());
544 t_pid_glob_ratio_eclreg->SetTitle(TString::Format(
"%s;ECL Region;#varepsilon/f", pid_glob_ratio_eclreg_name.Data()).Data());
546 t_pid_glob_ratio_eclreg->SetConfidenceLevel(0.683);
547 t_pid_glob_ratio_eclreg->SetStatisticOption(TEfficiency::kBUniform);
548 t_pid_glob_ratio_eclreg->SetPosteriorMode();
550 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"Description",
551 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).",
556 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"Check",
557 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
558 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marco Milesi. marco.milesi@desy.de"));
559 t_pid_glob_ratio_eclreg->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", metaopts.c_str()));
561 t_pid_glob_ratio_eclreg->Write();
563 delete t_pid_glob_ratio_eclreg;
566 if (TEfficiency::CheckConsistency(*h_phi_N, *h_phi_D)) {
568 TEfficiency* t_pid_glob_ratio_phi =
new TEfficiency(*h_phi_N, *h_phi_D);
569 t_pid_glob_ratio_phi->SetName(pid_glob_ratio_phi_name.Data());
570 t_pid_glob_ratio_phi->SetTitle(TString::Format(
"%s;#phi_{cluster} [rad];#varepsilon/f", pid_glob_ratio_phi_name.Data()).Data());
572 t_pid_glob_ratio_phi->SetConfidenceLevel(0.683);
573 t_pid_glob_ratio_phi->SetStatisticOption(TEfficiency::kBUniform);
574 t_pid_glob_ratio_phi->SetPosteriorMode();
576 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"Description",
577 TString::Format(
"Sample PDG = %s ; %s of ECL global PID(%i) > %.2f as a function of $\\phi_{cluster}$.",
582 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"Check",
583 "Shape should be consistent. Obviously, check for decreasing efficiency / increasing fake rate."));
584 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Marco Milesi. marco.milesi@desy.de"));
585 t_pid_glob_ratio_phi->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
587 t_pid_glob_ratio_phi->Write();
589 delete t_pid_glob_ratio_phi;
604 void ECLChargedPIDDataAnalysisValidationModule::dumpTrkClusMatchingEfficiency(TTree* tree,
const Const::ChargedStable& sampleHypo,
605 const int sampleCharge,
bool mergeSampleCharge)
609 const auto sampleHypoPdgId = sampleHypo.
getPDGCode();
612 TString h_pt_N_name = TString::Format(
"h_pt_N_%i", sampleHypoPdgId);
613 TString h_pt_D_name = TString::Format(
"h_pt_D_%i", sampleHypoPdgId);
614 TH1F* h_pt_N =
new TH1F(h_pt_N_name.Data(),
"h_pt_N", 10, 0.0, 5.0);
615 TH1F* h_pt_D =
new TH1F(h_pt_D_name.Data(),
"h_pt_D", 10, 0.0, 5.0);
617 TString h_th_N_name = TString::Format(
"h_th_N_%i", sampleHypoPdgId);
618 TString h_th_D_name = TString::Format(
"h_th_D_%i", sampleHypoPdgId);
619 TH1F* h_th_N =
new TH1F(h_th_N_name.Data(),
"h_th_N", m_th_binedges.size() - 1, m_th_binedges.data());
620 TH1F* h_th_D =
new TH1F(h_th_D_name.Data(),
"h_th_D", m_th_binedges.size() - 1, m_th_binedges.data());
622 TString h_phi_N_name = TString::Format(
"h_phi_N_%i", sampleHypoPdgId);
623 TString h_phi_D_name = TString::Format(
"h_phi_D_%i", sampleHypoPdgId);
624 TH1F* h_phi_N =
new TH1F(h_phi_N_name.Data(),
"h_phi_N", 5, -3.14159, 3.14159);
625 TH1F* h_phi_D =
new TH1F(h_phi_D_name.Data(),
"h_phi_D", 5, -3.14159, 3.14159);
627 TString match_cut_N(
"trackClusterMatch == 1");
628 TString match_cut_D(
"trackClusterMatch >= 0");
632 tree->Project(h_pt_N_name.Data(),
"pt", match_cut_N.Data());
633 tree->Project(h_pt_D_name.Data(),
"pt", match_cut_D.Data());
635 tree->Project(h_th_N_name.Data(),
"trkTheta", match_cut_N.Data());
636 tree->Project(h_th_D_name.Data(),
"trkTheta", match_cut_D.Data());
638 tree->Project(h_phi_N_name.Data(),
"trkPhi", match_cut_N.Data());
639 tree->Project(h_phi_D_name.Data(),
"trkPhi", match_cut_D.Data());
643 TString match_eff_pt_name = TString::Format(
"trkclusmatch_%i_Efficiency__VS_pt", sampleHypoPdgId);
644 TString match_eff_th_name = TString::Format(
"trkclusmatch_%i_Efficiency__VS_th", sampleHypoPdgId);
645 TString match_eff_phi_name = TString::Format(
"trkclusmatch_%i_Efficiency__VS_phi", sampleHypoPdgId);
648 std::string metaopts(
"pvalue-warn=0.01,pvalue-error=0.001,nostats");
649 std::string shifteropt(
"");
652 shifteropt =
"shifter,";
655 auto pdgIdDesc = (!mergeSampleCharge) ? std::to_string(sampleHypoPdgId * sampleCharge) : std::to_string(
656 sampleHypoPdgId) +
" and -" + std::to_string(sampleHypoPdgId);
658 if (TEfficiency::CheckConsistency(*h_pt_N, *h_pt_D)) {
660 TEfficiency* t_match_eff_pt =
new TEfficiency(*h_pt_N, *h_pt_D);
661 t_match_eff_pt->SetName(match_eff_pt_name.Data());
662 t_match_eff_pt->SetTitle(TString::Format(
"%s;p_{T}^{trk} [GeV/c];#varepsilon", match_eff_pt_name.Data()).Data());
663 t_match_eff_pt->SetTitle(match_eff_pt_name.Data());
665 t_match_eff_pt->SetConfidenceLevel(0.683);
666 t_match_eff_pt->SetStatisticOption(TEfficiency::kBUniform);
667 t_match_eff_pt->SetPosteriorMode();
669 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"Description",
670 TString::Format(
"Sample PDG = %s ; Efficiency of track-ECL-cluster matching as a function of $p_{T}^{trk}$.",
671 pdgIdDesc.c_str()).Data()));
672 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"Check",
673 "Shape should be consistent. Obviously, check for decreasing efficiency."));
674 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Frank Meier. frank.meier@desy.de"));
675 t_match_eff_pt->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
677 t_match_eff_pt->Write();
679 delete t_match_eff_pt;
682 if (TEfficiency::CheckConsistency(*h_th_N, *h_th_D)) {
684 TEfficiency* t_match_eff_th =
new TEfficiency(*h_th_N, *h_th_D);
685 t_match_eff_th->SetName(match_eff_th_name.Data());
686 t_match_eff_th->SetTitle(TString::Format(
"%s;#theta_{trk} [rad];#varepsilon", match_eff_th_name.Data()).Data());
687 t_match_eff_th->SetTitle(match_eff_th_name.Data());
689 t_match_eff_th->SetConfidenceLevel(0.683);
690 t_match_eff_th->SetStatisticOption(TEfficiency::kBUniform);
691 t_match_eff_th->SetPosteriorMode();
693 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"Description",
694 TString::Format(
"Sample PDG = %s ; Efficiency of track-ECL-cluster matching as a function of $\\theta_{trk}$.",
695 pdgIdDesc.c_str()).Data()));
696 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"Check",
697 "Shape should be consistent. Obviously, check for decreasing efficiency."));
698 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Frank Meier. frank.meier@desy.de"));
699 t_match_eff_th->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
701 t_match_eff_th->Write();
703 delete t_match_eff_th;
706 if (TEfficiency::CheckConsistency(*h_phi_N, *h_phi_D)) {
708 TEfficiency* t_match_eff_phi =
new TEfficiency(*h_phi_N, *h_phi_D);
709 t_match_eff_phi->SetName(match_eff_phi_name.Data());
710 t_match_eff_phi->SetTitle(TString::Format(
"%s;#phi_{trk} [rad];#varepsilon", match_eff_phi_name.Data()).Data());
712 t_match_eff_phi->SetConfidenceLevel(0.683);
713 t_match_eff_phi->SetStatisticOption(TEfficiency::kBUniform);
714 t_match_eff_phi->SetPosteriorMode();
716 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"Description",
717 TString::Format(
"Sample PDG = %s ; Efficiency of track-ECL-cluster matching as a function of $\\phi_{trk}$.",
718 pdgIdDesc.c_str()).Data()));
719 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"Check",
720 "Shape should be consistent. Obviously, check for decreasing efficiency."));
721 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"Contact",
"Frank Meier. frank.meier@desy.de"));
722 t_match_eff_phi->GetListOfFunctions()->Add(
new TNamed(
"MetaOptions", (shifteropt + metaopts).c_str()));
724 t_match_eff_phi->Write();
726 delete t_match_eff_phi;
739 void ECLChargedPIDDataAnalysisValidationModule::paintUnderOverflow(TH1F* h)
742 auto nentries = h->GetEntries();
743 auto nbins_vis = h->GetNbinsX();
746 float bin_vis_first = h->GetBinContent(1);
747 float bin_vis_last = h->GetBinContent(nbins_vis);
748 float bin_vis_first_err = h->GetBinError(1);
749 float bin_vis_last_err = h->GetBinError(nbins_vis);
752 float bin_uflow = h->GetBinContent(0);
753 float bin_oflow = h->GetBinContent(nbins_vis + 1);
754 float bin_uflow_err = h->GetBinError(0);
755 float bin_oflow_err = h->GetBinError(nbins_vis + 1);
758 h->SetBinContent(1, bin_vis_first + bin_uflow);
759 h->SetBinError(1, sqrt(bin_vis_first_err * bin_vis_first_err + bin_uflow_err * bin_uflow_err));
760 h->SetBinContent(nbins_vis, bin_vis_last + bin_oflow);
761 h->SetBinError(nbins_vis, sqrt(bin_vis_last_err * bin_vis_last_err + bin_oflow_err * bin_oflow_err));
764 h->SetEntries(nentries);