46 #include <Eigen/Dense>
48 #include <TLorentzVector.h>
80 recomass =
new TH2D(
"recomass",
"invariant mass vs pT", 1000, 0, 5, 4000,0,2);
81 hdecaypos =
new TH2D(
"hdecaypos",
"decay radius",200, -40, 40, 200,-40,40);
82 hdecaypos->GetXaxis()->SetTitle(
"decay X (cm)");
83 hdecaypos->GetYaxis()->SetTitle(
"decay Y (cm)");
84 hdecay_radius =
new TH1D(
"hdecay_radius",
"Decay Radius", 200, 0, 40.0);
86 ntp =
new TNtuple(
"ntp",
"decay_pairs",
"x1:y1:z1:px1:py1:pz1:dca3dxy1:dca3dz1:vposx1:vposy1:vposz1:vmomx1:vmomy1:vmomz1:pca_relx_1:pca_rely_1:pca_relz_1:eta1:charge1:tpcClusters_1:quality1:eta1:x2:y2:z2:px2:py2:pz2:dca3dxy2:dca3dz2:vposx2:vposy2:vposz2:vmomx2:vmomy2:vmomz2:pca_relx_2:pca_rely_2:pca_relz_2:eta2:charge2:tpcClusters_2:quality2:eta2:vertex_x:vertex_y:vertex_z:pair_dca:invariant_mass:invariant_pt:path:has_silicon1:has_silicon2");
92 void SecondaryVertexFinder::fillNtp(
SvtxTrack *track1,
SvtxTrack *track2,
double dca3dxy1,
double dca3dz1,
double dca3dxy2,
double dca3dz2, Eigen::Vector3d vpos1, Eigen::Vector3d vmom1, Eigen::Vector3d vpos2, Eigen::Vector3d vmom2,
Acts::Vector3 pca_rel1,
Acts::Vector3 pca_rel2,
double pair_dca,
double invariantMass,
double invariantPt,
double path,
int has_silicon_1,
int has_silicon_2)
94 double px1 = track1->
get_px();
95 double py1 = track1->
get_py();
96 double pz1 = track1->
get_pz();
99 double eta1 = asinh(pz1 / sqrt(pow(px1, 2) + pow(py1, 2)));
101 double px2 = track2->
get_px();
102 double py2 = track2->
get_py();
103 double pz2 = track2->
get_pz();
106 double eta2 = asinh(pz2 / sqrt(pow(px2, 2) + pow(py2, 2)));
110 if(!svtxVertex){
return; }
112 float reco_info[] = {
115 (float) dca3dxy1, (
float) dca3dz1, (float) vpos1(0), (float) vpos1(1), (float) vpos1(2),
116 (float) vmom1(0), (float) vmom1(1), (float) vmom1(2),
117 (float) pca_rel1(0), (float) pca_rel1(1), (float) pca_rel1(2),
118 (float) eta1, (
float) track1->
get_charge(), (float) tpcClusters1,
122 (float) dca3dxy2, (
float) dca3dz2, (float) vpos2(0), (float) vpos2(1), (float) vpos2(2),
123 (float) vmom2(0), (float) vmom2(1), (float) vmom2(2),
124 (float) pca_rel2(0), (float) pca_rel2(1), (float) pca_rel2(2),
125 (float) eta2, (
float) track2->
get_charge(), (float) tpcClusters2,
127 svtxVertex->get_x(), svtxVertex->get_y(), svtxVertex->get_z(),
128 (float) pair_dca,(
float) invariantMass, (float) invariantPt, (
float)
path,
129 (float) has_silicon_1, (
float) has_silicon_2};
132 ntp->Fill(reco_info);
144 auto id1 = tr1_it->first;
145 auto tr1 = tr1_it->second;
147 auto vertexId = tr1->get_vertex_id();
152 { std::cout <<
PHWHERE <<
" Failed to find vertex id " << vertexId <<
" skip this track " << std::endl; }
160 int has_silicon_1 = 0;
166 std::cout <<
"Track1 " << id1 <<
" details: " << std::endl;
170 if(tr1->get_quality() >
_qual_cut)
continue;
172 auto tpc_seed1 = tr1->get_tpc_seed();
173 int ntpc1 = tpc_seed1->size_cluster_keys();
174 if(ntpc1 < 20)
continue;
176 float dca3dxy1, dca3dz1,dca3dxysigma1, dca3dzsigma1;
177 get_dca(tr1, dca3dxy1, dca3dz1, dca3dxysigma1, dca3dzsigma1);
182 std::cout <<
" get_dca returned NAN " << std::endl;
191 auto id2 = tr2_it->first;
192 auto tr2 = tr2_it->second;
197 int has_silicon_2 = 0;
202 std::cout <<
"Track2 " << id2 <<
" details: " << std::endl;
206 if(tr2->get_charge() == tr1->get_charge())
continue;
208 if(tr2->get_quality() >
_qual_cut)
continue;
210 auto tpc2_seed = tr2->get_tpc_seed();
211 int ntpc2 = tpc2_seed->size_cluster_keys();
212 if(ntpc2 < 20)
continue;
214 float dca3dxy2, dca3dz2,dca3dxysigma2, dca3dzsigma2;
215 get_dca(tr2, dca3dxy2, dca3dz2, dca3dxysigma2, dca3dzsigma2);
219 std::cout <<
" get_dca returned NAN " << std::endl;
227 { std::cout <<
"Check pair DCA for tracks " << id1 <<
" and " << id2 << std::endl;}
230 Eigen::Vector2d center1;
234 std::cout << std::endl <<
"Track 1 circle: " << std::endl;
235 std::cout <<
" tr1.x " << tr1->get_x() <<
" tr1.y " << tr1->get_y() <<
" tr1.z " << tr1->get_z() <<
" charge " << tr1->get_charge() << std::endl;
236 std::cout <<
" tr1.px " << tr1->get_px() <<
" tr1.py " << tr1->get_py() <<
" tr1.pz " << tr1->get_pz() << std::endl;
237 std::cout <<
" track1 " << tr1->get_id() <<
" circle R " << R1 <<
" (x, y) " << center1(0) <<
" " << center1(1) << std::endl;
240 Eigen::Vector2d center2;
244 std::cout <<
"Track 2 circle: " << std::endl;
245 std::cout <<
" tr2.x " << tr2->get_x() <<
" tr2.y " << tr2->get_y() <<
" tr2.z " << tr2->get_z() <<
" charge " << tr2->get_charge() << std::endl;
246 std::cout <<
" tr2.px " << tr2->get_px() <<
" tr2.py " << tr2->get_py() <<
" tr2.pz " << tr2->get_pz() << std::endl;
247 std::cout <<
" track2 " << tr2->get_id() <<
" circle R " << R2 <<
" (x, y) " << center2(0) <<
" " << center2(1) << std::endl;
250 std::vector<double> intersections;
253 if(
Verbosity() > 2) std::cout <<
" - no intersections, skip this pair" << std::endl;
257 Eigen::Vector2d intersection[2];
258 if(intersections.size() == 2)
260 intersection[0](0) = intersections[0];
261 intersection[0](1) = intersections[1];
263 if(intersections.size() == 4)
265 intersection[1](0) = intersections[2];
266 intersection[1](1) = intersections[3];
270 for(
int i=0;
i<2; ++
i)
272 if(intersection[
i].
norm() == 0)
continue;
274 double vradius = sqrt(intersection[
i](0)*intersection[
i](0) + intersection[
i](1) * intersection[
i](1));
280 std::cout <<
" track intersection " << i <<
" at (x,y) " << intersection[
i](0) <<
" " << intersection[i](1)
281 <<
" radius " << vradius <<
" est. z1 " << z1 <<
" est. z2 " << z2 << std::endl;
283 if( fabs(z1-z2) > 2.0)
285 if(
Verbosity() > 2) std::cout <<
" z-mismatch - wrong intersection, skip it " << std::endl;
289 Eigen::Vector3d vpos1(0,0,0), vmom1(0,0,0);
290 Eigen::Vector3d vpos2(0,0,0), vmom2(0,0,0);
293 Eigen::Vector3d intersect1(intersection[i](0), intersection[i](1), z1);
297 std::cout <<
" Projected track 1 to point " << intersect1(0) <<
" " << intersect1(1) <<
" " << intersect1(2) << std::endl;
298 std::cout <<
" has vpos " << vpos1(0) <<
" " << vpos1(1) <<
" " << vpos1(2) << std::endl;
300 Eigen::Vector3d intersect2(intersection[i](0), intersection[i](1), z2);
304 std::cout <<
" Projected track 2 to point " << intersect2(0) <<
" " << intersect2(1) <<
" " << intersect2(2) << std::endl;
305 std::cout <<
" has vpos " << vpos2(0) <<
" " << vpos2(1) <<
" " << vpos2(2) << std::endl;
312 { std::cout <<
" Warning: projected z positions are screwed up, should not be" << std::endl; }
318 std::cout <<
"Summary for projected pair:" << std::endl;
319 std::cout <<
" Fitted tracks: " << std::endl;
320 std::cout <<
" tr1.x " << tr1->get_x() <<
" tr1.y " << tr1->get_y() <<
" tr1.z " << tr1->get_z() << std::endl;
321 std::cout <<
" tr2.x " << tr2->get_x() <<
" tr2.y " << tr2->get_y() <<
" tr2.z " << tr2->get_z() << std::endl;
322 std::cout <<
" tr1.px " << tr1->get_px() <<
" tr1.py " << tr1->get_py() <<
" tr1.pz " << tr1->get_pz() << std::endl;
323 std::cout <<
" tr2.px " << tr2->get_px() <<
" tr2.py " << tr2->get_py() <<
" tr2.pz " << tr2->get_pz() << std::endl;
324 std::cout <<
" Projected tracks: " << std::endl;
325 std::cout <<
" pos1.x " << vpos1(0) <<
" pos1.y " << vpos1(1) <<
" pos1.z " << vpos1(2) << std::endl;
326 std::cout <<
" pos2.x " << vpos2(0) <<
" pos2.y " << vpos2(1) <<
" pos2.z " << vpos2(2) << std::endl;
327 std::cout <<
" mom1.x " << vmom1(0) <<
" mom1.y " << vmom1(1) <<
" mom1.z " << vmom1(2) << std::endl;
328 std::cout <<
" mom2.x " << vmom2(0) <<
" mom2.y " << vmom2(1) <<
" mom2.z " << vmom2(2) << std::endl;
333 Eigen::Vector3d PCA1(0,0,0), PCA2(0,0,0);
337 std::cout <<
" pair_dca " << pair_dca <<
" two_track_dcacut " <<
_two_track_dcacut << std::endl;
338 std::cout <<
" PCA1 " << PCA1(0) <<
" " << PCA1(1) <<
" " << PCA1(2) << std::endl;
339 std::cout <<
" PCA2 " << PCA2(0) <<
" " << PCA2(1) <<
" " << PCA2(2) << std::endl;
347 Float_t E1 = sqrt(pow(vmom1(0),2) + pow(vmom1(1),2) + pow(vmom1(2),2)
349 t1.SetPxPyPzE(vmom1(0),vmom1(1),vmom1(2),E1);
352 Float_t E2 = sqrt(pow(vmom2(0),2) + pow(vmom2(1),2) + pow(vmom2(2),2)
354 t2.SetPxPyPzE(vmom2(0),vmom2(1),vmom2(2),E2);
356 TLorentzVector tsum = t1+
t2;
359 Eigen::Vector3d PCA = (vpos1+vpos2) / 2.0;
360 auto vtxid = tr1->get_vertex_id();
362 Eigen::Vector3d VTX(vertex1->get_x(), vertex1->get_y(), vertex1->get_z());
363 Eigen::Vector3d
path = PCA - VTX;
364 double decay_radius = sqrt( pow(PCA(0),2) + pow(PCA(1),2) );
370 std::cout <<
" Pair mass " << tsum.M() <<
" pair pT " << tsum.Pt()
371 <<
" decay length " << path.norm() << std::endl;
376 fillNtp(tr1, tr2, dca3dxy1, dca3dz1, dca3dxy2, dca3dz2, vpos1, vmom1, vpos2, vmom2,
377 PCA1, PCA2, pair_dca, tsum.M(), tsum.Pt(), path.norm(), has_silicon_1, has_silicon_2);
385 std::cout <<
" **** inserting tracks " << tr1->get_id() <<
" and " << tr2->get_id() << std::endl;
394 recomass->Fill(tsum.Pt(), tsum.M());
411 auto id = tr_it->first;
412 auto tr = tr_it->second;
414 std::cout <<
" Electron track " <<
id
415 <<
" x " << tr->get_x() <<
" y " << tr->get_y() <<
" z " << tr->get_z()
416 <<
" px " << tr->get_px() <<
" py " << tr->get_py() <<
" pz " << tr->get_pz()
442 Eigen::Vector3d
path = PCA - VTX;
443 if(path.norm() < 0.2) {
return pass;}
446 Eigen::Vector3d invariant_mom(tsum.Px(), tsum.Py(), tsum.Pz());
447 double costheta = path.dot(invariant_mom) / (path.norm() * invariant_mom.norm());
465 double phi0 = atan2(track->
get_y() - center(1), track->
get_x() - center(0));
466 double phi1 = atan2(intersection(1) - center(1), intersection(0) - center(0));
467 double xypath = R * fabs(phi1-phi0);
469 double zpath = xypath * track->
get_pz() / track->
get_pt();
470 double z = track->
get_z() + zpath;
473 std::cout <<
" Radius " << R <<
" center xy " << center(0) <<
" " << center(1) <<
" pT " << track->
get_pt() <<
" pz " << track->
get_pz() << std::endl;
474 std::cout <<
" phi0 " << phi0 <<
" y0 " << track->
get_y() <<
" x0 " << track->
get_x() << std::endl;
475 std::cout <<
" phi1 " << phi1 <<
" intersection y " << intersection(1) <<
" intersection x " << intersection(0) << std::endl;
476 std::cout <<
" xypath " << xypath <<
" zpath " << zpath <<
" z0 " << track->
get_z() <<
" z " << z << std::endl;
486 double x = track->
get_x();
487 double y = track->
get_y();
488 double px = track->
get_px();
489 double py = track->
get_py();
494 R = 3.3 * pt / (Bz * (
double) charge) * 100;
497 Eigen::Vector2d normal(py, -px);
498 normal /= normal.norm();
501 Eigen::Vector2d base(x,y);
502 center = base + R*normal;
518 auto perigee = Acts::Surface::makeShared<Acts::PerigeeSurface>(PCA);
529 auto result = propagator.propagateTrack(params.value(), perigee); \
532 auto resultparams = result.value().second;
534 const auto momentum = resultparams.momentum();
547 std::cout <<
" Failed projection of track with: " << std::endl;
548 std::cout <<
" x,y,z = " << track->
get_x() <<
" " << track->
get_y() <<
" " << track->
get_z() << std::endl;
549 std::cout <<
" px,py,pz = " << track->
get_px() <<
" " << track->
get_py() <<
" " << track->
get_pz() << std::endl;
579 std::cout <<
" ntpc " << ntpc <<
" nsilicon " << nsilicon <<
" quality " << qual
580 <<
" eta " <<
eta << std::endl;
581 std::cout <<
" pt " <<
pt <<
" x " <<
x <<
" y " <<
y <<
" z " <<
z << std::endl;
585 std::cout <<
" vtxid " << vtxid
586 <<
" vertex x " <<
vertex->get_x()
587 <<
" vertex y " <<
vertex->get_y()
588 <<
" vertex z " <<
vertex->get_z()
597 if(silicon_seed) ret =
true;
603 float& dca3dxy,
float& dca3dz,
604 float& dca3dxysigma,
float& dca3dzsigma)
618 std::cout <<
" Failed to find vertex for track " << std::endl;
624 svtxVertex->get_z());
628 std::cout <<
" track " << track->
get_id() <<
" vertex id is " << vtxid
629 <<
" vertex is " << svtxVertex->get_x() <<
" "
630 << svtxVertex->get_y() <<
" "
631 << svtxVertex->get_z() << std::endl;
637 for(
int i = 0;
i < 3; ++
i)
639 for(
int j = 0;
j < 3; ++
j)
646 float phi = atan2(
r(1),
r(0));
652 rot(0,1) = -sin(phi);
661 rot_T = rot.transpose();
668 dca3dxysigma = sqrt(rotCov(0,0));
669 dca3dzsigma = sqrt(rotCov(2,2));
673 double &
dca, Eigen::Vector3d &PCA1, Eigen::Vector3d &PCA2)
675 Eigen::Vector3d a1(pos1(0), pos1(1), pos1(2));
676 Eigen::Vector3d
b1(mom1(0) / mom1.norm(), mom1(1) / mom1.norm(), mom1(2) / mom1.norm());
677 Eigen::Vector3d
a2(pos2(0), pos2(1), pos2(2));
678 Eigen::Vector3d b2(mom2(0) / mom2.norm(), mom2(1) / mom2.norm(), mom2(2) / mom2.norm());
687 auto bcrossb =
b1.cross(b2);
688 auto mag_bcrossb = bcrossb.norm();
690 auto aminusa = a2-a1;
695 if( mag_bcrossb != 0)
696 dca = bcrossb.dot(aminusa) / mag_bcrossb;
702 double X =
b1.dot(b2) -
b1.dot(
b1) * b2.dot(b2) / b2.dot(
b1);
703 double Y = (a2.dot(b2) - a1.dot(b2)) - (a2.dot(
b1) - a1.dot(
b1)) * b2.dot(b2) / b2.dot(
b1) ;
706 double F =
b1.dot(
b1) / b2.dot(
b1);
707 double G = - (a2.dot(
b1) - a1.dot(
b1)) / b2.dot(
b1);
708 double d = c * F + G;
726 Eigen::Vector2d p0(x0,y0);
727 Eigen::Vector2d p1(x1,y1);
729 double d = (p0 - p1).
norm();
734 if(d < fabs(r1-r0))
return false;
741 if( fabs(d - (r0+r1)) < dr)
744 Eigen::Vector2d u0 = (p1 - p0);
746 Eigen::Vector2d PCA0 = p0 + u0 *
r0;
748 Eigen::Vector2d u1 = (p0 - p1);
750 Eigen::Vector2d PCA1 = p1 + u1 *
r1;
752 auto PCA = (PCA0+PCA1) / 2.0;
753 intersectionXY.push_back(PCA(0));
754 intersectionXY.push_back(PCA(1));
756 if(
Verbosity() > 2) std::cout <<
" *** Special case: Barely touching circles: " <<
" PCA.x, PCA.y " << PCA(0) <<
" " << PCA(1) << std::endl;
763 double a=(r0*r0-r1*r1+d*d)/(2*d);
764 double h = sqrt(r0*r0 - a*a);
766 double x2= x0 + a*(x1-
x0)/d;
767 double y2=y0+a*(y1-y0)/d;
769 double x3a=x2+h*(y1-y0)/d;
770 double y3a=y2-h*(x1-
x0)/d;
772 double x3b=x2-h*(y1-y0)/d;
773 double y3b=y2+h*(x1-
x0)/d;
775 intersectionXY.push_back(x3a);
776 intersectionXY.push_back(y3a);
777 intersectionXY.push_back(x3b);
778 intersectionXY.push_back(y3b);
788 TFile *
fout =
new TFile(
outfile.c_str(),
"recreate");
808 std::cerr <<
"DST node is missing, quitting" << std::endl;
809 throw std::runtime_error(
"Failed to find DST node in SecondaryVertexFinder");
825 svtxNode->
addNode(tracks_node);
827 { std::cout <<
"Svtx/SvtxTrackMapElectrons node added" << std::endl; }
836 _track_map = findNode::getClass<SvtxTrackMap>(topNode,
"SvtxTrackMap");
839 std::cout <<
PHWHERE <<
" ERROR: Can't find SvtxTrackMap: " << std::endl;
852 _svtx_vertex_map = findNode::getClass<SvtxVertexMap>(topNode,
"SvtxVertexMap");
855 std::cout <<
PHWHERE <<
"No vertex node, quit!" << std::endl;
859 _tGeometry = findNode::getClass<ActsGeometry>(topNode,
"ActsGeometry");
862 std::cout <<
PHWHERE <<
"Error, can't find acts tracking geometry" << std::endl;