Belle II Software  release-08-01-10
V0findingPerformanceEvaluationModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <tracking/modules/trackingPerformanceEvaluation/V0findingPerformanceEvaluationModule.h>
10 
11 #include <tracking/dataobjects/MCParticleInfo.h>
12 
13 #include <framework/datastore/StoreArray.h>
14 #include <framework/datastore/RelationVector.h>
15 
16 #include <mdst/dataobjects/Track.h>
17 
18 #include <framework/gearbox/Const.h>
19 
20 #include <framework/geometry/BFieldManager.h>
21 
22 #include <root/TAxis.h>
23 #include <root/TObject.h>
24 
25 #include <vector>
26 
27 using namespace Belle2;
28 
29 //-----------------------------------------------------------------
30 // Register the Module
31 //-----------------------------------------------------------------
32 REG_MODULE(V0findingPerformanceEvaluation);
33 
35  Module()
36 {
37 
38  setDescription("This module evaluates the V0 finding package performance");
39 
40  addParam("outputFileName", m_rootFileName, "Name of output root file.",
41  std::string("V0findingPerformanceEvaluation_output.root"));
42  addParam("V0sName", m_V0sName, "Name of V0 collection.", std::string("V0ValidationVertexs"));
43  addParam("MCParticlesName", m_MCParticlesName, "Name of MC Particle collection.", std::string(""));
44 
45 }
46 
48 {
49 
50 }
51 
53 {
56 
57  //create list of histograms to be saved in the rootfile
58  m_histoList = new TList;
59  m_histoList_multiplicity = new TList;
60  m_histoList_efficiency = new TList;
61  m_histoList_purity = new TList;
62  m_histoList_trkQuality = new TList;
63 
64  //set the ROOT File
65  m_rootFilePtr = new TFile(m_rootFileName.c_str(), "RECREATE");
66 
67  //now create histograms
68 
69  //multiplicity histograms
70  m_multiplicityV0s = createHistogram1D("h1nV0", "number of V0s per MC Particle", 8, -0.5, 7.5, "# V0s", m_histoList_multiplicity);
71 
72  m_multiplicityMCParticles = createHistogram1D("h1nMCPrtcl", "number of MCParticles per V0s", 5, -0.5, 4.5,
73  "# MCParticles", m_histoList_multiplicity);
74 
75  m_MCParticlePDGcode = createHistogram1D("h1PDGcode", "PDG code of MCParticles", 6244, Const::antiLambda.getPDGCode(),
76  Const::Lambda.getPDGCode(),
77  "PDG code", m_histoList_multiplicity);
78 
79 
80  //vertex and momentum parameters errors
81  m_h1_vtxX_err = createHistogram1D("h1vtxXerr", "vtxX error", 100, 0, 0.1, "#sigma_{vtxX} (cm)", m_histoList);
82  m_h1_vtxY_err = createHistogram1D("h1vtxYerr", "vtxY error", 100, 0, 0.1, "#sigma_{vtxY} (cm)", m_histoList);
83  m_h1_vtxZ_err = createHistogram1D("h1vtxZerr", "vtxZ error", 100, 0, 0.3, "#sigma_{vtxZ} (cm)", m_histoList);
84  m_h2_vtxTvsR_err = createHistogram2D("h2vtxTerrVsR", "vtxT error vs R", 100, 0, 100, "R (cm)", 100, 0, 0.3, "#sigma_{vtxT} (cm)",
85  m_histoList);
86  // m_h1_mom_err = createHistogram1D("h1momerr", "mom error", 100, 0, 0.1, "#sigma_{p} (GeV/c)", m_histoList);
87  // m_h1_mass_err = createHistogram1D("h1masserr", "mass error", 100, 0, 1, "#sigma_{m} (GeV/c2)", m_histoList);
88  //vertex and momentum parameters residuals
89  m_h1_vtxX_res = createHistogram1D("h1vtxXres", "vtxX resid", 100, -0.2, 0.2, "vtxX resid (cm)", m_histoList);
90  m_h1_vtxY_res = createHistogram1D("h1vtxYres", "vtxY resid", 100, -0.2, 0.2, "vtxY resid (cm)", m_histoList);
91  m_h1_vtxZ_res = createHistogram1D("h1vtxZres", "vtxZ resid", 100, -0.5, 0.5, "vtxZ resid (cm)", m_histoList);
92  m_h1_mom_res = createHistogram1D("h1momres", "mom resid", 1000, -0.5, 0.5, "mom resid (GeV/c)", m_histoList);
93  m_h1_mass_res = createHistogram1D("h1massres", "mass resid", 500, -0.3, 0.3, "mass resid (GeV/c)", m_histoList);
94 
95  //vertex and momentum parameters pulls
96  m_h1_vtxX_pll = createHistogram1D("h1vtxXpll", "vtxX pull", 100, -5, 5, "vtxX pull", m_histoList);
97  m_h1_vtxY_pll = createHistogram1D("h1vtxYpll", "vtxY pull", 100, -5, 5, "vtxY pull", m_histoList);
98  m_h1_vtxZ_pll = createHistogram1D("h1vtxZpll", "vtxZ pull", 100, -5, 5, "vtxZ pull", m_histoList);
99  // m_h1_mom_pll = createHistogram1D("h1mompll", "mom pull", 100, -5, 5, "momX pull", m_histoList);
100  // m_h1_mass_pll = createHistogram1D("h1masspll", "mass pull", 100, -5, 5, "momY pull", m_histoList);
101 
102 
103  m_h1_ChiSquare = createHistogram1D("h1Chi2", "Chi2 of the fit", 100, 0, 20, "Chi2", m_histoList_trkQuality);
104 
105  m_h1_nMatchedDau = createHistogram1D("h1nMatchedDau", "Number of Matched MCParticle Daughters", 3, -0.5, 2.5, "# matched dau",
106  m_histoList);
107 
108 
109  m_h2_mom = createHistogram2D("h2mom", "reco VS true momentum", 100, 0, 3, "V0 mom (GeV/c)", 100, 0, 3, "MC mom (GeV/c)",
110  m_histoList);
111  m_h2_mass = createHistogram2D("h2mass", "reco VS true mass", 100, 0, 1.5, "V0 mass (GeV/c2)", 100, 0, 1.5, "MC mass (GeV/c)",
112  m_histoList);
113 
114  //histograms to produce efficiency plots
115  Double_t bins_pt[9 + 1] = {0, 0.05, 0.1, 0.15, 0.2, 0.3, 0.5, 1, 2, 3.5}; //GeV/c
116  Double_t bins_theta[10 + 1] = {0, 0.25, 0.5, 0.75, 0.75 + 0.32, 0.75 + 2 * 0.32, 0.75 + 3 * 0.32, 0.75 + 4 * 0.32, 0.75 + 5 * 0.32, 2.65, M_PI};
117  Double_t bins_phi[14 + 1];
118  Double_t width_phi = 2 * M_PI / 14;
119  for (int bin = 0; bin < 14 + 1; bin++)
120  bins_phi[bin] = - M_PI + bin * width_phi;
121 
122  m_h1_MCParticle_R = createHistogram1D("h1nMCParticleVSr", "entry per MCParticles", 50, 0, 20, "transverse L", m_histoList);
123 
124  m_h1_V0sPerMCParticle_R = (TH1F*)duplicateHistogram("h1nV0perMCvsR", "entry per V0 related to a MCParticle", m_h1_MCParticle_R,
125  m_histoList);
126 
127 
128  m_h3_MCParticle = createHistogram3D("h3MCParticle", "entry per MCParticle",
129  9, bins_pt, "p_{t} (GeV/c)",
130  10, bins_theta, "#theta",
131  14, bins_phi, "#phi" /*, m_histoList*/);
132 
133  m_h3_V0sPerMCParticle = (TH3F*)duplicateHistogram("h3V0sPerMCParticle",
134  "entry per V0 connected to a MCParticle",
135  m_h3_MCParticle /*, m_histoList*/);
136 
137  m_h3_V0s = (TH3F*)duplicateHistogram("h3V0s", "entry per V0",
138  m_h3_MCParticle /*, m_histoList*/);
139 
140  //histograms to produce purity plots
141  m_h3_MCParticlesPerV0 = (TH3F*)duplicateHistogram("h3MCParticlesPerV0",
142  "entry per MCParticle connected to a V0",
143  m_h3_MCParticle /*, m_histoList*/);
144 }
145 
147 {
148 
149 }
150 
152 {
153 
154  ROOT::Math::XYZVector magField = BFieldManager::getField(0, 0, 0) / Unit::T;
155 
156  B2DEBUG(29, "+++++ 1. loop on MCParticles");
157  for (const MCParticle& mcParticle : m_MCParticles) {
158 
159  if (! isV0(mcParticle))
160  continue;
161 
162  int nMatchedDau = nMatchedDaughters(mcParticle);
163  m_h1_nMatchedDau->Fill(nMatchedDau);
164 
165  //proceed only in case the MCParticle daughters have both one associated reconstructed track:
166  if (nMatchedDau != 2)
167  continue;
168 
169  int pdgCode = mcParticle.getPDG();
170  B2DEBUG(29, "MCParticle has PDG code " << pdgCode);
171  m_MCParticlePDGcode->Fill(mcParticle.getPDG());
172 
173  MCParticleInfo mcParticleInfo(mcParticle, magField);
174 
175  ROOT::Math::XYZVector MC_prodvtx = mcParticle.getVertex();
176  ROOT::Math::XYZVector MC_vtx = mcParticle.getDecayVertex();
177  float MC_mom = mcParticle.getMomentum().R();
178  float MC_mass = mcParticle.getMass();
179  ROOT::Math::XYZVector MC_FL = MC_vtx - MC_prodvtx;
180  float flightR = sqrt(MC_FL.X() * MC_FL.X() + MC_FL.Y() * MC_FL.Y());
181  m_h1_MCParticle_R->Fill(flightR);
182 
183  m_h3_MCParticle->Fill(mcParticleInfo.getPt(), mcParticleInfo.getPtheta(), mcParticleInfo.getPphi());
184 
185  //1. retrieve all the V0s related to the MCParticle
186 
187  //1.0 check if there is a V0
188  RelationVector<V0ValidationVertex> V0s_toMCParticle =
189  DataStore::getRelationsWithObj<V0ValidationVertex>(&mcParticle, m_V0sName);
190 
191  m_multiplicityV0s->Fill(V0s_toMCParticle.size());
192 
193  if (V0s_toMCParticle.size() > 0)
194  m_h3_V0sPerMCParticle->Fill(mcParticleInfo.getPt(), mcParticleInfo.getPtheta(), mcParticleInfo.getPphi());
195 
196  for (int v0 = 0; v0 < (int)V0s_toMCParticle.size(); v0++) {
197 
198  ROOT::Math::XYZVector V0_vtx = V0s_toMCParticle[v0]->getVertexPosition();
199  float V0_mom = V0s_toMCParticle[v0]->getFittedMomentum();
200  float V0_chi2 = V0s_toMCParticle[v0]->getVertexChi2();
201  float V0_mass = V0s_toMCParticle[v0]->getFittedInvariantMass();
202  TMatrixDSym V0_cov = V0s_toMCParticle[v0]->getVertexPositionCovariance();
203 
204  m_h1_vtxX_err->Fill(sqrt(V0_cov[0][0]));
205  m_h1_vtxY_err->Fill(sqrt(V0_cov[1][1]));
206  m_h1_vtxZ_err->Fill(sqrt(V0_cov[2][2]));
207  m_h2_vtxTvsR_err->Fill(flightR, sqrt(V0_cov[0][0] + V0_cov[1][1]));
208 
209  m_h1_V0sPerMCParticle_R->Fill(flightR);
210 
211  m_h1_vtxX_res->Fill(V0_vtx.X() - MC_vtx.X());
212  m_h1_vtxY_res->Fill(V0_vtx.Y() - MC_vtx.Y());
213  m_h1_vtxZ_res->Fill(V0_vtx.Z() - MC_vtx.Z());
214 
215  m_h1_mom_res->Fill(V0_mom - MC_mom);
216  m_h2_mom->Fill(V0_mom, MC_mom);
217  m_h1_mass_res->Fill(V0_mass - MC_mass);
218  m_h2_mass->Fill(V0_mass, MC_mass);
219 
220  m_h1_vtxX_pll->Fill((V0_vtx.X() - MC_vtx.X()) / sqrt(V0_cov[0][0]));
221  m_h1_vtxY_pll->Fill((V0_vtx.Y() - MC_vtx.Y()) / sqrt(V0_cov[1][1]));
222  m_h1_vtxZ_pll->Fill((V0_vtx.Z() - MC_vtx.Z()) / sqrt(V0_cov[2][2]));
223 
224  m_h1_ChiSquare->Fill(V0_chi2);
225 
226  }
227 
228 
229  }
230 
231 
232  B2DEBUG(29, "+++++ 2. loop on V0s");
233 
234  for (const V0ValidationVertex& v0 : m_V0ValidationVertices) {
235 
236  int nMCParticles = 0;
237 
238  // m_h3_V0s>Fill(mcParticleInfo.getPt(), mcParticleInfo.getPtheta(), mcParticleInfo.getPphi());
239  //2. retrieve all the MCParticles related to the V0s
240  RelationVector<MCParticle> MCParticles_fromV0 =
241  DataStore::getRelationsWithObj<MCParticle>(&v0, m_MCParticlesName);
242 
243  nMCParticles = MCParticles_fromV0.size();
244 
245  if (nMCParticles == 0)
246  continue;
247 
248  MCParticleInfo mcParticleInfo(* MCParticles_fromV0[0], magField);
249  m_h3_MCParticlesPerV0->Fill(mcParticleInfo.getPt(), mcParticleInfo.getPtheta(), mcParticleInfo.getPphi());
250  m_multiplicityMCParticles->Fill(nMCParticles);
251 
252  }
253 
254 }
255 
257 {
258 
259  double num = 0;
260  double den = 0;
261 
262  for (int bin = 1; bin < m_multiplicityV0s->GetNbinsX(); bin ++)
263  num += m_multiplicityV0s->GetBinContent(bin + 1);
264  den = m_multiplicityV0s->GetEntries();
265  double efficiency = num / den ;
266  double efficiencyErr = sqrt(efficiency * (1 - efficiency)) / sqrt(den);
267 
268  double nMCParticles = 0;
269  for (int bin = 1; bin < m_multiplicityMCParticles->GetNbinsX(); bin ++)
270  nMCParticles += m_multiplicityMCParticles->GetBinContent(bin + 1);
271  double purity = nMCParticles / m_multiplicityMCParticles->GetEntries();
272  double purityErr = sqrt(purity * (1 - purity)) / sqrt(m_multiplicityMCParticles->GetEntries());
273 
274  B2INFO("");
275  B2INFO("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
276  B2INFO("~ V0 Finding Performance Evaluation ~ SHORT SUMMARY ~");
277  B2INFO("");
278  B2INFO(" + overall:");
279  B2INFO(" efficiency = (" << efficiency * 100 << " +/- " << efficiencyErr * 100 << ")% ");
280  B2INFO(" purity = (" << purity * 100 << " +/- " << purityErr * 100 << ")% ");
281  B2INFO("");
282  B2INFO("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
283 }
284 
286 {
287 
288  TH1F* h_eff_R = (TH1F*)duplicateHistogram("h_eff_R", "efficiency vs R", m_h1_MCParticle_R, m_histoList_efficiency);
289 
290  for (int bin = 0; bin < h_eff_R->GetXaxis()->GetNbins(); bin++) {
291  float num = m_h1_V0sPerMCParticle_R->GetBinContent(bin + 1);
292  float den = m_h1_MCParticle_R->GetBinContent(bin + 1);
293  double eff = 0;
294  double err = 0;
295 
296  if (den > 0) {
297  eff = (double)num / den;
298  err = sqrt(eff * (1 - eff)) / sqrt(den);
299  }
300 
301  h_eff_R->SetBinContent(bin + 1, eff);
302  h_eff_R->SetBinError(bin + 1, err);
303  }
304 
306 
308 
309  // addPurityPlots(m_histoList_purity, m_h3_MCParticlesPerV0, m_h3_V0s);
310 
311  if (m_rootFilePtr != nullptr) {
312  m_rootFilePtr->cd();
313 
314  TDirectory* oldDir = gDirectory;
315 
316  TDirectory* dir_multiplicity = oldDir->mkdir("multiplicity");
317  dir_multiplicity->cd();
318  TIter nextH_multiplicity(m_histoList_multiplicity);
319  TObject* obj;
320  while ((obj = nextH_multiplicity()))
321  obj->Write();
322 
323  TDirectory* dir_efficiency = oldDir->mkdir("efficiency");
324  dir_efficiency->cd();
325  TIter nextH_efficiency(m_histoList_efficiency);
326  while ((obj = nextH_efficiency()))
327  obj->Write();
328 
329  TDirectory* dir_purity = oldDir->mkdir("purity");
330  dir_purity->cd();
331  TIter nextH_purity(m_histoList_purity);
332  while ((obj = nextH_purity()))
333  obj->Write();
334 
335  TDirectory* dir_trkQuality = oldDir->mkdir("trkQuality");
336  dir_trkQuality->cd();
337  TIter nextH_trkQuality(m_histoList_trkQuality);
338  while ((obj = nextH_trkQuality()))
339  obj->Write();
340 
341  TIter nextH(m_histoList);
342  while ((obj = nextH()))
343  obj->Write();
344 
345 
346  m_rootFilePtr->Close();
347  }
348 
349 }
350 
351 
353 {
354 
355  bool isGamma = false;
356  if (abs(the_mcParticle.getPDG()) == Const::photon.getPDGCode())
357  isGamma = true;
358 
359  bool isK_S0 = false;
360  if (abs(the_mcParticle.getPDG()) == Const::Kshort.getPDGCode())
361  isK_S0 = true;
362 
363  bool isK_0 = false;
364  if (abs(the_mcParticle.getPDG()) == 311)
365  isK_0 = true;
366 
367  bool isLambda = false;
368  if (abs(the_mcParticle.getPDG()) == Const::Lambda.getPDGCode())
369  isLambda = true;
370 
371  bool twoProngs = false;
372  bool twoChargedProngs = false;
373 
374  if (the_mcParticle.getDaughters().size() == 2)
375  twoProngs = true;
376 
377  if (twoProngs)
378  if (the_mcParticle.getDaughters()[0]->getCharge() * the_mcParticle.getDaughters()[1]->getCharge() < 0)
379  twoChargedProngs = true;
380 
381  return ((isGamma || isK_S0 || isK_0 || isLambda) && twoChargedProngs);
382 
383 }
384 
386 {
387 
388  int nMatchedDau = 0;
389 
390  std::vector< MCParticle* > MCPart_dau = the_mcParticle.getDaughters();
391 
392  bool first = false;
393  bool second = false;
394 
395  RelationVector<Track> Tracks_fromMCParticle_0 = DataStore::getRelationsWithObj<Track>(MCPart_dau[0]);
396  if (Tracks_fromMCParticle_0.size() > 0)
397  first = true;
398 
399  RelationVector<Track> Tracks_fromMCParticle_1 = DataStore::getRelationsWithObj<Track>(MCPart_dau[1]);
400  if (Tracks_fromMCParticle_1.size() > 0)
401  second = true;
402 
403 
404  if (first)
405  nMatchedDau++;
406 
407  if (second)
408  nMatchedDau++;
409 
410 
411  return nMatchedDau;
412 
413 }
int getPDGCode() const
PDG code.
Definition: Const.h:464
static const ParticleType Lambda
Lambda particle.
Definition: Const.h:670
static const ParticleType antiLambda
Anti-Lambda particle.
Definition: Const.h:671
static const ParticleType Kshort
K^0_S particle.
Definition: Const.h:668
static const ParticleType photon
photon particle
Definition: Const.h:664
This struct is used by the TrackingPerformanceEvaluation Module to save information of reconstructed ...
double getPt()
Getter for transverse momentum.
double getPtheta()
Getter for theta of momentum vector.
double getPphi()
Getter for phi of momentum vector.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
Definition: MCParticle.cc:52
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
TH1F * createHistogram1D(const char *name, const char *title, Int_t nbins, Double_t min, Double_t max, const char *xtitle, TList *histoList=nullptr)
Create a 1D histogram and add it to the TList of 1D-histograms.
TH1 * duplicateHistogram(const char *newname, const char *newtitle, TH1 *h, TList *histoList=nullptr)
Make a copy of a 1D histogram and add it to the TList of 1D-histograms.
void addInefficiencyPlots(TList *graphList=nullptr, TH3F *h3_xPerMCParticle=nullptr, TH3F *h3_MCParticle=nullptr)
Create pt-, theta- and phi-inefficiency 1D histograms and add them to the TList of 1D-histograms.
TList * m_histoList_trkQuality
List of track-quality histograms.
TList * m_histoList_purity
List of purity histograms.
TList * m_histoList
List of performance-evaluation histograms.
TList * m_histoList_multiplicity
List of multiplicity histograms.
void addEfficiencyPlots(TList *graphList=nullptr, TH3F *h3_xPerMCParticle=nullptr, TH3F *h3_MCParticle=nullptr)
Create pt-, theta- and phi-efficiency 1D histograms and add them to the TList of 1D-histograms.
TH3F * createHistogram3D(const char *name, const char *title, Int_t nbinsX, Double_t minX, Double_t maxX, const char *titleX, Int_t nbinsY, Double_t minY, Double_t maxY, const char *titleY, Int_t nbinsZ, Double_t minZ, Double_t maxZ, const char *titleZ, TList *histoList=nullptr)
Create a 3D histogram and add it to the TList of 3D-histograms.
TH2F * createHistogram2D(const char *name, const char *title, Int_t nbinsX, Double_t minX, Double_t maxX, const char *titleX, Int_t nbinsY, Double_t minY, Double_t maxY, const char *titleY, TList *histoList=nullptr)
Create a 2D histogram and add it to the TList of 2D-histograms.
TFile * m_rootFilePtr
pointer at root file used for storing histograms
TList * m_histoList_efficiency
List of efficiency histograms.
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
static const double T
[tesla]
Definition: Unit.h:120
Class which stores some additional information on V0 vertices.
TH2F * m_h2_vtxTvsR_err
vtx error on transverse plane VS transverse flight length
void event() override
This method is called for each event.
void endRun() override
This method is called if the current run ends.
void terminate() override
This method is called at the end of the event processing.
int nMatchedDaughters(const MCParticle &the_mcParticle)
number of truth matched dauhters
void beginRun() override
Called when entering a new run.
StoreArray< V0ValidationVertex > m_V0ValidationVertices
V0ValidationVertices StoreArray.
TH1F * m_multiplicityMCParticles
number of MCParticles per fitted Track
StoreArray< MCParticle > m_MCParticles
MCParticles StoreArray.
REG_MODULE(arichBtest)
Register the Module.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
static void getField(const double *pos, double *field)
return the magnetic field at a given position.
Definition: BFieldManager.h:91
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.