Belle II Software  release-08-01-10
MCTrackCandClassifierModule.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/mcTrackCandClassifier/MCTrackCandClassifierModule.h>
10 
11 #include <pxd/dataobjects/PXDTrueHit.h>
12 #include <svd/dataobjects/SVDTrueHit.h>
13 #include <vxd/geometry/GeoCache.h>
14 
15 #include <framework/geometry/B2Vector3.h>
16 #include <framework/geometry/BFieldManager.h>
17 
18 #include <TH2F.h>
19 
20 using namespace Belle2;
21 
23 REG_MODULE(MCTrackCandClassifier);
24 
27  , m_rootFilePtr(nullptr)
28 {
29  //Set module properties
30  setDescription("This module is meant to classify the MCTrackCands as either ideal, fine and nasty");
32 
33  addParam("MCParticlesName", m_mcParticlesName,
34  "Name of MC Particle collection.",
35  std::string(""));
36 
37  addParam("MCTrackCandCollName", m_mcTrackCandsColName,
38  "Name of the input collection of MC track candidates",
39  std::string(""));
40 
41  addParam("rootFileName", m_rootFileName,
42  "Name of the root file",
43  std::string("MCTrackCandClassifier.root"));
44 
45  addParam("isInAnnulusCriterium", m_applyAnnulus,
46  "Require that the hit is in the expected annulus",
47  bool(true));
48  addParam("isInSemiplaneCriterium", m_applySemiplane,
49  "Require that the hit is in the expected semiplane",
50  bool(true));
51  addParam("isInFirstLapCriterium", m_applyLap,
52  "Require that the hit belong to the first lap in the transverse plane",
53  bool(true));
54  addParam("isInWedgePartCriterium", m_applyWedge,
55  "Require that the hit belong to the barrel part of the SVD",
56  bool(true));
57  addParam("removeBadHits", m_removeBadHits,
58  "Remove the clusters that do not satisfy the criteria from the idealMCTrackCands",
59  bool(true));
60 
61  addParam("minNhits", m_minHit,
62  "Minimum number of 1D Clusters to classify the MCTrackCand as ideal",
63  int(5));
64 
65  addParam("nSigma_dR", m_nSigma, "n sigma dR", int(3));
66 
67  addParam("lapFraction", m_fraction, "Fraction of lap", double(1));
68 
69  addParam("usePXD", m_usePXD, "Use the PXD or not", bool(true));
70 }
71 
72 
74 {
75  // MCParticles, MCTrackCands, MCTracks needed for this module
79 
82 
83  //create list of histograms to be saved in the rootfile
84  m_histoList = new TList;
85 
86  //set the ROOT File
87  m_rootFilePtr = new TFile(m_rootFileName.c_str(), "RECREATE");
88 
89  //histograms to produce efficiency plots
90  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
91  const 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, TMath::Pi()};
92  Double_t bins_lambda[10 + 1];
93  const Double_t width_lambda = TMath::Pi() / 10;
94  Double_t bins_phi[14 + 1];
95  const Double_t width_phi = 2 * TMath::Pi() / 14;
96  for (int bin = 0; bin < 14 + 1; bin++)
97  bins_phi[bin] = - TMath::Pi() + bin * width_phi;
98 
99  for (int bin = 0; bin < 10 + 1; bin++) {
100  bins_lambda[bin] = - TMath::Pi() / 2 + bin * width_lambda;
101  B2DEBUG(21, bins_lambda[bin] << " " << bins_theta[bin]);
102  }
103 
104  m_h3_MCParticle = createHistogram3D("h3MCParticle", "entry per MCParticle",
105  9, bins_pt, "p_{t} (GeV/c)",
106  10, bins_lambda, "#lambda",
107  14, bins_phi, "#phi" /*, m_histoList*/);
108 
109  m_h3_idealMCTrackCand = (TH3F*)duplicateHistogram("h3idealMCTrackCand",
110  "entry per idealMCTrackCand",
111  m_h3_MCParticle /*, m_histoList*/);
112 
113  m_h3_MCTrackCand = (TH3F*)duplicateHistogram("h3MCTrackCand",
114  "entry per MCTrackCand",
115  m_h3_MCParticle /*, m_histoList*/);
116 
117 
118  m_h1_thetaMS_SVD = new TH1F("h1thetaMS_SVD", "Multiple Scattering Angle (SVD)", 500, 0, 500);
120  m_h1_thetaMS_SVD->GetXaxis()->SetTitle("#theta_{MS} (mrad)");
121 
122  m_h1_thetaMS_PXD = (TH1F*) duplicateHistogram("h1thetaMS_PXD", "Multiple Scattering Angle (PXD)", m_h1_thetaMS_SVD, m_histoList);
123 
124  m_h1_dR = new TH1F("h1dR", "dR, annulus half width", 1000, 0, 5);
125  m_histoList->Add(m_h1_dR);
126  m_h1_dR->GetXaxis()->SetTitle("dR (cm)");
127 
128  m_h1_dRoverR = new TH1F("h1dRoverR", "dR over helix radius", 1000, 0, 0.1);
130  m_h1_dRoverR->GetXaxis()->SetTitle("dR/R");
131 
132  m_h1_distOVERdR = new TH1F("h1distOVERdR", "(hit radius - helix radius)/dR", 100, -5, 5);
134  m_h1_distOVERdR->GetXaxis()->SetTitle("(hit R - helix R)/dR");
135 
136  m_h1_hitRadius_accepted = new TH1F("h1hitRadAccep", "hit radius for accepted hits", 100, 0, 500);
138  m_h1_hitRadius_accepted->GetXaxis()->SetTitle("hit radius (cm)");
139 
140  m_h1_hitRadius_rejected = new TH1F("h1hitRadRejec", "hit radius for rejected hits", 100, 0, 500);
142  m_h1_hitRadius_rejected->GetXaxis()->SetTitle("hit radius (cm)");
143 
144  m_h1_hitDistance_accepted = new TH1F("h1hitDistCentAccep", "hit distance from 0,0 for accepted hits", 100, 0, 15);
146  m_h1_hitDistance_accepted->GetXaxis()->SetTitle("hit distance (cm)");
147 
148  m_h1_hitDistance_rejected = new TH1F("h1hitDistCentRejec", "hit distance from 0,0 for rejected hits", 100, 0, 15);
150  m_h1_hitDistance_rejected->GetXaxis()->SetTitle("hit distance (cm)");
151 
152  m_h1_lapTime = new TH1F("h1LapTime", "lap time", 200, 0, 100);
154  m_h1_lapTime->GetXaxis()->SetTitle("time (ns)");
155 
156  m_h1_timeDifference = (TH1F*)duplicateHistogram("h1TimeDiff", "Hit Time Difference",
158  m_h1_diffOVERlap = new TH1F("h1HitDiffOVERlap", "Hit Time Difference over Lap Time",
159  100, 0, 1.5);
161  m_h1_diffOVERlap->GetXaxis()->SetTitle("hit difference/lap");
162 
163  m_h1_nGoodTrueHits = new TH1F("h1nTrueHitsGoods", "Number of True Hits for Accepted Tracks", 20, 0, 20);
165  m_h1_nGoodTrueHits->GetXaxis()->SetTitle("number of hits");
166 
167  m_h1_nBadTrueHits = new TH1F("h1nTrueHitsBads", "Number of True Hits for Rejected Tracks", 10, 0, 10);
169  m_h1_nBadTrueHits->GetXaxis()->SetTitle("number of hits");
170 
171  m_h1_nGood1dInfo = new TH1F("h1nGood1Dinfo", "Number of 1D Info for Accepted Tracks", 20, 0, 20);
173  m_h1_nGood1dInfo->GetXaxis()->SetTitle("number of hits");
174 
175  m_h1_nBad1dInfo = new TH1F("h1nBad1Dinfo", "Number of 1D Info for Rejected Tracks", 20, 0, 20);
177  m_h1_nBad1dInfo->GetXaxis()->SetTitle("number of hits");
178 
179  m_h1_firstRejectedHit = new TH1F("h1idealMCTCnHit", "idealMCTrackCands number of hits", 40, 0, 40);
181  m_h1_firstRejectedHit->GetXaxis()->SetTitle("# idealMCTrackCands hits");
182 
183  m_h1_firstRejectedOVERMCHit = new TH1F("h1FirstRejOVERmc", "# idealMCTrackCands hits / # MCTrackCands hits", 100, 0, 1);
185  m_h1_firstRejectedOVERMCHit->GetXaxis()->SetTitle("# idealMCTrackCands hits / # MCTrackCands hits");
186 
187  m_h1_MCTrackCandNhits = (TH1F*)duplicateHistogram("h1MCTrackCandNhits", "number of MCTrackCands hits", m_h1_firstRejectedHit,
188  m_histoList);
189 }
190 
191 
193 {
194  nWedge = 0;
195  nBarrel = 0;
196 
198 }
199 
200 
202 {
203  B2DEBUG(21, "+++++ 1. loop on MCTrackCands");
204 
205  const VXD::GeoCache& aGeometry = VXD::GeoCache::getInstance();
206 
207  //1.a retrieve the MCTrackCands
208  for (const genfit::TrackCand& mcTrackCand : m_GenfitMCTrackCands) {
209 
210  int nGoodTrueHits = 0;
211  int nGood1Dinfo = 0;
212 
213  B2DEBUG(21, " a NEW MCTrackCand ");
214 
215  //1.b retrieve the MCParticle
216  RelationVector<MCParticle> MCParticles_fromMCTrackCand = DataStore::getRelationsWithObj<MCParticle>(&mcTrackCand);
217 
218  B2DEBUG(21, "~~~ " << MCParticles_fromMCTrackCand.size() << " MCParticles related to this MCTrackCand");
219  for (int mcp = 0; mcp < (int)MCParticles_fromMCTrackCand.size(); mcp++) { //should be ONE
220 
221  MCParticle mcParticle = *MCParticles_fromMCTrackCand[mcp];
222 
223  B2DEBUG(21, " a NEW charged MC Particle, " << mcParticle.getIndex() << ", " << mcParticle.getPDG());
224 
225  MCParticleInfo mcParticleInfo(mcParticle, m_magField);
226 
227  B2Vector3D decayVertex = mcParticle.getProductionVertex();
228  ROOT::Math::XYZVector mom = mcParticle.getMomentum();
229  double charge = mcParticle.getCharge();
230  double omega = mcParticleInfo.getOmega();
231  double px = mom.x();
232  double py = mom.y();
233  double pt = mom.Rho();
234  double x = decayVertex.X();
235  double y = decayVertex.Y();
236  double R = 1 / abs(omega); //cm
237 
238  m_h3_MCTrackCand->Fill(mcParticleInfo.getPt(), mcParticleInfo.getLambda(), mcParticleInfo.getPphi());
239 
240  double alpha = R / pt * charge; //cm/GeV
241  double Cx = x + alpha * py; //cm
242  double Cy = y - alpha * px; //cm
243 
244  ROOT::Math::XYZVector center(Cx, Cy, 0);
245 
246  //recover Clusters and loop on them
247  int Nhits = mcTrackCand.getNHits();
248  m_h1_MCTrackCandNhits->Fill(Nhits);
249 
250  int cluster = 0;
251  bool hasTrueHit = true;
252  bool isAccepted = true;
253  int firstRejectedHit = Nhits + 1;
254  double prevHitRadius = abs(1 / omega);
255 
256  double lapTime = 2 * M_PI * mcParticle.getEnergy() / 0.299792 / m_magField.Z();
257  double FirstHitTime = -1;
258  double HitTime = -1;
259 
260  bool isFirstSVDhit = true;
261 
262  while (cluster < Nhits && isAccepted && hasTrueHit) {
263  int detId, hitId;
264  mcTrackCand.getHit(cluster, detId, hitId);
265 
266  bool hasPXDCluster = false;
267  bool hasSVDuCluster = false;
268  bool hasSVDvCluster = false;
269 
270  double uCoor = 0;
271  double vCoor = 0;
272  VxdID sensor = 0;
273 
274  double thetaMS = 0;
275 
276  if (detId == Const::PXD && m_usePXD) {
277 
278  PXDCluster* aPXDCluster = m_PXDClusters[hitId];
279  RelationVector<PXDTrueHit> PXDTrueHit_fromPXDCluster = aPXDCluster->getRelationsWith<PXDTrueHit>();
280  if (PXDTrueHit_fromPXDCluster.size() == 0) {
281  B2WARNING("What's happening?!? no True Hit associated to the PXD Cluster");
282  hasTrueHit = false;
283  isAccepted = false;
284  continue;
285  }
286 
287  PXDTrueHit* aPXDTrueHit = PXDTrueHit_fromPXDCluster[0];
288  thetaMS = compute_thetaMS(mcParticleInfo, aPXDTrueHit);
289  m_h1_thetaMS_PXD->Fill(thetaMS / 2 * 1000); //PXD
290 
291  uCoor = aPXDTrueHit->getU();
292  vCoor = aPXDTrueHit->getV();
293  sensor = aPXDTrueHit->getSensorID();
294  if (cluster == 0) {
295  FirstHitTime = aPXDTrueHit->getGlobalTime();
296  HitTime = FirstHitTime;
297  } else
298  HitTime = aPXDTrueHit->getGlobalTime();
299 
300  hasPXDCluster = true;
301  } else if (detId == Const::SVD) {
302  SVDCluster* aSVDCluster = m_SVDClusters[hitId];
303  RelationVector<SVDTrueHit> SVDTrueHit_fromSVDCluster = aSVDCluster->getRelationsWith<SVDTrueHit>();
304  if (SVDTrueHit_fromSVDCluster.size() == 0) {
305  B2WARNING("What's happening?!? no True Hit associated to the SVD Cluster");
306  hasTrueHit = false;
307  isAccepted = false;
308  continue;
309  }
310 
311  SVDTrueHit* aSVDTrueHit = SVDTrueHit_fromSVDCluster[0];
312 
313  thetaMS = compute_thetaMS(mcParticleInfo, aSVDTrueHit);
314  m_h1_thetaMS_SVD->Fill(thetaMS * 1000); //SVD
315 
316  uCoor = aSVDTrueHit->getU();
317  vCoor = aSVDTrueHit->getV();
318  sensor = aSVDTrueHit->getSensorID();
319  if (isFirstSVDhit) {
320  FirstHitTime = aSVDTrueHit->getGlobalTime();
321  HitTime = FirstHitTime;
322  isFirstSVDhit = false;
323 
324  } else
325  HitTime = aSVDTrueHit->getGlobalTime();
326  if (aSVDCluster->isUCluster())
327  hasSVDuCluster = true;
328  else
329  hasSVDvCluster = true;
330  } else {
331  cluster++;
332  continue;
333  }
334 
335  const VXD::SensorInfoBase& aSensorInfo = aGeometry.getSensorInfo(sensor);
336  bool accepted4 = true;
337  if (m_applyWedge) {
338  if (aSensorInfo.getForwardWidth() != aSensorInfo.getBackwardWidth()) {
339  nWedge++;
340  accepted4 = false;
341  } else
342  nBarrel++;
343  }
344 
345  ROOT::Math::XYZVector globalHit = aSensorInfo.pointToGlobal(ROOT::Math::XYZVector(uCoor, vCoor, 0), true);
346  double hitRadius = theDistance(center, globalHit);
347 
348  bool accepted1 = true;
349  if (m_applySemiplane)
350  accepted1 = isInSemiPlane(semiPlane(decayVertex, center, globalHit), omega);
351 
352  if (accepted1) {
353  B2DEBUG(21, " semiplane: ACCEPTED");
354  } else {
355  B2DEBUG(21, " semiplane: REJECTED, next track");
356  }
357 
358  double dR = compute_dR(thetaMS, theDistance(ROOT::Math::XYZVector(0, 0, 0), globalHit));
359  m_h1_dR->Fill(dR);
360  m_h1_dRoverR->Fill(dR * abs(omega));
361  m_h1_distOVERdR->Fill((hitRadius - abs(1 / omega)) / dR);
362 
363 
364  bool accepted2 = true;
365  if (m_applyAnnulus)
366  accepted2 = isInAnnulus(hitRadius, prevHitRadius, dR);
367 
368  prevHitRadius = hitRadius;
369 
370  if (accepted2) {
371  B2DEBUG(21, " annulus: ACCEPTED");
372  } else {
373  B2DEBUG(21, " annulus: REJECTED, next track");
374  }
375 
376  bool accepted3 = true;
377  if (m_applyLap)
378  accepted3 = isFirstLap(FirstHitTime, HitTime, lapTime);
379 
380  if (accepted3) {
381  B2DEBUG(21, " lapTime: ACCEPTED");
382  } else {
383  B2DEBUG(21, " lapTime: REJECTED, next track");
384  }
385 
386  if (accepted2 && accepted1 && accepted3 && accepted4) {
387  nGoodTrueHits ++;
388  m_h1_hitDistance_accepted->Fill(theDistance(ROOT::Math::XYZVector(0, 0, 0), globalHit));
389  m_h1_hitRadius_accepted->Fill(hitRadius);
390  } else {
391  m_h1_hitDistance_rejected->Fill(theDistance(ROOT::Math::XYZVector(0, 0, 0), globalHit));
392  m_h1_hitRadius_rejected->Fill(hitRadius);
393  if (m_removeBadHits)
394  firstRejectedHit = cluster;
395  isAccepted = false;
396  continue;
397  }
398 
399  if (hasPXDCluster)
400  nGood1Dinfo = +2;
401  else {
402  if (hasSVDuCluster)
403  nGood1Dinfo++;
404  if (hasSVDvCluster)
405  nGood1Dinfo++;
406  }
407  if (hasPXDCluster || hasSVDuCluster || hasSVDvCluster)
408  B2DEBUG(21, "cluster: ACCEPTED (" << nGood1Dinfo << ")");
409 
410  cluster++;
411  }//close loop on clusters
412 
413  if (nGood1Dinfo >= m_minHit) {
414  B2DEBUG(21, " idealMCTrackCand FOUND!! " << nGood1Dinfo << " 1D infos (" << nGoodTrueHits << " good true hits)");
415  m_h3_idealMCTrackCand->Fill(mcParticleInfo.getPt(), mcParticleInfo.getLambda(), mcParticleInfo.getPphi());
416  m_h1_nGoodTrueHits->Fill(nGoodTrueHits);
417  m_h1_nGood1dInfo->Fill(nGood1Dinfo);
418 
419  genfit::TrackCand* tmpTrackCand = new genfit::TrackCand(mcTrackCand);
420 
421  if ((int)firstRejectedHit <= (int)mcTrackCand.getNHits()) {
422  tmpTrackCand->reset();
423  for (int hit = 0; hit < firstRejectedHit; hit++)
424  if (mcTrackCand.getHit(hit))
425  tmpTrackCand->addHit(mcTrackCand.getHit(hit));
426  tmpTrackCand->sortHits();
427  }
428  m_GenfitIdealMCTrackCands.appendNew(*tmpTrackCand);
429 
430  m_h1_firstRejectedHit->Fill(tmpTrackCand->getNHits());
431  m_h1_firstRejectedOVERMCHit->Fill((float)tmpTrackCand->getNHits() / mcTrackCand.getNHits());
432  } else {
433  B2DEBUG(21, " too few good hits (" << nGood1Dinfo << ") to track this one ( vs " << nGoodTrueHits << " true hits)");
434  m_h1_nBadTrueHits->Fill(nGoodTrueHits);
435  m_h1_nBad1dInfo->Fill(nGood1Dinfo);
436  }
437 
438  B2DEBUG(21, "");
439  }//close loop on MCParticles
440  }//close loop on MCTrackCands
441 }
442 
443 
445 {
446  B2INFO("** MCTrackCandClassifier parameters **");
447  B2INFO("rootfilename = " << m_rootFileName);
448  B2INFO("use PXD informations = " << m_usePXD);
449  B2INFO("--> classification criteria:");
450  if (m_applyAnnulus)
451  B2INFO(" -) |d - R| < " << m_nSigma << " dL thetaMS");
452  if (m_applySemiplane)
453  B2INFO(" -) hit in the expected semiplane");
454  if (m_applyLap)
455  B2INFO(" -) HitTime < " << m_fraction << " lap time");
456  if (m_applyWedge)
457  B2INFO(" -) hit must be in the barrel part of the VXD");
458  B2INFO("");
459 
460  double num = 0;
461  double den = 0;
462 
463  num = m_h3_idealMCTrackCand->GetEntries();
464  den = m_h3_MCTrackCand->GetEntries();
465  double efficiency = num / den ;
466  double efficiencyErr = sqrt(efficiency * (1 - efficiency)) / sqrt(den);
467 
468  B2INFO("");
469  B2INFO("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
470  B2INFO("~ MCTrackCandClassifier ~ SHORT SUMMARY ~");
471  B2INFO("");
472  B2INFO(" + overall:");
473  B2INFO(" fraction of ideal MCTrackCands = (" << efficiency * 100 << " +/- " << efficiencyErr * 100 << ")% ");
474  B2INFO("");
475  B2INFO(" # idealMCTrackCand = " << num);
476  B2INFO(" # MCTrackCand = " << den);
477  B2INFO("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
478  B2INFO("");
479  B2DEBUG(21, " nWedge = " << nWedge);
480  B2DEBUG(21, " nBarrel = " << nBarrel);
481 }
482 
483 
485 {
488 
489  if (m_rootFilePtr != nullptr) {
490  m_rootFilePtr->cd();
491 
492  TIter nextH(m_histoList);
493  TObject* obj;
494  while ((obj = nextH()))
495  obj->Write();
496 
497  m_rootFilePtr->Close();
498  }
499 }
500 
501 
502 double MCTrackCandClassifierModule::semiPlane(ROOT::Math::XYZVector vertex, ROOT::Math::XYZVector center, ROOT::Math::XYZVector hit)
503 {
504  ROOT::Math::XYZVector err = center - vertex;
505 
506  double semiPlane = err.Y() / err.X() * hit.X() + err.Y() / err.X() * vertex.x() - vertex.Y();
507 
508  B2DEBUG(21, "");
509  B2DEBUG(21, " SEMI-PLANE defined by: y + " << err.Y() / err.X() << " x + " << err.Y() / err.X()*vertex.x() - vertex.Y() << " = 0");
510  B2DEBUG(21, " with: center(" << center.X() << "," << center.Y() << ")");
511  B2DEBUG(21, " decayV(" << vertex.X() << "," << vertex.Y() << ")");
512  B2DEBUG(21, " vector(" << err.X() << "," << err.Y() << ")");
513  B2DEBUG(21, " y SLOPE = " << semiPlane << " VS y HIT = " << hit.Y());
514  B2DEBUG(21, " HIT - SLOPE = " << - semiPlane + hit.Y());
515 
516  if (vertex.X() < center.X())
517  return hit.Y() - semiPlane;
518  else
519  return semiPlane - hit.Y();
520 }
521 
522 
523 bool MCTrackCandClassifierModule::isInSemiPlane(double semiPlane, double omega)
524 {
525  if (semiPlane * omega > 0)
526  return true;
527  else
528  return false;
529 }
530 
531 
532 double MCTrackCandClassifierModule::theDistance(ROOT::Math::XYZVector center, ROOT::Math::XYZVector hit)
533 {
534  double xSquared = TMath::Power(center.X() - hit.X(), 2);
535  double ySquared = TMath::Power(center.Y() - hit.Y(), 2);
536 
537  return TMath::Sqrt(xSquared + ySquared);
538 }
539 
540 
541 bool MCTrackCandClassifierModule::isInAnnulus(double hitDistance, double R, double dR)
542 {
543  bool accepted = false;
544 
545  B2DEBUG(21, "");
546  B2DEBUG(21, " ANNULUS defined between radii: " << R - dR << " and " << R + dR);
547  B2DEBUG(21, " hit distance = " << hitDistance);
548  B2DEBUG(21, " helix radius = " << R);
549  B2DEBUG(21, " dR = " << dR);
550 
551  if ((hitDistance > R - dR) && (hitDistance < R + dR))
552  accepted = true;
553 
554  return accepted;
555 }
556 
557 
558 bool MCTrackCandClassifierModule::isFirstLap(double FirstHitTime, double HitTime, double LapTime)
559 {
560  bool accepted = false;
561 
562  B2DEBUG(21, "");
563  B2DEBUG(21, " lapTime: " << LapTime);
564  B2DEBUG(21, " FirstHitTime = " << FirstHitTime);
565  B2DEBUG(21, " HitTime = " << HitTime);
566  B2DEBUG(21, " difference = " << HitTime - FirstHitTime);
567 
568  m_h1_lapTime->Fill(LapTime);
569  m_h1_timeDifference->Fill(HitTime - FirstHitTime);
570  m_h1_diffOVERlap->Fill((HitTime - FirstHitTime) / LapTime);
571 
572  if (HitTime - FirstHitTime < m_fraction * LapTime)
573  accepted = true;
574 
575  return accepted;
576 }
577 
578 
579 TH3F* MCTrackCandClassifierModule::createHistogram3D(const char* name, const char* title,
580  Int_t nbinsX, Double_t minX, Double_t maxX,
581  const char* titleX,
582  Int_t nbinsY, Double_t minY, Double_t maxY,
583  const char* titleY,
584  Int_t nbinsZ, Double_t minZ, Double_t maxZ,
585  const char* titleZ,
586  TList* histoList)
587 {
588  TH3F* h = new TH3F(name, title, nbinsX, minX, maxX, nbinsY, minY, maxY, nbinsZ, minZ, maxZ);
589 
590  h->GetXaxis()->SetTitle(titleX);
591  h->GetYaxis()->SetTitle(titleY);
592  h->GetZaxis()->SetTitle(titleZ);
593 
594  if (histoList)
595  histoList->Add(h);
596 
597  return h;
598 }
599 
600 
601 TH3F* MCTrackCandClassifierModule::createHistogram3D(const char* name, const char* title,
602  Int_t nbinsX, Double_t* binsX,
603  const char* titleX,
604  Int_t nbinsY, Double_t* binsY,
605  const char* titleY,
606  Int_t nbinsZ, Double_t* binsZ,
607  const char* titleZ,
608  TList* histoList)
609 {
610  TH3F* h = new TH3F(name, title, nbinsX, binsX, nbinsY, binsY, nbinsZ, binsZ);
611 
612  h->GetXaxis()->SetTitle(titleX);
613  h->GetYaxis()->SetTitle(titleY);
614  h->GetZaxis()->SetTitle(titleZ);
615 
616  if (histoList)
617  histoList->Add(h);
618 
619  return h;
620 }
621 
622 
623 TH1* MCTrackCandClassifierModule::duplicateHistogram(const char* newname, const char* newtitle,
624  TH1* h, TList* histoList)
625 {
626  TH1F* h1 = dynamic_cast<TH1F*>(h);
627  TH2F* h2 = dynamic_cast<TH2F*>(h);
628  TH3F* h3 = dynamic_cast<TH3F*>(h);
629 
630  TH1* newh = nullptr;
631 
632  if (h1)
633  newh = new TH1F(*h1);
634  if (h2)
635  newh = new TH2F(*h2);
636  if (h3)
637  newh = new TH3F(*h3);
638 
639  if (newh == nullptr) {
640  B2ERROR("In function duplicateHistogram: newh is a nullptr. This shouldn't happen."\
641  "Don't continue creation of duplicate histogram in this case and return nullptr.");
642  return nullptr;
643  }
644 
645  newh->SetName(newname);
646  newh->SetTitle(newtitle);
647 
648  if (histoList)
649  histoList->Add(newh);
650 
651  return newh;
652 }
653 
654 
656 {
657  //normalized to MCTrackCands
658  TH1F* h_effMCTC_pt = createHistogramsRatio("heffMCTCpt", "fraction of idealMCTrackCand VS pt", m_h3_idealMCTrackCand,
659  m_h3_MCTrackCand, true, 0);
660  histoList->Add(h_effMCTC_pt);
661 
662  TH1F* h_effMCTC_theta = createHistogramsRatio("heffMCTCtheta", "fraction of idealMCTrackCandVS #lambda", m_h3_idealMCTrackCand,
663  m_h3_MCTrackCand, true, 1);
664  histoList->Add(h_effMCTC_theta);
665 
666  TH1F* h_effMCTC_phi = createHistogramsRatio("heffMCTCphi", "fraction of idealMCTrackCand VS #phi", m_h3_idealMCTrackCand,
667  m_h3_MCTrackCand, true, 2);
668  histoList->Add(h_effMCTC_phi);
669 }
670 
671 
673 {
674  //normalized to MCTrackCands
675  TH1F* h_ineffMCTC_pt = createHistogramsRatio("hineffMCTCpt", "1 - fraction of idealMCTrackCand VS pt", m_h3_idealMCTrackCand,
676  m_h3_MCTrackCand, false, 0);
677  histoList->Add(h_ineffMCTC_pt);
678 
679  TH1F* h_ineffMCTC_theta = createHistogramsRatio("hineffMCTCtheta", "1 - fraction of idealMCTrackCandVS #lambda",
681  histoList->Add(h_ineffMCTC_theta);
682 
683  TH1F* h_ineffMCTC_phi = createHistogramsRatio("hineffMCTCphi", "1 - fraction of idealMCTrackCand VS #phi", m_h3_idealMCTrackCand,
684  m_h3_MCTrackCand, false, 2);
685  histoList->Add(h_ineffMCTC_phi);
686 }
687 
688 
689 TH1F* MCTrackCandClassifierModule::createHistogramsRatio(const char* name, const char* title,
690  TH1* hNum, TH1* hDen, bool isEffPlot,
691  int axisRef)
692 {
693  TH1F* h1den = dynamic_cast<TH1F*>(hDen);
694  TH1F* h1num = dynamic_cast<TH1F*>(hNum);
695  TH2F* h2den = dynamic_cast<TH2F*>(hDen);
696  TH2F* h2num = dynamic_cast<TH2F*>(hNum);
697  TH3F* h3den = dynamic_cast<TH3F*>(hDen);
698  TH3F* h3num = dynamic_cast<TH3F*>(hNum);
699 
700  TH1* hden = nullptr;
701  TH1* hnum = nullptr;
702 
703  if (h1den) {
704  hden = new TH1F(*h1den);
705  hnum = new TH1F(*h1num);
706  }
707  if (h2den) {
708  hden = new TH2F(*h2den);
709  hnum = new TH2F(*h2num);
710  }
711  if (h3den) {
712  hden = new TH3F(*h3den);
713  hnum = new TH3F(*h3num);
714  }
715 
716  if (hden == nullptr or hnum == nullptr) {
717  B2ERROR("In function createHistogramsRatio: either hden or hnum are a nullptr. This shouldn't happen."\
718  "Don't continue creatio of histogram ratios in this case and return nullptr.");
719  return nullptr;
720  }
721 
722  TAxis* the_axis;
723  TAxis* the_other1;
724  TAxis* the_other2;
725 
726  if (axisRef == 0) {
727  the_axis = hden->GetXaxis();
728  the_other1 = hden->GetYaxis();
729  the_other2 = hden->GetZaxis();
730  } else if (axisRef == 1) {
731  the_axis = hden->GetYaxis();
732  the_other1 = hden->GetXaxis();
733  the_other2 = hden->GetZaxis();
734  } else if (axisRef == 2) {
735  the_axis = hden->GetZaxis();
736  the_other1 = hden->GetXaxis();
737  the_other2 = hden->GetYaxis();
738  } else
739  return nullptr;
740 
741 
742  TH1F* h;
743  if (the_axis->GetXbins()->GetSize())
744  h = new TH1F(name, title, the_axis->GetNbins(), (the_axis->GetXbins())->GetArray());
745  else
746  h = new TH1F(name, title, the_axis->GetNbins(), the_axis->GetXmin(), the_axis->GetXmax());
747  h->GetXaxis()->SetTitle(the_axis->GetTitle());
748 
749  h->GetYaxis()->SetRangeUser(0.00001, 1);
750 
751  Int_t bin = 0;
752 
753  for (int the_bin = 1; the_bin < the_axis->GetNbins() + 1; the_bin++) {
754 
755  double num = 0;
756  double den = 0 ;
757 
758  for (int other1_bin = 1; other1_bin < the_other1->GetNbins() + 1; other1_bin++)
759  for (int other2_bin = 1; other2_bin < the_other2->GetNbins() + 1; other2_bin++) {
760 
761  if (axisRef == 0) bin = hden->GetBin(the_bin, other1_bin, other2_bin);
762  else if (axisRef == 1) bin = hden->GetBin(other1_bin, the_bin, other2_bin);
763  else if (axisRef == 2) bin = hden->GetBin(other1_bin, other2_bin, the_bin);
764 
765  if (hden->IsBinUnderflow(bin))
766  B2DEBUG(21, " bin = " << bin << "(" << the_bin << "," << other1_bin << "," << other2_bin << "), UNDERFLOW");
767  if (hden->IsBinOverflow(bin))
768  B2DEBUG(21, " bin = " << bin << "(" << the_bin << "," << other1_bin << "," << other2_bin << "), OVERFLOW");
769 
770  num += hnum->GetBinContent(bin);
771  den += hden->GetBinContent(bin);
772  }
773  double eff = 0;
774  double err = 0;
775 
776  if (den > 0) {
777  eff = (double)num / den;
778  err = sqrt(eff * (1 - eff)) / sqrt(den);
779  }
780 
781  if (isEffPlot) {
782  h->SetBinContent(the_bin, eff);
783  h->SetBinError(the_bin, err);
784  } else {
785  h->SetBinContent(the_bin, 1 - eff);
786  h->SetBinError(the_bin, err);
787  }
788 
789  }
790 
791  return h;
792 }
793 
794 
795 float MCTrackCandClassifierModule::compute_dR(double thetaMS, double hitDistance)
796 {
797  double dL;
798  if (hitDistance < 1.8) //L1
799  dL = 0.4;
800  else if (hitDistance < 3) //L2
801  dL = 0.8;
802  else if (hitDistance < 5) //L3
803  dL = 1.6;
804  else if (hitDistance < 9) //L4
805  dL = 4.2;
806  else if (hitDistance < 12) //L5
807  dL = 2.4;
808  else dL = 3.1;
809 
810  if ((hitDistance < 3) && (hitDistance > 1.2))
811  thetaMS = thetaMS / 2;
812 
813  double dR = m_nSigma * dL * thetaMS;
814 
815  return dR;
816 };
817 
818 
820 {
821  // double thetaMS = 0.0136 * 14 * sqrt(0.008); //SVD, PXD is half of it
822  double thetaMS = 0.0136 * 14; //SVD, PXD is half of it
823 
824  double p = mcParticleInfo.getP();
825  // double pt = mcParticleInfo.getPt();
826  double E = mcParticleInfo.getEnergy();
827 
828  double X = sqrt(pow(aTrueHit->getEntryU() - aTrueHit->getExitU(), 2) +
829  pow(aTrueHit->getEntryV() - aTrueHit->getExitV(), 2) +
830  pow(aTrueHit->getEntryW() - aTrueHit->getExitW(), 2));
831 
832  double X0 = 21.82; // g cm-2
833  double rho = 2.329; // g cm-3
834  thetaMS = thetaMS / (p * p / E) * sqrt(X / X0 * rho);
835 
836  return thetaMS;
837 };
R E
internal precision of FFTW codelets
double R
typedef autogenerated by FFTW
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:431
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:433
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
This struct is used by the TrackingPerformanceEvaluation Module to save information of reconstructed ...
double getPt()
Getter for transverse momentum.
double getLambda()
Getter for Lambda.
double getEnergy()
Getter for energy.
double getOmega()
Getter for Omega.
double getPphi()
Getter for phi of momentum vector.
double getP()
Getter for magnitut of momentum.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
float getEnergy() const
Return particle energy in GeV.
Definition: MCParticle.h:147
int getIndex() const
Get 1-based index of the particle in the corresponding MCParticle list.
Definition: MCParticle.h:230
ROOT::Math::XYZVector getProductionVertex() const
Return production vertex position.
Definition: MCParticle.h:189
float getCharge() const
Return the particle charge defined in TDatabasePDG.
Definition: MCParticle.cc:36
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
ROOT::Math::XYZVector getMomentum() const
Return momentum.
Definition: MCParticle.h:198
bool m_applySemiplane
Wether to require that the hit is in the expected semiplane.
bool m_applyWedge
Whether to require that the hit belong to the barrel part of the SVD.
void addInefficiencyPlots(TList *graphList=nullptr)
Function to create inefficiency plots and add them to list.
ROOT::Math::XYZVector m_magField
magnetic field needed set particle info
StoreArray< genfit::TrackCand > m_GenfitMCTrackCands
MC Genfit TrackCands StoreArray.
int nWedge
Counter for hits on wedged sensors.
StoreArray< SVDCluster > m_SVDClusters
SVDClusters StoreArray.
bool isInAnnulus(double hitDistance, double R, double dR)
Function to check if hitDistance is within a given annulus.
void initialize() override
Initializes the Module.
std::string m_mcParticlesName
MCParticle list name.
int nBarrel
Counter for hits on barrel sensors.
TH1 * duplicateHistogram(const char *newname, const char *newtitle, TH1 *h, TList *histoList=nullptr)
Function to clone a histogram.
float compute_thetaMS(MCParticleInfo &mcParticleInfo, VXDTrueHit *aTrueHit)
Calculate thetaMS.
void terminate() override
Termination action.
bool m_applyLap
Whether to require that the hit belongs to the first lap in the transverse plane.
MCTrackCandClassifierModule()
Constructor of the module.
StoreArray< genfit::TrackCand > m_GenfitIdealMCTrackCands
Ideal Genfit TrackCands StoreArray.
bool isFirstLap(double FirstHitTime, double HitTime, double LapTime)
Function to check if a hitTime is within a given lapTime, under consideration of m_fraction and with ...
void addEfficiencyPlots(TList *graphList=nullptr)
Function to create efficiency plots and add them to list.
StoreArray< PXDCluster > m_PXDClusters
PXDClusters StoreArray.
double semiPlane(ROOT::Math::XYZVector vertex, ROOT::Math::XYZVector center, ROOT::Math::XYZVector hit)
Function to get semiplane.
double theDistance(ROOT::Math::XYZVector center, ROOT::Math::XYZVector hit)
Get distance between two points.
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 ROOT Histogram.
TH1F * createHistogramsRatio(const char *name, const char *title, TH1 *hNum, TH1 *hDen, bool isEffPlot, int axisRef)
Function to create a ratio histogram from two histograms.
TFile * m_rootFilePtr
Pointer to root file used for storing histograms.
StoreArray< MCParticle > m_MCParticles
MCParticles StoreArray.
bool m_applyAnnulus
Whether to require that the hit is in the expected annulus.
std::string m_mcTrackCandsColName
TrackCand list name.
bool isInSemiPlane(double semiPlane, double omega)
Function to check if a omega value is in a given semiPlane.
float compute_dR(double thetaMS, double omega)
Calculate dR.
bool m_removeBadHits
Whether to remove the clusters that do not satisfy the criteria from the idealMCTrackCands.
int m_minHit
Minimum number of 1D Clusters to classify the MCTrackCand as ideal.
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
Definition: PXDCluster.h:30
Class PXDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: PXDTrueHit.h:31
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
RelationVector< T > getRelationsWith(const std::string &name="", const std::string &namedRelation="") const
Get the relations between this object and another store array.
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
Definition: SVDCluster.h:29
bool isUCluster() const
Get the direction of strips.
Definition: SVDCluster.h:110
Class SVDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: SVDTrueHit.h:33
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
static const double T
[tesla]
Definition: Unit.h:120
Class VXDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: VXDTrueHit.h:36
float getV() const
Return local v coordinate of hit.
Definition: VXDTrueHit.h:76
float getGlobalTime() const
Return the time when the track reached its midpoint.
Definition: VXDTrueHit.h:94
float getEntryU() const
Return local u coordinate of hit when entering silicon.
Definition: VXDTrueHit.h:80
float getExitW() const
Return local w coordinate of hit at the endpoint of the track.
Definition: VXDTrueHit.h:90
float getEntryW() const
Return local w coordinate of the start point of the track.
Definition: VXDTrueHit.h:84
VxdID getSensorID() const
Return the Sensor ID.
Definition: VXDTrueHit.h:70
float getU() const
Return local u coordinate of hit.
Definition: VXDTrueHit.h:74
float getExitU() const
Return local u coordinate of hit at the endpoint of the track.
Definition: VXDTrueHit.h:86
float getExitV() const
Return local v coordinate of hit at the endpoint of the track.
Definition: VXDTrueHit.h:88
float getEntryV() const
Return local v coordinate of the start point of the track.
Definition: VXDTrueHit.h:82
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:39
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a referecne to the SensorInfo of a given SensorID.
Definition: GeoCache.cc:67
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
Base class to provide Sensor Information for PXD and SVD.
ROOT::Math::XYZVector pointToGlobal(const ROOT::Math::XYZVector &local, bool reco=false) const
Convert a point from local to global coordinates.
double getForwardWidth() const
Convinience Wrapper to return width at forward side.
double getBackwardWidth() const
Convinience Wrapper to return width at backward side.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
Track candidate – seed values and indices.
Definition: TrackCand.h:69
void sortHits()
Sort the hits that were already added to the trackCand using the sorting parameters.
Definition: TrackCand.cc:222
void reset()
Delete and clear the TrackCandHits.
Definition: TrackCand.cc:172
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.