11 #include <tracking/modules/mcTrackCandClassifier/MCTrackCandClassifierModule.h>
13 #include <pxd/dataobjects/PXDTrueHit.h>
14 #include <pxd/dataobjects/PXDCluster.h>
15 #include <svd/dataobjects/SVDTrueHit.h>
16 #include <svd/dataobjects/SVDCluster.h>
17 #include <vxd/geometry/GeoCache.h>
19 #include <framework/datastore/StoreArray.h>
20 #include <framework/geometry/B2Vector3.h>
21 #include <framework/geometry/BFieldManager.h>
23 #include <genfit/TrackCand.h>
25 #include <boost/foreach.hpp>
35 MCTrackCandClassifierModule::MCTrackCandClassifierModule() :
Module()
40 setDescription(
"This module is meant to classify the MCTrackCands as either ideal, fine and nasty");
44 "Name of MC Particle collection.",
48 "Name of the input collection of MC track candidates",
52 "Name of the root file",
53 std::string(
"MCTrackCandClassifier.root"));
56 "Require that the hit is in the expected annulus",
59 "Require that the hit is in the expected semiplane",
62 "Require that the hit belong to the first lap in the transverse plane",
65 "Require that the hit belong to the barrel part of the SVD",
68 "Remove the clusters that do not satisfy the criteria from the idealMCTrackCands",
72 "Minimum number of 1D Clusters to classify the MCTrackCand as ideal",
87 pxdClusters.isRequired();
90 svdClusters.isRequired();
93 mcParticles.isRequired();
96 mcTrackCands.isRequired();
101 pxdTrueHits.isRequired();
104 svdTrueHits.isRequired();
113 Double_t bins_pt[9 + 1] = {0, 0.05, 0.1, 0.15, 0.2, 0.3, 0.5, 1, 2, 3.5};
114 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()};
115 Double_t bins_lambda[10 + 1];
116 Double_t width_lambda = TMath::Pi() / 10;
117 Double_t bins_phi[14 + 1];
118 Double_t width_phi = 2 * TMath::Pi() / 14;
119 for (
int bin = 0; bin < 14 + 1; bin++)
120 bins_phi[bin] = - TMath::Pi() + bin * width_phi;
122 for (
int bin = 0; bin < 10 + 1; bin++) {
123 bins_lambda[bin] = - TMath::Pi() / 2 + bin * width_lambda;
124 B2DEBUG(1, bins_lambda[bin] <<
" " << bins_theta[bin]);
128 9, bins_pt,
"p_{t} (GeV/c)",
129 10, bins_lambda,
"#lambda",
130 14, bins_phi,
"#phi" );
133 "entry per idealMCTrackCand",
137 "entry per MCTrackCand",
141 m_h1_thetaMS_SVD =
new TH1F(
"h1thetaMS_SVD",
"Multiple Scattering Angle (SVD)", 500, 0, 500);
147 m_h1_dR =
new TH1F(
"h1dR",
"dR, annulus half width", 1000, 0, 5);
149 m_h1_dR->GetXaxis()->SetTitle(
"dR (cm)");
151 m_h1_dRoverR =
new TH1F(
"h1dRoverR",
"dR over helix radius", 1000, 0, 0.1);
155 m_h1_distOVERdR =
new TH1F(
"h1distOVERdR",
"(hit radius - helix radius)/dR", 100, -5, 5);
175 m_h1_lapTime =
new TH1F(
"h1LapTime",
"lap time", 200, 0, 100);
181 m_h1_diffOVERlap =
new TH1F(
"h1HitDiffOVERlap",
"Hit Time Difference over Lap Time",
186 m_h1_nGoodTrueHits =
new TH1F(
"h1nTrueHitsGoods",
"Number of True Hits for Accepted Tracks", 20, 0, 20);
190 m_h1_nBadTrueHits =
new TH1F(
"h1nTrueHitsBads",
"Number of True Hits for Rejected Tracks", 10, 0, 10);
194 m_h1_nGood1dInfo =
new TH1F(
"h1nGood1Dinfo",
"Number of 1D Info for Accepted Tracks", 20, 0, 20);
198 m_h1_nBad1dInfo =
new TH1F(
"h1nBad1Dinfo",
"Number of 1D Info for Rejected Tracks", 20, 0, 20);
226 B2DEBUG(1,
"+++++ 1. loop on MCTrackCands");
238 int nGoodTrueHits = 0;
239 int nBadTrueHits = 0;
242 B2DEBUG(1,
" a NEW MCTrackCand ");
247 B2DEBUG(1,
"~~~ " << MCParticles_fromMCTrackCand.
size() <<
" MCParticles related to this MCTrackCand");
248 for (
int mcp = 0; mcp < (int)MCParticles_fromMCTrackCand.
size(); mcp++) {
250 MCParticle mcParticle = *MCParticles_fromMCTrackCand[mcp];
252 B2DEBUG(1,
" a NEW charged MC Particle, " << mcParticle.
getIndex() <<
", " << mcParticle.
getPDG());
259 double omega = mcParticleInfo.
getOmega();
260 double px = mom.Px();
261 double py = mom.Py();
262 double pt = mom.Pt();
263 double x = decayVertex.X();
264 double y = decayVertex.Y();
265 double R = 1 / abs(omega);
269 double alpha = R / pt * charge;
270 double Cx = x + alpha * py;
271 double Cy = y - alpha * px;
273 TVector3 center(Cx, Cy, 0);
276 int Nhits = mcTrackCand.getNHits();
280 bool hasTrueHit =
true;
281 bool isAccepted =
true;
282 int firstRejectedHit = Nhits + 1;
283 double prevHitRadius = abs(1 / omega);
285 double lapTime = 2 * M_PI * mcParticle.
getEnergy() / 0.299792 / magField.
Z();
286 double FirstHitTime = -1;
289 bool isFirstSVDhit =
true;
291 while (cluster < Nhits && isAccepted && hasTrueHit) {
293 mcTrackCand.getHit(cluster, detId, hitId);
295 bool hasPXDCluster =
false;
296 bool hasSVDuCluster =
false;
297 bool hasSVDvCluster =
false;
305 if (detId == Const::PXD &&
m_usePXD) {
309 if (PXDTrueHit_fromPXDCluster.
size() == 0) {
310 B2WARNING(
"What's happening?!? no True Hit associated to the PXD Cluster");
316 PXDTrueHit* aPXDTrueHit = PXDTrueHit_fromPXDCluster[0];
320 uCoor = aPXDTrueHit->
getU();
321 vCoor = aPXDTrueHit->
getV();
325 HitTime = FirstHitTime;
329 hasPXDCluster =
true;
330 }
else if (detId == Const::SVD) {
333 if (SVDTrueHit_fromSVDCluster.
size() == 0) {
334 B2WARNING(
"What's happening?!? no True Hit associated to the SVD Cluster");
340 SVDTrueHit* aSVDTrueHit = SVDTrueHit_fromSVDCluster[0];
345 uCoor = aSVDTrueHit->
getU();
346 vCoor = aSVDTrueHit->
getV();
350 HitTime = FirstHitTime;
351 isFirstSVDhit =
false;
356 hasSVDuCluster =
true;
358 hasSVDvCluster =
true;
365 bool accepted4 =
true;
374 TVector3 globalHit = aSensorInfo.
pointToGlobal(TVector3(uCoor, vCoor, 0),
true);
377 bool accepted1 =
true;
382 B2DEBUG(1,
" semiplane: ACCEPTED");
384 B2DEBUG(1,
" semiplane: REJECTED, next track");
393 bool accepted2 =
true;
395 accepted2 =
isInAnnulus(hitRadius, prevHitRadius, dR);
397 prevHitRadius = hitRadius;
400 B2DEBUG(1,
" annulus: ACCEPTED");
402 B2DEBUG(1,
" annulus: REJECTED, next track");
405 bool accepted3 =
true;
407 accepted3 =
isFirstLap(FirstHitTime, HitTime, lapTime);
410 B2DEBUG(1,
" lapTime: ACCEPTED");
412 B2DEBUG(1,
" lapTime: REJECTED, next track");
415 if (accepted2 && accepted1 && accepted3 && accepted4) {
424 firstRejectedHit = cluster;
437 if (hasPXDCluster || hasSVDuCluster || hasSVDvCluster)
438 B2DEBUG(1,
"cluster: ACCEPTED (" << nGood1Dinfo <<
")");
444 B2DEBUG(1,
" idealMCTrackCand FOUND!! " << nGood1Dinfo <<
" 1D infos (" << nGoodTrueHits <<
" good true hits)");
451 if ((
int)firstRejectedHit <= (
int)mcTrackCand.getNHits()) {
452 tmpTrackCand->
reset();
453 for (
int hit = 0; hit < firstRejectedHit; hit++)
454 if (mcTrackCand.getHit(hit))
455 tmpTrackCand->addHit(mcTrackCand.getHit(hit));
458 idealMCTrackCands.
appendNew(*tmpTrackCand);
463 B2DEBUG(1,
" too few good hits (" << nGood1Dinfo <<
") to track this one ( vs " << nGoodTrueHits <<
" true hits)");
476 B2INFO(
"** MCTrackCandClassifier parameters **");
478 B2INFO(
"use PXD informations = " <<
m_usePXD);
479 B2INFO(
"--> classification criteria:");
481 B2INFO(
" -) |d - R| < " <<
m_nSigma <<
" dL thetaMS");
483 B2INFO(
" -) hit in the expected semiplane");
485 B2INFO(
" -) HitTime < " <<
m_fraction <<
" lap time");
487 B2INFO(
" -) hit must be in the barrel part of the VXD");
495 double efficiency = num / den ;
496 double efficiencyErr = sqrt(efficiency * (1 - efficiency)) / sqrt(den);
499 B2INFO(
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
500 B2INFO(
"~ MCTrackCandClassifier ~ SHORT SUMMARY ~");
502 B2INFO(
" + overall:");
503 B2INFO(
" fraction of ideal MCTrackCands = (" << efficiency * 100 <<
" +/- " << efficiencyErr * 100 <<
")% ");
505 B2INFO(
" # idealMCTrackCand = " << num);
506 B2INFO(
" # MCTrackCand = " << den);
507 B2INFO(
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
509 B2DEBUG(1,
" nWedge = " <<
nWedge);
510 B2DEBUG(1,
" nBarrel = " <<
nBarrel);
524 while ((obj = nextH()))
534 TVector3 err = center - vertex;
536 double semiPlane = err.Y() / err.X() * hit.X() + err.Y() / err.X() * vertex.x() - vertex.Y();
539 B2DEBUG(1,
" SEMI-PLANE defined by: y + " << err.Y() / err.X() <<
" x + " << err.Y() / err.X()*vertex.x() - vertex.Y() <<
" = 0");
540 B2DEBUG(1,
" with: center(" << center.X() <<
"," << center.Y() <<
")");
541 B2DEBUG(1,
" decayV(" << vertex.X() <<
"," << vertex.Y() <<
")");
542 B2DEBUG(1,
" vector(" << err.X() <<
"," << err.Y() <<
")");
543 B2DEBUG(1,
" y SLOPE = " <<
semiPlane <<
" VS y HIT = " << hit.Y());
544 B2DEBUG(1,
" HIT - SLOPE = " << -
semiPlane + hit.Y());
546 if (vertex.X() < center.X())
564 double xSquared = TMath::Power(center.X() - hit.X(), 2);
565 double ySquared = TMath::Power(center.Y() - hit.Y(), 2);
567 return TMath::Sqrt(xSquared + ySquared);
573 bool accepted =
false;
576 B2DEBUG(1,
" ANNULUS defined between radii: " << R - dR <<
" and " << R + dR);
577 B2DEBUG(1,
" hit distance = " << hitDistance);
578 B2DEBUG(1,
" helix radius = " << R);
579 B2DEBUG(1,
" dR = " << dR);
581 if ((hitDistance > R - dR) && (hitDistance < R + dR))
590 bool accepted =
false;
593 B2DEBUG(1,
" lapTime: " << LapTime);
594 B2DEBUG(1,
" FirstHitTime = " << FirstHitTime);
595 B2DEBUG(1,
" HitTime = " << HitTime);
596 B2DEBUG(1,
" difference = " << HitTime - FirstHitTime);
602 if (HitTime - FirstHitTime <
m_fraction * LapTime)
610 Int_t nbinsX, Double_t minX, Double_t maxX,
612 Int_t nbinsY, Double_t minY, Double_t maxY,
614 Int_t nbinsZ, Double_t minZ, Double_t maxZ,
618 TH3F* h =
new TH3F(name, title, nbinsX, minX, maxX, nbinsY, minY, maxY, nbinsZ, minZ, maxZ);
620 h->GetXaxis()->SetTitle(titleX);
621 h->GetYaxis()->SetTitle(titleY);
622 h->GetZaxis()->SetTitle(titleZ);
632 Int_t nbinsX, Double_t* binsX,
634 Int_t nbinsY, Double_t* binsY,
636 Int_t nbinsZ, Double_t* binsZ,
640 TH3F* h =
new TH3F(name, title, nbinsX, binsX, nbinsY, binsY, nbinsZ, binsZ);
642 h->GetXaxis()->SetTitle(titleX);
643 h->GetYaxis()->SetTitle(titleY);
644 h->GetZaxis()->SetTitle(titleZ);
654 TH1* h, TList* histoList)
656 TH1F* h1 =
dynamic_cast<TH1F*
>(h);
657 TH2F* h2 =
dynamic_cast<TH2F*
>(h);
658 TH3F* h3 =
dynamic_cast<TH3F*
>(h);
663 newh =
new TH1F(*h1);
665 newh =
new TH2F(*h2);
667 newh =
new TH3F(*h3);
669 newh->SetName(newname);
670 newh->SetTitle(newtitle);
673 histoList->Add(newh);
684 histoList->Add(h_effMCTC_pt);
688 histoList->Add(h_effMCTC_theta);
692 histoList->Add(h_effMCTC_phi);
701 histoList->Add(h_ineffMCTC_pt);
703 TH1F* h_ineffMCTC_theta =
createHistogramsRatio(
"hineffMCTCtheta",
"1 - fraction of idealMCTrackCandVS #lambda",
705 histoList->Add(h_ineffMCTC_theta);
709 histoList->Add(h_ineffMCTC_phi);
714 TH1* hNum, TH1* hDen,
bool isEffPlot,
717 TH1F* h1den =
dynamic_cast<TH1F*
>(hDen);
718 TH1F* h1num =
dynamic_cast<TH1F*
>(hNum);
719 TH2F* h2den =
dynamic_cast<TH2F*
>(hDen);
720 TH2F* h2num =
dynamic_cast<TH2F*
>(hNum);
721 TH3F* h3den =
dynamic_cast<TH3F*
>(hDen);
722 TH3F* h3num =
dynamic_cast<TH3F*
>(hNum);
728 hden =
new TH1F(*h1den);
729 hnum =
new TH1F(*h1num);
732 hden =
new TH2F(*h2den);
733 hnum =
new TH2F(*h2num);
736 hden =
new TH3F(*h3den);
737 hnum =
new TH3F(*h3num);
745 the_axis = hden->GetXaxis();
746 the_other1 = hden->GetYaxis();
747 the_other2 = hden->GetZaxis();
748 }
else if (axisRef == 1) {
749 the_axis = hden->GetYaxis();
750 the_other1 = hden->GetXaxis();
751 the_other2 = hden->GetZaxis();
752 }
else if (axisRef == 2) {
753 the_axis = hden->GetZaxis();
754 the_other1 = hden->GetXaxis();
755 the_other2 = hden->GetYaxis();
761 if (the_axis->GetXbins()->GetSize())
762 h =
new TH1F(name, title, the_axis->GetNbins(), (the_axis->GetXbins())->GetArray());
764 h =
new TH1F(name, title, the_axis->GetNbins(), the_axis->GetXmin(), the_axis->GetXmax());
765 h->GetXaxis()->SetTitle(the_axis->GetTitle());
767 h->GetYaxis()->SetRangeUser(0.00001, 1);
772 for (
int the_bin = 1; the_bin < the_axis->GetNbins() + 1; the_bin++) {
777 for (
int other1_bin = 1; other1_bin < the_other1->GetNbins() + 1; other1_bin++)
778 for (
int other2_bin = 1; other2_bin < the_other2->GetNbins() + 1; other2_bin++) {
780 if (axisRef == 0) bin = hden->GetBin(the_bin, other1_bin, other2_bin);
781 else if (axisRef == 1) bin = hden->GetBin(other1_bin, the_bin, other2_bin);
782 else if (axisRef == 2) bin = hden->GetBin(other1_bin, other2_bin, the_bin);
784 if (hden->IsBinUnderflow(bin))
785 B2DEBUG(1,
" bin = " << bin <<
"(" << the_bin <<
"," << other1_bin <<
"," << other2_bin <<
"), UNDERFLOW");
786 if (hden->IsBinOverflow(bin))
787 B2DEBUG(1,
" bin = " << bin <<
"(" << the_bin <<
"," << other1_bin <<
"," << other2_bin <<
"), OVERFLOW");
789 num += hnum->GetBinContent(bin);
790 den += hden->GetBinContent(bin);
799 eff = (double)num / den;
800 err = sqrt(eff * (1 - eff)) / sqrt(den);
804 h->SetBinContent(the_bin, eff);
805 h->SetBinError(the_bin, err);
807 h->SetBinContent(the_bin, 1 - eff);
808 h->SetBinError(the_bin, err);
820 if (hitDistance < 1.8)
822 else if (hitDistance < 3)
824 else if (hitDistance < 5)
826 else if (hitDistance < 9)
828 else if (hitDistance < 12)
832 if ((hitDistance < 3) && (hitDistance > 1.2))
833 thetaMS = thetaMS / 2;
835 double dR =
m_nSigma * dL * thetaMS;
844 double thetaMS = 0.0136 * 14;
846 double p = mcParticleInfo.
getP();
856 thetaMS = thetaMS / (p * p / E) * sqrt(X / X0 * rho);