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