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
20using namespace Belle2;
21
23REG_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,
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;
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 }
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");
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
502double 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
523bool MCTrackCandClassifierModule::isInSemiPlane(double semiPlane, double omega)
524{
525 if (semiPlane * omega > 0)
526 return true;
527 else
528 return false;
529}
530
531
532double 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
541bool 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
558bool 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
579TH3F* 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
601TH3F* 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
623TH1* 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
689TH1F* 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
795float 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
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
#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.
Definition: BFieldManager.h:91
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.