File indexing completed on 2025-08-06 08:17:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include "KFParticle_eventReconstruction.h"
0029 #include "KFParticle_Tools.h"
0030 #include "KFParticle_truthAndDetTools.h"
0031
0032
0033 #include <trackbase_historic/SvtxTrack.h>
0034
0035
0036 #include <KFParticle.h>
0037
0038 #include <algorithm>
0039 #include <cassert>
0040 #include <iterator> // for begin, distance, end
0041 #include <memory> // for allocator_traits<>::value_type
0042 #include <string> // for string
0043 #include <tuple> // for tie, tuple
0044
0045 #include <iostream>
0046
0047
0048 KFParticle_Tools kfp_Tools_evtReco;
0049
0050
0051 KFParticle_eventReconstruction::KFParticle_eventReconstruction()
0052 : m_constrain_to_vertex(false)
0053 , m_constrain_int_mass(false)
0054 , m_use_fake_pv(false)
0055 {
0056 }
0057
0058 void KFParticle_eventReconstruction::createDecay(PHCompositeNode* topNode, std::vector<KFParticle>& selectedMother, std::vector<KFParticle>& selectedVertex,
0059 std::vector<std::vector<KFParticle>>& selectedDaughters,
0060 std::vector<std::vector<KFParticle>>& selectedIntermediates,
0061 int& nPVs)
0062 {
0063 std::vector<KFParticle> primaryVertices;
0064 if (m_use_fake_pv)
0065 {
0066 primaryVertices.push_back(createFakePV());
0067 }
0068 else
0069 {
0070 primaryVertices = makeAllPrimaryVertices(topNode, m_vtx_map_node_name);
0071 }
0072
0073 std::vector<KFParticle> daughterParticles = makeAllDaughterParticles(topNode);
0074
0075 nPVs = primaryVertices.size();
0076
0077 std::vector<int> goodTrackIndex = findAllGoodTracks(daughterParticles, primaryVertices);
0078
0079 if (!m_has_intermediates)
0080 {
0081 buildBasicChain(selectedMother, selectedVertex, selectedDaughters, daughterParticles, goodTrackIndex, primaryVertices, topNode);
0082 }
0083 else
0084 {
0085 buildChain(selectedMother, selectedVertex, selectedDaughters, selectedIntermediates, daughterParticles, goodTrackIndex, primaryVertices, topNode);
0086 }
0087 }
0088
0089
0090
0091
0092 void KFParticle_eventReconstruction::buildBasicChain(std::vector<KFParticle>& selectedMotherBasic,
0093 std::vector<KFParticle>& selectedVertexBasic,
0094 std::vector<std::vector<KFParticle>>& selectedDaughtersBasic,
0095 const std::vector<KFParticle>& daughterParticlesBasic,
0096 const std::vector<int>& goodTrackIndexBasic,
0097 const std::vector<KFParticle>& primaryVerticesBasic, PHCompositeNode* topNode)
0098 {
0099 std::vector<std::vector<int>> goodTracksThatMeet = findTwoProngs(daughterParticlesBasic, goodTrackIndexBasic, m_num_tracks);
0100 for (int p = 3; p < m_num_tracks + 1; ++p)
0101 {
0102 goodTracksThatMeet = findNProngs(daughterParticlesBasic, goodTrackIndexBasic, goodTracksThatMeet, m_num_tracks, p);
0103 }
0104
0105 getCandidateDecay(selectedMotherBasic, selectedVertexBasic, selectedDaughtersBasic, daughterParticlesBasic,
0106 goodTracksThatMeet, primaryVerticesBasic, 0, m_num_tracks, false, 0, true, topNode);
0107 }
0108
0109
0110
0111
0112 void KFParticle_eventReconstruction::buildChain(std::vector<KFParticle>& selectedMotherAdv,
0113 std::vector<KFParticle>& selectedVertexAdv,
0114 std::vector<std::vector<KFParticle>>& selectedDaughtersAdv,
0115 std::vector<std::vector<KFParticle>>& selectedIntermediatesAdv,
0116 const std::vector<KFParticle>& daughterParticlesAdv,
0117 const std::vector<int>& goodTrackIndexAdv,
0118 const std::vector<KFParticle>& primaryVerticesAdv, PHCompositeNode* topNode)
0119 {
0120 int track_start = 0;
0121 int track_stop = m_num_tracks_from_intermediate[0];
0122 std::vector<KFParticle> goodCandidates;
0123 std::vector<KFParticle> goodVertex;
0124 std::vector<KFParticle> *goodDaughters = new std::vector<KFParticle>[m_num_tracks];
0125 std::vector<KFParticle> *goodIntermediates = new std::vector<KFParticle>[m_num_intermediate_states];
0126 std::vector<KFParticle> *potentialIntermediates = new std::vector<KFParticle>[m_num_intermediate_states];
0127 std::vector<std::vector<KFParticle>> *potentialDaughters = new std::vector<std::vector<KFParticle>>[m_num_intermediate_states];
0128 for (int i = 0; i < m_num_intermediate_states; ++i)
0129 {
0130 std::vector<KFParticle> vertices;
0131 std::vector<std::vector<int>> goodTracksThatMeet = findTwoProngs(daughterParticlesAdv, goodTrackIndexAdv, m_num_tracks_from_intermediate[i]);
0132 for (int p = 3; p <= m_num_tracks_from_intermediate[i]; ++p)
0133 {
0134 goodTracksThatMeet = findNProngs(daughterParticlesAdv,
0135 goodTrackIndexAdv,
0136 goodTracksThatMeet,
0137 m_num_tracks_from_intermediate[i], p);
0138 }
0139 getCandidateDecay(potentialIntermediates[i], vertices, potentialDaughters[i], daughterParticlesAdv,
0140 goodTracksThatMeet, primaryVerticesAdv, track_start, track_stop, true, i, m_constrain_int_mass, topNode);
0141 track_start += track_stop;
0142 track_stop += m_num_tracks_from_intermediate[i + 1];
0143 }
0144 int num_tracks_used_by_intermediates = 0;
0145 for (int i = 0; i < m_num_intermediate_states; ++i)
0146 {
0147 num_tracks_used_by_intermediates += m_num_tracks_from_intermediate[i];
0148 }
0149
0150 int num_remaining_tracks = m_num_tracks - num_tracks_used_by_intermediates;
0151 unsigned int num_pot_inter_a, num_pot_inter_b, num_pot_inter_c, num_pot_inter_d;
0152 num_pot_inter_a = potentialIntermediates[0].size();
0153 num_pot_inter_b = m_num_intermediate_states < 2 ? 1 : potentialIntermediates[1].size();
0154 num_pot_inter_c = m_num_intermediate_states < 3 ? 1 : potentialIntermediates[2].size();
0155 num_pot_inter_d = m_num_intermediate_states < 4 ? 1 : potentialIntermediates[3].size();
0156
0157 for (unsigned int a = 0; a < num_pot_inter_a; ++a)
0158 {
0159 for (unsigned int b = 0; b < num_pot_inter_b; ++b)
0160 {
0161 for (unsigned int c = 0; c < num_pot_inter_c; ++c)
0162 {
0163 for (unsigned int d = 0; d < num_pot_inter_d; ++d)
0164 {
0165 KFParticle candidate;
0166 bool isGood = false;
0167 const unsigned int matchIterators[4] = {a, b, c, d};
0168
0169 int num_mother_decay_products = m_num_intermediate_states + num_remaining_tracks;
0170 assert(num_mother_decay_products > 0);
0171 KFParticle *motherDecayProducts = new KFParticle[num_mother_decay_products];
0172 std::vector<KFParticle> finalTracks = potentialDaughters[0][a];
0173
0174 for (int i = 0; i < m_num_intermediate_states; ++i)
0175 {
0176 motherDecayProducts[i] = potentialIntermediates[i][matchIterators[i]];
0177 }
0178 for (int j = 1; j < m_num_intermediate_states; ++j)
0179 {
0180 finalTracks.insert(finalTracks.end(), potentialDaughters[j][matchIterators[j]].begin(), potentialDaughters[j][matchIterators[j]].end());
0181 }
0182
0183 bool have_duplicate_track = false;
0184
0185 for (size_t i = 0; i < finalTracks.size(); ++i)
0186 {
0187 for (size_t j = i + 1; j < finalTracks.size(); ++j)
0188 {
0189 if (finalTracks[i].Id() == finalTracks[j].Id())
0190 {
0191 have_duplicate_track = true;
0192 break;
0193 }
0194 }
0195 if (have_duplicate_track)
0196 {
0197 break;
0198 }
0199 }
0200
0201 if (have_duplicate_track)
0202 {
0203 continue;
0204 }
0205
0206
0207 std::vector<int> goodTrackIndexAdv_withoutIntermediates = goodTrackIndexAdv;
0208 for (int m = 0; m < num_tracks_used_by_intermediates; ++m)
0209 {
0210 int trackID_to_remove = finalTracks[m].Id();
0211 int trackElement_to_remove = -1;
0212
0213 auto it = std::find_if(daughterParticlesAdv.begin(), daughterParticlesAdv.end(),
0214 [&trackID_to_remove](const KFParticle& obj)
0215 { return obj.Id() == trackID_to_remove; });
0216
0217 if (it != daughterParticlesAdv.end())
0218 {
0219 trackElement_to_remove = std::distance(daughterParticlesAdv.begin(), it);
0220 }
0221
0222 goodTrackIndexAdv_withoutIntermediates.erase(remove(goodTrackIndexAdv_withoutIntermediates.begin(),
0223 goodTrackIndexAdv_withoutIntermediates.end(), trackElement_to_remove),
0224 goodTrackIndexAdv_withoutIntermediates.end());
0225 }
0226
0227 float required_unique_vertexID = 0;
0228 for (int n = 0; n < m_num_intermediate_states; ++n)
0229 {
0230 required_unique_vertexID += m_intermediate_charge[n] * kfp_Tools_evtReco.getParticleMass(m_intermediate_name[n].c_str());
0231 }
0232
0233 std::vector<std::vector<int>> uniqueCombinations;
0234 std::vector<std::vector<int>> listOfTracksToAppend;
0235
0236 if (num_remaining_tracks != 0)
0237 {
0238 for (int i = num_tracks_used_by_intermediates; i < m_num_tracks; ++i)
0239 {
0240 required_unique_vertexID += m_daughter_charge[i] * kfp_Tools_evtReco.getParticleMass(m_daughter_name[i].c_str());
0241 }
0242
0243 uniqueCombinations = findUniqueDaughterCombinations(num_tracks_used_by_intermediates, m_num_tracks);
0244
0245 listOfTracksToAppend = appendTracksToIntermediates(motherDecayProducts, daughterParticlesAdv, goodTrackIndexAdv_withoutIntermediates, num_remaining_tracks);
0246
0247 for (auto& uniqueCombination : uniqueCombinations)
0248 {
0249 for (const auto& element_of_intermediate : m_intermediate_name)
0250 {
0251 uniqueCombination.insert(begin(uniqueCombination), kfp_Tools_evtReco.getParticleID(element_of_intermediate));
0252 }
0253 }
0254 }
0255 else
0256 {
0257 std::vector<int> m_intermediate_id;
0258 m_intermediate_id.clear();
0259 for (const auto& element_of_intermediate : m_intermediate_name)
0260 {
0261 m_intermediate_id.push_back(kfp_Tools_evtReco.getParticleID(element_of_intermediate));
0262 }
0263 uniqueCombinations.push_back(m_intermediate_id);
0264 listOfTracksToAppend.push_back({0});
0265 }
0266
0267 for (auto& n_tracks : listOfTracksToAppend)
0268 {
0269 for (int n_trackID = 0; n_trackID < num_remaining_tracks; ++n_trackID)
0270 {
0271 int mDP_trackElem = m_num_intermediate_states + n_trackID;
0272 int dP_trackElem = n_tracks[n_trackID];
0273 motherDecayProducts[mDP_trackElem] = daughterParticlesAdv[dP_trackElem];
0274 }
0275
0276 for (auto& uniqueCombination : uniqueCombinations)
0277 {
0278 for (const auto& i_pv : primaryVerticesAdv)
0279 {
0280 std::tie(candidate, isGood) = getCombination(motherDecayProducts, &uniqueCombination[0], i_pv,
0281 m_constrain_to_vertex, false, 0, num_mother_decay_products, m_constrain_int_mass, required_unique_vertexID, topNode);
0282 if (isGood)
0283 {
0284
0285 if (m_require_bunch_crossing_match)
0286 {
0287 KFParticle_truthAndDetTools toolSet;
0288 std::vector<int> crossings;
0289 for (int i = 0; i < num_tracks_used_by_intermediates; ++i)
0290 {
0291 SvtxTrack *thisTrack = toolSet.getTrack(finalTracks[i].Id(), m_dst_trackmap);
0292 if (thisTrack)
0293 {
0294 crossings.push_back(thisTrack->get_crossing());
0295 }
0296 }
0297
0298 for (int k = 0; k < num_remaining_tracks; ++k)
0299 {
0300 int trackArrayID = k + m_num_intermediate_states;
0301 SvtxTrack *thisTrack = toolSet.getTrack(motherDecayProducts[trackArrayID].Id(), m_dst_trackmap);
0302 if (thisTrack)
0303 {
0304 crossings.push_back(thisTrack->get_crossing());
0305 }
0306 }
0307
0308 removeDuplicates(crossings);
0309
0310 if (crossings.size() !=1)
0311 {
0312 continue;
0313 }
0314 }
0315
0316 goodCandidates.push_back(candidate);
0317 if (m_constrain_to_vertex)
0318 {
0319 goodVertex.push_back(i_pv);
0320 }
0321 for (int k = 0; k < m_num_intermediate_states; ++k)
0322 {
0323 goodIntermediates[k].push_back(motherDecayProducts[k]);
0324 }
0325 for (int k = 0; k < num_tracks_used_by_intermediates; ++k)
0326 {
0327 goodDaughters[k].push_back(finalTracks[k]);
0328 }
0329 for (int k = 0; k < num_remaining_tracks; ++k)
0330 {
0331 int trackArrayID = k + m_num_intermediate_states;
0332 double slowTrackMass=-1;
0333 int slowTrackPDG=0;
0334 if ((Int_t) motherDecayProducts[trackArrayID].GetQ() != 0)
0335 {
0336 slowTrackMass = kfp_Tools_evtReco.getParticleMass((Int_t) motherDecayProducts[trackArrayID].GetQ() * uniqueCombination[trackArrayID]);
0337 slowTrackPDG = (Int_t) motherDecayProducts[trackArrayID].GetQ() * uniqueCombination[trackArrayID];
0338
0339
0340
0341
0342 if (abs(slowTrackPDG) == 11 || abs(slowTrackPDG) == 13 || abs(slowTrackPDG) == 15)
0343 {
0344 slowTrackPDG *= -1;
0345 }
0346 }
0347 else if ((Int_t) motherDecayProducts[trackArrayID].GetQ() == 0)
0348 {
0349 slowTrackMass = kfp_Tools_evtReco.getParticleMass(uniqueCombination[trackArrayID]);
0350 slowTrackPDG = uniqueCombination[trackArrayID];
0351 }
0352 KFParticle slowTrack;
0353 slowTrack.Create(motherDecayProducts[trackArrayID].Parameters(),
0354 motherDecayProducts[trackArrayID].CovarianceMatrix(),
0355 (Int_t) motherDecayProducts[trackArrayID].GetQ(),
0356 slowTrackMass);
0357 slowTrack.NDF() = motherDecayProducts[trackArrayID].GetNDF();
0358 slowTrack.Chi2() = motherDecayProducts[trackArrayID].GetChi2();
0359 slowTrack.SetId(motherDecayProducts[trackArrayID].Id());
0360 slowTrack.SetPDG(slowTrackPDG);
0361 goodDaughters[k + num_tracks_used_by_intermediates].push_back(slowTrack);
0362 }
0363 }
0364 }
0365 }
0366
0367 if (goodCandidates.size() != 0)
0368 {
0369 int bestCombinationIndex = selectBestCombination(m_constrain_to_vertex, false, goodCandidates, goodVertex);
0370
0371 selectedMotherAdv.push_back(goodCandidates[bestCombinationIndex]);
0372 if (m_constrain_to_vertex)
0373 {
0374 selectedVertexAdv.push_back(goodVertex[bestCombinationIndex]);
0375 }
0376 std::vector<KFParticle> intermediates;
0377 intermediates.reserve(m_num_intermediate_states);
0378 for (int i = 0; i < m_num_intermediate_states; ++i)
0379 {
0380 intermediates.push_back(goodIntermediates[i][bestCombinationIndex]);
0381 }
0382 selectedIntermediatesAdv.push_back(intermediates);
0383 std::vector<KFParticle> particles;
0384 particles.reserve(m_num_tracks);
0385 for (int i = 0; i < m_num_tracks; ++i)
0386 {
0387 particles.push_back(goodDaughters[i][bestCombinationIndex]);
0388 }
0389 selectedDaughtersAdv.push_back(particles);
0390 }
0391 goodCandidates.clear();
0392 goodVertex.clear();
0393 for (int j = 0; j < m_num_intermediate_states; ++j)
0394 {
0395 goodIntermediates[j].clear();
0396 }
0397 for (int j = 0; j < m_num_tracks; ++j)
0398 {
0399 goodDaughters[j].clear();
0400 }
0401 }
0402 delete [] motherDecayProducts;
0403 }
0404 }
0405 }
0406 }
0407 delete [] goodDaughters;
0408 delete [] goodIntermediates;
0409 delete [] potentialIntermediates;
0410 }
0411
0412 void KFParticle_eventReconstruction::getCandidateDecay(std::vector<KFParticle>& selectedMotherCand,
0413 std::vector<KFParticle>& selectedVertexCand,
0414 std::vector<std::vector<KFParticle>>& selectedDaughtersCand,
0415 const std::vector<KFParticle>& daughterParticlesCand,
0416 const std::vector<std::vector<int>>& goodTracksThatMeetCand,
0417 const std::vector<KFParticle>& primaryVerticesCand,
0418 int n_track_start, int n_track_stop,
0419 bool isIntermediate, int intermediateNumber, bool constrainMass, PHCompositeNode* topNode)
0420 {
0421 int nTracks = n_track_stop - n_track_start;
0422 std::vector<std::vector<int>> uniqueCombinations = findUniqueDaughterCombinations(n_track_start, n_track_stop);
0423 std::vector<KFParticle> goodCandidates, goodVertex;
0424 std::vector<KFParticle> *goodDaughters = new std::vector<KFParticle>[nTracks];
0425 KFParticle candidate;
0426 bool isGood;
0427 bool fixToPV = m_constrain_to_vertex && !isIntermediate;
0428
0429 float required_unique_vertexID = 0;
0430 for (int i = n_track_start; i < n_track_stop; ++i)
0431 {
0432 required_unique_vertexID += m_daughter_charge[i] * kfp_Tools_evtReco.getParticleMass(m_daughter_name[i].c_str());
0433 }
0434
0435 for (auto& i_comb : goodTracksThatMeetCand)
0436 {
0437 KFParticle *daughterTracks = new KFParticle[nTracks];
0438
0439 for (int i_track = 0; i_track < nTracks; ++i_track)
0440 {
0441 daughterTracks[i_track] = daughterParticlesCand[i_comb[i_track]];
0442 }
0443
0444 for (auto& uniqueCombination : uniqueCombinations)
0445 {
0446 for (unsigned int i_pv = 0; i_pv < primaryVerticesCand.size(); ++i_pv)
0447 {
0448 int* PDGIDofFirstParticleInCombination = &uniqueCombination[0];
0449 std::tie(candidate, isGood) = getCombination(daughterTracks, PDGIDofFirstParticleInCombination, primaryVerticesCand[i_pv], m_constrain_to_vertex,
0450 isIntermediate, intermediateNumber, nTracks, constrainMass, required_unique_vertexID, topNode);
0451 if (isIntermediate && isGood)
0452 {
0453 float min_ip = 0;
0454 float min_ipchi2 = 0;
0455 float min_ip_xy = 0;
0456 float min_ipchi2_xy = 0;
0457 calcMinIP(candidate, primaryVerticesCand, min_ip, min_ipchi2);
0458 calcMinIP(candidate, primaryVerticesCand, min_ip_xy , min_ipchi2_xy, false);
0459 if (!isInRange(m_intermediate_min_ip[intermediateNumber], min_ip, m_intermediate_max_ip[intermediateNumber])
0460 || !isInRange(m_intermediate_min_ipchi2[intermediateNumber], min_ipchi2, m_intermediate_max_ipchi2[intermediateNumber])
0461 || !isInRange(m_intermediate_min_ip_xy[intermediateNumber], min_ip_xy, m_intermediate_max_ip_xy[intermediateNumber])
0462 || !isInRange(m_intermediate_min_ipchi2_xy[intermediateNumber], min_ipchi2_xy, m_intermediate_max_ipchi2_xy[intermediateNumber]))
0463 {
0464 isGood = false;
0465 }
0466 }
0467
0468 if (isGood)
0469 {
0470 goodCandidates.push_back(candidate);
0471 goodVertex.push_back(primaryVerticesCand[i_pv]);
0472 for (int i = 0; i < nTracks; ++i)
0473 {
0474 KFParticle intParticle;
0475 double intParticleMass=-1;
0476 int intParticlePDG=0;
0477 if ((Int_t) daughterTracks[i].GetQ() != 0)
0478 {
0479 intParticleMass = kfp_Tools_evtReco.getParticleMass((Int_t) daughterTracks[i].GetQ() * PDGIDofFirstParticleInCombination[i]);
0480 intParticlePDG = (Int_t) daughterTracks[i].GetQ() * PDGIDofFirstParticleInCombination[i];
0481
0482
0483
0484
0485 if (abs(intParticlePDG) == 11 || abs(intParticlePDG) == 13 || abs(intParticlePDG) == 15)
0486 {
0487 intParticlePDG *= -1;
0488 }
0489 }
0490 else if ((Int_t) daughterTracks[i].GetQ() == 0)
0491 {
0492 intParticleMass = kfp_Tools_evtReco.getParticleMass(PDGIDofFirstParticleInCombination[i]);
0493 intParticlePDG = PDGIDofFirstParticleInCombination[i];
0494 }
0495 intParticle.Create(daughterTracks[i].Parameters(),
0496 daughterTracks[i].CovarianceMatrix(),
0497 (Int_t) daughterTracks[i].GetQ(),
0498 intParticleMass);
0499 intParticle.NDF() = daughterTracks[i].GetNDF();
0500 intParticle.Chi2() = daughterTracks[i].GetChi2();
0501 intParticle.SetId(daughterTracks[i].Id());
0502 intParticle.SetPDG(intParticlePDG);
0503 goodDaughters[i].push_back(intParticle);
0504 }
0505 }
0506 }
0507 }
0508
0509 if (goodCandidates.size() != 0)
0510 {
0511 int bestCombinationIndex = selectBestCombination(fixToPV, isIntermediate, goodCandidates, goodVertex);
0512
0513 selectedMotherCand.push_back(goodCandidates[bestCombinationIndex]);
0514 if (fixToPV)
0515 {
0516 selectedVertexCand.push_back(goodVertex[bestCombinationIndex]);
0517 }
0518 std::vector<KFParticle> particles;
0519 particles.reserve(nTracks);
0520 for (int i = 0; i < nTracks; ++i)
0521 {
0522 particles.push_back(goodDaughters[i][bestCombinationIndex]);
0523 }
0524 selectedDaughtersCand.push_back(particles);
0525
0526 goodCandidates.clear();
0527 goodVertex.clear();
0528 for (int j = 0; j < nTracks; ++j)
0529 {
0530 goodDaughters[j].clear();
0531 }
0532 }
0533 delete [] daughterTracks;
0534 }
0535 delete [] goodDaughters;
0536 }
0537
0538 int KFParticle_eventReconstruction::selectBestCombination(bool PVconstraint, bool isAnInterMother,
0539 std::vector<KFParticle> possibleCandidates,
0540 std::vector<KFParticle> possibleVertex)
0541 {
0542 KFParticle smallestMassError = possibleCandidates[0];
0543 int bestCombinationIndex = 0;
0544 for (unsigned int i = 1; i < possibleCandidates.size(); ++i)
0545 {
0546 if (PVconstraint && !isAnInterMother)
0547 {
0548 float current_IPchi2 = 0;
0549 float best_IPchi2 = 0;
0550
0551 if (m_use_2D_matching_tools)
0552 {
0553 current_IPchi2 = possibleCandidates[i].GetDeviationFromVertexXY(possibleVertex[i]);
0554 best_IPchi2 = smallestMassError.GetDeviationFromVertexXY(possibleVertex[bestCombinationIndex]);
0555 }
0556 else
0557 {
0558 current_IPchi2 = possibleCandidates[i].GetDeviationFromVertex(possibleVertex[i]);
0559 best_IPchi2 = smallestMassError.GetDeviationFromVertex(possibleVertex[bestCombinationIndex]);
0560 }
0561
0562 if (current_IPchi2 < best_IPchi2)
0563 {
0564 smallestMassError = possibleCandidates[i];
0565 bestCombinationIndex = i;
0566 }
0567 }
0568 else
0569 {
0570 if (possibleCandidates[i].GetErrMass() < smallestMassError.GetErrMass())
0571 {
0572 smallestMassError = possibleCandidates[i];
0573 bestCombinationIndex = i;
0574 }
0575 }
0576 }
0577 return bestCombinationIndex;
0578 }
0579
0580 KFParticle KFParticle_eventReconstruction::createFakePV()
0581 {
0582 float f_vertexParameters[6] = {0};
0583
0584 float f_vertexCovariance[21] = {0};
0585
0586 KFParticle kfp_vertex;
0587 kfp_vertex.Create(f_vertexParameters, f_vertexCovariance, 0, -1);
0588 kfp_vertex.NDF() = 0;
0589 kfp_vertex.Chi2() = 0;
0590 kfp_vertex.SetId(0);
0591 return kfp_vertex;
0592 }