45 #include <TDatabasePDG.h>
47 #include <TMatrixDfwd.h>
50 #include <Eigen/Dense>
62 : m_has_intermediates(
false)
65 , m_min_decayTime(-1 * FLT_MAX)
66 , m_max_decayTime(FLT_MAX)
67 , m_min_decayLength(-1 * FLT_MAX)
68 , m_max_decayLength(FLT_MAX)
70 , m_track_ptchi2(FLT_MAX)
73 , m_track_chi2ndof(4.)
77 , m_vertex_chi2ndof(15.)
82 , m_mother_ipchi2(FLT_MAX)
83 , m_get_charge_conjugate(
true)
84 , m_extrapolateTracksToSV(
true)
85 , m_vtx_map_node_name(
"SvtxVertexMap")
86 , m_trk_map_node_name(
"SvtxTrackMap")
100 float f_vertexCovariance[21];
101 unsigned int iterate = 0;
102 for (
unsigned int i = 0;
i < 3; ++
i)
104 for (
unsigned int j = 0;
j <=
i; ++
j)
112 kfp_vertex.
Create(f_vertexParameters, f_vertexCovariance, 0, -1);
122 if (vertexMapName.empty())
128 vtxMN = vertexMapName;
131 std::vector<KFParticle> primaryVertices;
133 auto globalvertexmap = findNode::getClass<GlobalVertexMap>(topNode,
"GlobalVertexMap");
134 if (!globalvertexmap)
136 std::cout <<
"Can't continue in KFParticle_Tools::makeAllPrimaryVertices" << std::endl;
139 unsigned int vertexID = 0;
151 auto svtxvertexvector = svtxiter->second;
153 for (
auto &
vertex : svtxvertexvector)
157 primaryVertices.push_back(
makeVertex(topNode));
158 primaryVertices[vertexID].SetId(gvertex->
get_id());
163 return primaryVertices;
177 float f_trackCovariance[21];
178 unsigned int iterate = 0;
179 for (
unsigned int i = 0;
i < 6; ++
i)
181 for (
unsigned int j = 0;
j <=
i; ++
j)
198 std::vector<KFParticle> daughterParticles;
217 const auto &cluster_key = *cluster_iter;
234 const auto &cluster_key = *cluster_iter;
249 daughterParticles[
trackID].SetId(iter.first);
253 return daughterParticles;
259 if (vertexMapName.empty())
265 vtxMN = vertexMapName;
270 auto globalvertexmap = findNode::getClass<GlobalVertexMap>(topNode,
"GlobalVertexMap");
271 GlobalVertex *associatedgvertex = globalvertexmap->find(vertex.
Id())->second;
280 bool goodTrack =
false;
283 float min_ipchi2 = 0;
287 float ptchi2 = pow(pterr / pt, 2);
288 float trackchi2ndof = particle.
GetChi2() / particle.
GetNDF();
289 calcMinIP(particle, primaryVertices, min_ip, min_ipchi2);
308 float &minimumIP,
float &minimumIPchi2)
310 std::vector<float> ip, ipchi2;
312 for (
const auto &PV : PVs)
320 ipchi2.push_back(thisIPchi2);
323 auto minmax_ip = minmax_element(ip.begin(), ip.end());
324 minimumIP = *minmax_ip.first;
325 auto minmax_ipchi2 = minmax_element(ipchi2.begin(), ipchi2.end());
326 minimumIPchi2 = *minmax_ipchi2.first;
333 std::vector<int> goodTrackIndex;
335 for (
unsigned int i_parts = 0; i_parts < daughterParticles.size(); ++i_parts)
337 if (
isGoodTrack(daughterParticles[i_parts], primaryVertices))
339 goodTrackIndex.push_back(i_parts);
345 return goodTrackIndex;
350 std::vector<std::vector<int>> goodTracksThatMeet;
352 for (std::vector<int>::iterator i_it = goodTrackIndex.begin(); i_it != goodTrackIndex.end(); ++i_it)
354 for (std::vector<int>::iterator j_it = goodTrackIndex.begin(); j_it != goodTrackIndex.end(); ++j_it)
361 twoParticleVertex += daughterParticles[*i_it];
362 twoParticleVertex += daughterParticles[*j_it];
363 float vertexchi2ndof = twoParticleVertex.
GetChi2() / twoParticleVertex.
GetNDF();
364 std::vector<int> combination = {*i_it, *j_it};
372 goodTracksThatMeet.push_back(combination);
379 return goodTracksThatMeet;
383 const std::vector<int> &goodTrackIndex,
384 std::vector<std::vector<int>> goodTracksThatMeet,
385 int nRequiredTracks,
unsigned int nProngs)
387 unsigned int nGoodProngs = goodTracksThatMeet.size();
389 for (
auto &i_it : goodTrackIndex)
391 for (
unsigned int i_prongs = 0; i_prongs < nGoodProngs; ++i_prongs)
393 bool trackNotUsedAlready =
true;
394 for (
unsigned int i_trackCheck = 0; i_trackCheck < nProngs - 1; ++i_trackCheck)
396 if (i_it == goodTracksThatMeet[i_prongs][i_trackCheck])
398 trackNotUsedAlready =
false;
401 if (trackNotUsedAlready)
404 for (
unsigned int i = 0;
i < nProngs - 1; ++
i)
415 particleVertex += daughterParticles[i_it];
416 std::vector<int> combination;
417 combination.push_back(i_it);
418 for (
unsigned int i = 0;
i < nProngs - 1; ++
i)
420 particleVertex += daughterParticles[goodTracksThatMeet[i_prongs][
i]];
421 combination.push_back(goodTracksThatMeet[i_prongs][
i]);
423 float vertexchi2ndof = particleVertex.
GetChi2() / particleVertex.
GetNDF();
425 if ((
unsigned int) nRequiredTracks == nProngs && vertexchi2ndof >
m_vertex_chi2ndof)
431 goodTracksThatMeet.push_back(combination);
438 goodTracksThatMeet.erase(goodTracksThatMeet.begin(), goodTracksThatMeet.begin() + nGoodProngs);
439 for (
auto &
i : goodTracksThatMeet)
445 return goodTracksThatMeet;
450 std::vector<std::vector<int>> goodTracksThatMeet, goodTracksThatMeetIntermediates;
451 if (num_remaining_tracks == 1)
453 for (
auto &i_it : goodTrackIndex)
455 std::vector<KFParticle> v_intermediateResonances(intermediateResonances, intermediateResonances +
m_num_intermediate_states);
456 std::vector<std::vector<int>> dummyTrackList;
457 std::vector<int> dummyTrackID;
458 v_intermediateResonances.insert(
end(v_intermediateResonances), daughterParticles[i_it]);
459 for (
unsigned int k = 0;
k < v_intermediateResonances.size(); ++
k)
461 dummyTrackID.push_back(
k);
463 dummyTrackList =
findTwoProngs(v_intermediateResonances, dummyTrackID, (
int) v_intermediateResonances.size());
464 if (v_intermediateResonances.size() > 2)
466 for (
unsigned int p = 3;
p <= v_intermediateResonances.size(); ++
p)
468 dummyTrackList =
findNProngs(v_intermediateResonances,
469 dummyTrackID, dummyTrackList,
470 (
int) v_intermediateResonances.size(), (int)
p);
474 if (dummyTrackList.size() != 0)
476 std::vector<int> goodTrack{i_it};
477 goodTracksThatMeetIntermediates.push_back(goodTrack);
483 goodTracksThatMeet =
findTwoProngs(daughterParticles, goodTrackIndex, num_remaining_tracks);
485 for (
int p = 3;
p <= num_remaining_tracks; ++
p)
487 goodTracksThatMeet =
findNProngs(daughterParticles, goodTrackIndex, goodTracksThatMeet, num_remaining_tracks,
p);
490 for (
auto &
i : goodTracksThatMeet)
492 std::vector<KFParticle> v_intermediateResonances(intermediateResonances, intermediateResonances +
m_num_intermediate_states);
493 std::vector<std::vector<int>> dummyTrackList;
494 std::vector<int> dummyTrackID;
497 v_intermediateResonances.push_back(daughterParticles[i[
j]]);
499 for (
unsigned int k = 0;
k < v_intermediateResonances.size(); ++
k)
501 dummyTrackID.push_back(
k);
503 dummyTrackList =
findTwoProngs(v_intermediateResonances, dummyTrackID, (
int) v_intermediateResonances.size());
504 for (
unsigned int p = 3;
p <= v_intermediateResonances.size(); ++
p)
506 dummyTrackList =
findNProngs(v_intermediateResonances, dummyTrackID, dummyTrackList, (
int) v_intermediateResonances.size(), (int)
p);
509 if (dummyTrackList.size() != 0)
511 goodTracksThatMeetIntermediates.push_back(i);
516 return goodTracksThatMeetIntermediates;
521 TMatrixD flightVector(3, 1);
522 TMatrixD momVector(3, 1);
523 flightVector(0, 0) = particle.
GetX() - vertex.
GetX();
524 flightVector(1, 0) = particle.
GetY() - vertex.
GetY();
525 flightVector(2, 0) = particle.
GetZ() - vertex.
GetZ();
527 momVector(0, 0) = particle.
GetPx();
528 momVector(1, 0) = particle.
GetPy();
529 momVector(2, 0) = particle.
GetPz();
531 TMatrixD momDotFD(1, 1);
532 momDotFD = TMatrixD(momVector, TMatrixD::kTransposeMult, flightVector);
533 float f_momDotFD = momDotFD(0, 0);
535 TMatrixD sizeOfMom(1, 1);
536 sizeOfMom = TMatrixD(momVector, TMatrixD::kTransposeMult, momVector);
537 float f_sizeOfMom = sqrt(sizeOfMom(0, 0));
539 TMatrixD sizeOfFD(1, 1);
540 sizeOfFD = TMatrixD(flightVector, TMatrixD::kTransposeMult, flightVector);
541 float f_sizeOfFD = sqrt(sizeOfFD(0, 0));
543 return f_momDotFD / (f_sizeOfMom * f_sizeOfFD);
548 TMatrixD flightVector(3, 1);
549 TMatrixD flightDistanceCovariance(3, 3);
553 flightVector(0, 0) = particle.
GetX() - kfp_vertex.
GetX();
554 flightVector(1, 0) = particle.
GetY() - kfp_vertex.
GetY();
555 flightVector(2, 0) = particle.
GetZ() - kfp_vertex.
GetZ();
557 for (
int i = 0;
i < 3;
i++)
559 for (
int j = 0;
j < 3;
j++)
565 TMatrixD anInverseMatrix(3, 3);
566 anInverseMatrix = flightDistanceCovariance.Invert();
567 TMatrixD m_chi2Value(1, 1);
568 m_chi2Value = TMatrixD(flightVector, TMatrixD::kTransposeMult, anInverseMatrix * flightVector);
569 return m_chi2Value(0, 0);
573 bool isIntermediate,
int intermediateNumber,
int nTracks,
574 bool constrainMass,
float required_vertexID)
581 bool daughterMassCheck =
true;
582 float unique_vertexID = 0;
585 int num_tracks_used_by_intermediates = 0;
590 int num_remaining_tracks =
m_num_tracks - num_tracks_used_by_intermediates;
592 for (
int i = 0;
i < nTracks; ++
i)
594 float daughterMass = 0;
596 if ((num_remaining_tracks > 0 &&
i >= m_num_intermediate_states) || isIntermediate)
600 inputTracks[
i].
Create(vDaughters[
i].Parameters(),
601 vDaughters[
i].CovarianceMatrix(),
602 (Int_t) vDaughters[
i].
GetQ(),
620 chargeCheck = std::abs(unique_vertexID) == std::abs(required_vertexID) ?
true :
false;
624 chargeCheck = unique_vertexID == required_vertexID ?
true :
false;
627 for (
int j = 0;
j < nTracks; ++
j)
637 daughterMassCheck =
false;
642 float calculated_mass, calculated_mass_err;
643 mother.
GetMass(calculated_mass, calculated_mass_err);
644 float calculated_pt = mother.
GetPt();
652 bool goodCandidate =
false;
653 if (calculated_mass >= min_mass && calculated_mass <= max_mass &&
654 calculated_pt >= min_pt && daughterMassCheck && chargeCheck &&
calculateEllipsoidVolume(mother) <= max_vertex_volume)
656 goodCandidate =
true;
664 float intermediate_DIRA =
eventDIRA(vDaughters[
k], mother);
669 goodCandidate =
false;
683 float calculated_decayTime;
684 float calculated_decayTimeErr;
685 float calculated_decayLength;
686 float calculated_decayLengthErr;
688 particleCopy.
GetLifeTime(calculated_decayTime, calculated_decayTimeErr);
689 particleCopy.
GetDecayLength(calculated_decayLength, calculated_decayLengthErr);
692 float calculated_dira =
eventDIRA(particle, vertex);
695 goodCandidate =
false;
697 const float speed = 2.99792458e-2;
698 calculated_decayTime /= speed;
702 goodCandidate =
true;
709 bool isGoodCandidate;
711 std::tie(candidate, isGoodCandidate) =
buildMother(vDaughters, daughterOrder, isIntermediate, intermediateNumber, nTracks, constrainMass, required_vertexID);
713 if (constrain_to_vertex && isGoodCandidate && !isIntermediate)
723 std::vector<int> vect_permutations;
724 std::vector<std::vector<std::string>> uniqueCombinations;
725 std::map<int, std::string> daughterMap;
726 for (
int i = start;
i <
end;
i++)
729 vect_permutations.push_back(i);
731 int *permutations = &vect_permutations[0];
735 std::vector<std::string> combination;
736 combination.reserve((end - start));
737 for (
int i = 0;
i < (end -
start);
i++)
739 combination.push_back(daughterMap.find(permutations[
i])->second);
741 uniqueCombinations.push_back(combination);
742 }
while (std::next_permutation(permutations, permutations + vect_permutations.size()));
746 return uniqueCombinations;
751 if (std::abs(posOrNeg) != 1)
753 std::cout <<
"You have set posOrNeg to " << posOrNeg <<
". This value must be +/- 1! Skipping" << std::endl;
757 double r_ij = sqrt((sigma_ii + sigma_jj) / 2 + posOrNeg * (sqrt(pow((sigma_ii - sigma_jj) / 2, 2) + pow(sigma_ij, 2))));
764 TMatrixD cov_matrix(3, 3);
766 for (
int i = 0;
i < 3; ++
i)
768 for (
int j = 0;
j < 3; ++
j)
775 if (cov_matrix(0, 0) * cov_matrix(1, 1) * cov_matrix(2, 2) == 0)
781 volume = (4. / 3.) * M_PI * sqrt((std::abs(cov_matrix.Determinant())));
789 Eigen::Vector3f motherP = Eigen::Vector3f(mother.
GetPx(), mother.
GetPy(), mother.
GetPz());
790 Eigen::Vector3f daughterP = Eigen::Vector3f(daughter.
GetPx(), daughter.
GetPy(), daughter.
GetPz());
792 Eigen::Vector3f motherP_X_daughterP = motherP.cross(daughterP);
794 float jT = (motherP_X_daughterP.norm()) / motherP.norm();
801 return min <= value && value <= max;
807 for (
auto it = v.begin();
it !=
end; ++
it)
811 v.erase(
end, v.end());
817 for (
auto it = v.begin();
it !=
end; ++
it)
821 v.erase(
end, v.end());
831 v.erase(
end,
v.end());
841 v.erase(
end,
v.end());
846 bool particleFound =
true;
847 if (!TDatabasePDG::Instance()->GetParticle(particle.c_str()))
849 std::cout <<
"The particle, " << particle <<
" is not recognized" << std::endl;
850 std::cout <<
"Check TDatabasePDG for a list of available particles" << std::endl;
851 particleFound =
false;
854 return particleFound;
859 return TDatabasePDG::Instance()->GetParticle(particle.c_str())->PdgCode();
864 return TDatabasePDG::Instance()->GetParticle(particle.c_str())->Mass();
869 return TDatabasePDG::Instance()->GetParticle(PDGID)->Mass();
874 std::cout <<
"Track ID: " << particle.
Id() << std::endl;
875 std::cout <<
"PDG ID: " << particle.
GetPDG() <<
", charge: " << (int) particle.
GetQ() <<
", mass: " << particle.
GetMass() <<
" GeV" << std::endl;
876 std::cout <<
"(px,py,pz) = (" << particle.
GetPx() <<
" +/- " << std::sqrt(particle.
GetCovariance(3, 3)) <<
", ";
877 std::cout << particle.
GetPy() <<
" +/- " << std::sqrt(particle.
GetCovariance(4, 4)) <<
", ";
878 std::cout << particle.
GetPz() <<
" +/- " << std::sqrt(particle.
GetCovariance(5, 5)) <<
") GeV" << std::endl;
879 std::cout <<
"(x,y,z) = (" << particle.
GetX() <<
" +/- " << std::sqrt(particle.
GetCovariance(0, 0)) <<
", ";
880 std::cout << particle.
GetY() <<
" +/- " << std::sqrt(particle.
GetCovariance(1, 1)) <<
", ";
881 std::cout << particle.
GetZ() <<
" +/- " << std::sqrt(particle.
GetCovariance(2, 2)) <<
") cm\n"