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