File indexing completed on 2025-12-17 09:21:06
0001 #include "PHSimpleVertexFinder.h"
0002
0003
0004
0005 #include <trackbase/TrackVertexCrossingAssoc_v1.h>
0006 #include <trackbase/TrkrCluster.h> // for TrkrCluster
0007 #include <trackbase/TrkrClusterContainer.h>
0008 #include <trackbase/TrkrDefs.h> // for cluskey, getLayer, TrkrId
0009 #include <trackbase/TrackFitUtils.h>
0010 #include <trackbase_historic/SvtxTrack.h> // for SvtxTrack, SvtxTrack::C...
0011 #include <trackbase_historic/SvtxTrackMap_v2.h>
0012
0013 #include <globalvertex/SvtxVertexMap_v1.h>
0014 #include <globalvertex/SvtxVertex_v2.h>
0015
0016 #include <fun4all/Fun4AllReturnCodes.h>
0017 #include <phool/PHCompositeNode.h>
0018 #include <phool/PHNode.h>
0019 #include <phool/PHNodeIterator.h>
0020
0021 #include <phool/getClass.h>
0022 #include <phool/phool.h>
0023
0024 #include <Acts/Surfaces/PerigeeSurface.hpp>
0025
0026 #include <cmath> // for sqrt, fabs, atan2, cos
0027 #include <iomanip>
0028 #include <iostream> // for operator<<, basic_ostream
0029 #include <map> // for map
0030 #include <set> // for _Rb_tree_const_iterator
0031 #include <utility> // for pair, make_pair
0032
0033 #include <algorithm>
0034 #include <cassert>
0035 #include <functional>
0036 #include <numeric>
0037 #include <vector>
0038
0039 #include <Eigen/Dense>
0040
0041
0042 PHSimpleVertexFinder::PHSimpleVertexFinder(const std::string &name)
0043 : SubsysReco(name)
0044 {
0045 }
0046
0047
0048 int PHSimpleVertexFinder::InitRun(PHCompositeNode *topNode)
0049 {
0050 if (Verbosity() > 0)
0051 {
0052 std::cout << __PRETTY_FUNCTION__ << " is pp mode? " << _pp_mode << std::endl;
0053 }
0054
0055 int ret = GetNodes(topNode);
0056 if (ret != Fun4AllReturnCodes::EVENT_OK)
0057 {
0058 return ret;
0059 }
0060 ret = CreateNodes(topNode);
0061 if (ret != Fun4AllReturnCodes::EVENT_OK)
0062 {
0063 return ret;
0064 }
0065 return ret;
0066 }
0067
0068
0069 int PHSimpleVertexFinder::process_event(PHCompositeNode * )
0070 {
0071 if (Verbosity() > 0)
0072 {
0073 std::cout << PHWHERE << " track map size " << _track_map->size() << std::endl;
0074 }
0075
0076 _active_dcacut = _base_dcacut;
0077
0078
0079 _svtx_vertex_map->Reset();
0080 _track_vertex_crossing_map->Reset();
0081
0082
0083
0084
0085 std::set<short int> crossings;
0086 for (const auto &[trackkey, track] : *_track_map)
0087 {
0088 auto crossing = track->get_crossing();
0089
0090 if (Verbosity() > 0)
0091 {
0092 std::cout << "track id " << trackkey << " crossing " << crossing
0093 << " x y z " << track->get_x() << " " << track->get_y() << " " << track->get_z() << std::endl;
0094 }
0095
0096
0097
0098 if (_pp_mode)
0099 {
0100 auto *siseed = track->get_silicon_seed();
0101 if (crossing == 0 && !siseed)
0102 {
0103 continue;
0104 }
0105 }
0106
0107 crossings.insert(crossing);
0108 _track_vertex_crossing_map->addTrackAssoc(crossing, trackkey);
0109 }
0110
0111 unsigned int vertex_id = 0;
0112
0113 for (auto cross : crossings)
0114 {
0115
0116 _vertex_track_map.clear();
0117 _track_pair_map.clear();
0118 _track_pair_pca_map.clear();
0119 _vertex_position_map.clear();
0120 _vertex_covariance_map.clear();
0121 _vertex_set.clear();
0122
0123 if (Verbosity() > 0)
0124 {
0125 std::cout << "process tracks for beam crossing " << cross << std::endl;
0126 }
0127
0128
0129 auto crossing_track_index = _track_vertex_crossing_map->getTracks(cross);
0130 SvtxTrackMap *crossing_tracks = new SvtxTrackMap_v2;
0131 for (auto iter = crossing_track_index.first; iter != crossing_track_index.second; ++iter)
0132 {
0133 unsigned int trackkey = (*iter).second;
0134 SvtxTrack *track = _track_map->get(trackkey);
0135 if(!track)
0136 {
0137 continue;
0138 }
0139 crossing_tracks->insertWithKey(track, trackkey);
0140 }
0141
0142
0143
0144 if(_zero_field)
0145 {
0146 checkDCAsZF(crossing_tracks);
0147 }
0148 else
0149 {
0150 checkDCAs(crossing_tracks);
0151 }
0152
0153
0154 if (_track_pair_map.empty())
0155 {
0156 _active_dcacut = 3.0 * _base_dcacut;
0157 if(_zero_field)
0158 {
0159 checkDCAsZF(crossing_tracks);
0160 }
0161 else
0162 {
0163 checkDCAs(crossing_tracks);
0164 }
0165 }
0166
0167 if (Verbosity() > 0)
0168 {
0169 std::cout << "crossing " << cross << " track pair map size " << _track_pair_map.size() << std::endl;
0170 }
0171
0172
0173 std::vector<std::set<unsigned int>> connected_tracks = findConnectedTracks();
0174
0175
0176 for (unsigned int ivtx = 0; ivtx < connected_tracks.size(); ++ivtx)
0177 {
0178 bool isdone = true;
0179 for (unsigned int j = 0; j < connected_tracks.size() - ivtx - 1; j++)
0180 {
0181 if (connected_tracks[j].size() < connected_tracks[j + 1].size())
0182 {
0183 swap(connected_tracks[j], connected_tracks[j + 1]);
0184 isdone = false;
0185 }
0186
0187 if(isdone)
0188 {
0189 break;
0190 }
0191 }
0192 }
0193
0194
0195 for (unsigned int ivtx = 0; ivtx < connected_tracks.size(); ++ivtx)
0196 {
0197 if (Verbosity() > 0)
0198 {
0199 std::cout << "process vertex " << ivtx + vertex_id << std::endl;
0200 }
0201
0202 for (auto it : connected_tracks[ivtx])
0203 {
0204 unsigned int id = it;
0205 _vertex_track_map.insert(std::make_pair(ivtx, id));
0206 if (Verbosity() > 0)
0207 {
0208 std::cout << " adding track " << id << " to vertex " << ivtx + vertex_id << std::endl;
0209 }
0210 }
0211 }
0212
0213
0214 for (auto it : _vertex_track_map)
0215 {
0216 if (Verbosity() > 1)
0217 {
0218 std::cout << " vertex " << it.first + vertex_id << " track " << it.second << std::endl;
0219 }
0220 _vertex_set.insert(it.first);
0221 }
0222
0223
0224 removeOutlierTrackPairs();
0225
0226
0227 for (auto it : _vertex_set)
0228 {
0229 matrix_t avgCov = matrix_t::Zero();
0230 double cov_wt = 0.0;
0231
0232 auto ret = _vertex_track_map.equal_range(it);
0233 for (auto cit = ret.first; cit != ret.second; ++cit)
0234 {
0235 unsigned int trid = cit->second;
0236 matrix_t cov;
0237 auto *track = _track_map->get(trid);
0238 for (int i = 0; i < 3; ++i)
0239 {
0240 for (int j = 0; j < 3; ++j)
0241 {
0242 cov(i, j) = track->get_error(i, j);
0243 }
0244 }
0245
0246 avgCov += cov;
0247 cov_wt++;
0248 }
0249
0250 avgCov /= sqrt(cov_wt);
0251 if (Verbosity() > 2)
0252 {
0253 std::cout << "Average covariance for vertex " << it << " is:" << std::endl;
0254 std::cout << std::setprecision(8) << avgCov << std::endl;
0255 }
0256 _vertex_covariance_map.insert(std::make_pair(it, avgCov));
0257 }
0258
0259
0260
0261
0262 for (auto it : _vertex_set)
0263 {
0264 unsigned int thisid = it + vertex_id;
0265
0266 auto svtxVertex = std::make_unique<SvtxVertex_v2>();
0267
0268 svtxVertex->set_chisq(0.0);
0269 svtxVertex->set_ndof(0);
0270 svtxVertex->set_t0(0);
0271 svtxVertex->set_id(thisid);
0272 svtxVertex->set_beam_crossing(cross);
0273
0274 auto ret = _vertex_track_map.equal_range(it);
0275 for (auto cit = ret.first; cit != ret.second; ++cit)
0276 {
0277 unsigned int trid = cit->second;
0278
0279 if (Verbosity() > 1)
0280 {
0281 std::cout << " vertex " << thisid << " insert track " << trid << std::endl;
0282 SvtxTrack *track = _track_map->get(trid);
0283 if (track)
0284 {
0285 auto *siseed = track->get_silicon_seed();
0286 short int intt_crossing = siseed->get_crossing();
0287 std::cout << " vtxid " << thisid << " vertex crossing " << cross
0288 << " track crossing " << cross
0289 << " intt crossing " << intt_crossing
0290 << " trackID " << trid
0291 << " track Z " << track->get_z()
0292 << " X " << track->get_x()
0293 << " Y " << track->get_y()
0294 << " quality " << track->get_quality()
0295 << " pt " << track->get_pt()
0296 << std::endl;
0297 }
0298 }
0299 svtxVertex->insert_track(trid);
0300 _track_map->get(trid)->set_vertex_id(thisid);
0301 }
0302
0303 Eigen::Vector3d pos = _vertex_position_map.find(it)->second;
0304 svtxVertex->set_x(pos.x());
0305 svtxVertex->set_y(pos.y());
0306 svtxVertex->set_z(pos.z());
0307 if (Verbosity() > 1)
0308 {
0309 std::cout << " vertex " << thisid << " insert pos.x " << pos.x() << " pos.y " << pos.y() << " pos.z " << pos.z() << std::endl;
0310 }
0311
0312 auto vtxCov = _vertex_covariance_map.find(it)->second;
0313 for (int i = 0; i < 3; ++i)
0314 {
0315 for (int j = 0; j < 3; ++j)
0316 {
0317 svtxVertex->set_error(i, j, vtxCov(i, j));
0318 }
0319 }
0320
0321 _svtx_vertex_map->insert(svtxVertex.release());
0322 }
0323
0324 vertex_id += _vertex_set.size();
0325
0326
0327
0328
0329
0330
0331 for (const auto &[trackkey, track] : *crossing_tracks)
0332 {
0333 auto *thistrack = _track_map->get(trackkey);
0334 auto vtxid = thistrack->get_vertex_id();
0335 if (Verbosity() > 1)
0336 {
0337 std::cout << " track " << trackkey << " track vtxid " << vtxid << std::endl;
0338 }
0339
0340
0341 if (vtxid != std::numeric_limits<unsigned int>::max())
0342 {
0343 continue;
0344 }
0345
0346 float maxdz = std::numeric_limits<float>::max();
0347 unsigned int newvtxid = std::numeric_limits<unsigned int>::max();
0348
0349 for (auto it : _vertex_set)
0350 {
0351 unsigned int thisid = it + vertex_id - _vertex_set.size();
0352
0353 if (Verbosity() > 1)
0354 {
0355 std::cout << " test vertex " << thisid << std::endl;
0356 }
0357
0358 auto *thisvertex = _svtx_vertex_map->get(thisid);
0359 float dz = thistrack->get_z() - thisvertex->get_z();
0360 if (std::abs(dz) < maxdz)
0361 {
0362 maxdz = dz;
0363 newvtxid = thisid;
0364 }
0365 }
0366
0367
0368 if (newvtxid != std::numeric_limits<unsigned int>::max())
0369 {
0370 thistrack->set_vertex_id(newvtxid);
0371 if (Verbosity() > 1)
0372 {
0373 std::cout << " assign vertex " << newvtxid << " to additional track " << trackkey << std::endl;
0374 }
0375 }
0376 }
0377
0378 delete crossing_tracks;
0379
0380 }
0381
0382
0383 for (const auto &[vtxkey, vertex] : *_svtx_vertex_map)
0384 {
0385 short int crossing = vertex->get_beam_crossing();
0386 _track_vertex_crossing_map->addVertexAssoc(crossing, vtxkey);
0387
0388 if (Verbosity() > 1)
0389 {
0390 std::cout << "Vertex ID: " << vtxkey << " vertex crossing " << crossing << " list of tracks: " << std::endl;
0391 for (auto trackiter = vertex->begin_tracks(); trackiter != vertex->end_tracks(); ++trackiter)
0392 {
0393 SvtxTrack *track = _track_map->get(*trackiter);
0394 if (!track)
0395 {
0396 continue;
0397 }
0398
0399 auto *siseed = track->get_silicon_seed();
0400 short int intt_crossing = siseed->get_crossing();
0401
0402
0403 short int track_crossing = track->get_crossing();
0404 std::cout << " vtxid " << vtxkey << " vertex crossing " << crossing
0405 << " track crossing " << track_crossing
0406 << " intt crossing " << intt_crossing
0407 << " trackID " << *trackiter
0408 << " track Z " << track->get_z()
0409 << " X " << track->get_x()
0410 << " Y " << track->get_y()
0411 << " quality " << track->get_quality()
0412 << " pt " << track->get_pt()
0413 << std::endl;
0414 if (Verbosity() > 3)
0415 {
0416 siseed->identify();
0417 }
0418 }
0419 }
0420 }
0421
0422 if (Verbosity() > 2)
0423 {
0424 _track_vertex_crossing_map->identify();
0425 }
0426
0427 return Fun4AllReturnCodes::EVENT_OK;
0428 }
0429
0430 int PHSimpleVertexFinder::End(PHCompositeNode * )
0431 {
0432 return Fun4AllReturnCodes::EVENT_OK;
0433 }
0434
0435 int PHSimpleVertexFinder::CreateNodes(PHCompositeNode *topNode)
0436 {
0437 PHNodeIterator iter(topNode);
0438
0439 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0440
0441
0442 if (!dstNode)
0443 {
0444 std::cerr << "DST Node missing, quitting" << std::endl;
0445 throw std::runtime_error("failed to find DST node in PHActsInitialVertexFinder::createNodes");
0446 }
0447
0448
0449 PHCompositeNode *svtxNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "SVTX"));
0450
0451 if (!svtxNode)
0452 {
0453 svtxNode = new PHCompositeNode("SVTX");
0454 dstNode->addNode(svtxNode);
0455 }
0456
0457 _svtx_vertex_map = findNode::getClass<SvtxVertexMap>(topNode, _vertex_map_name);
0458
0459 if (!_svtx_vertex_map)
0460 {
0461 _svtx_vertex_map = new SvtxVertexMap_v1;
0462 PHIODataNode<PHObject> *vertexNode = new PHIODataNode<PHObject>(
0463 _svtx_vertex_map, _vertex_map_name, "PHObject");
0464
0465 svtxNode->addNode(vertexNode);
0466 }
0467
0468 _track_vertex_crossing_map = findNode::getClass<TrackVertexCrossingAssoc>(topNode, "TrackVertexCrossingAssocMap");
0469 if (!_track_vertex_crossing_map)
0470 {
0471 _track_vertex_crossing_map = new TrackVertexCrossingAssoc_v1;
0472 PHIODataNode<PHObject> *trackvertexNode = new PHIODataNode<PHObject>(
0473 _track_vertex_crossing_map, "TrackVertexCrossingAssocMap", "PHObject");
0474
0475 svtxNode->addNode(trackvertexNode);
0476 }
0477
0478 return Fun4AllReturnCodes::EVENT_OK;
0479 }
0480 int PHSimpleVertexFinder::GetNodes(PHCompositeNode *topNode)
0481 {
0482 _track_map = findNode::getClass<SvtxTrackMap>(topNode, _track_map_name);
0483 if (!_track_map)
0484 {
0485 std::cout << PHWHERE << " ERROR: Can't find SvtxTrackMap: " << _track_map_name << std::endl;
0486 return Fun4AllReturnCodes::ABORTEVENT;
0487 }
0488
0489
0490 _cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, m_clusterContainerName);
0491 if (!_cluster_map)
0492 {
0493 std::cout << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER container" << std::endl;
0494 return Fun4AllReturnCodes::ABORTEVENT;
0495 }
0496
0497 _tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0498 if (!_tGeometry)
0499 {
0500 std::cout << PHWHERE << "Error, can't find acts tracking geometry" << std::endl;
0501 return Fun4AllReturnCodes::ABORTEVENT;
0502 }
0503
0504 return Fun4AllReturnCodes::EVENT_OK;
0505 }
0506
0507 void PHSimpleVertexFinder::checkDCAs(SvtxTrackMap *track_map)
0508 {
0509
0510 for (auto tr1_it = track_map->begin(); tr1_it != track_map->end(); ++tr1_it)
0511 {
0512 auto id1 = tr1_it->first;
0513 auto *tr1 = tr1_it->second;
0514 if (tr1->get_quality() > _qual_cut)
0515 {
0516 continue;
0517 }
0518 if (_require_mvtx)
0519 {
0520 unsigned int nmvtx = 0;
0521 TrackSeed *siliconseed = tr1->get_silicon_seed();
0522 if (!siliconseed)
0523 {
0524 continue;
0525 }
0526
0527 for (auto clusit = siliconseed->begin_cluster_keys(); clusit != siliconseed->end_cluster_keys(); ++clusit)
0528 {
0529 if (TrkrDefs::getTrkrId(*clusit) == TrkrDefs::mvtxId)
0530 {
0531 nmvtx++;
0532 }
0533 if (nmvtx >= _nmvtx_required)
0534 {
0535 break;
0536 }
0537 }
0538 if (nmvtx < _nmvtx_required)
0539 {
0540 continue;
0541 }
0542 if (Verbosity() > 3)
0543 {
0544 std::cout << " tr1 id " << id1 << " has nmvtx at least " << nmvtx << std::endl;
0545 }
0546 }
0547
0548
0549 for (auto tr2_it = std::next(tr1_it); tr2_it != track_map->end(); ++tr2_it)
0550 {
0551 auto id2 = tr2_it->first;
0552 auto *tr2 = tr2_it->second;
0553 if (tr2->get_quality() > _qual_cut)
0554 {
0555 continue;
0556 }
0557 if (_require_mvtx)
0558 {
0559 unsigned int nmvtx = 0;
0560 TrackSeed *siliconseed = tr2->get_silicon_seed();
0561 if (!siliconseed)
0562 {
0563 continue;
0564 }
0565
0566 for (auto clusit = siliconseed->begin_cluster_keys(); clusit != siliconseed->end_cluster_keys(); ++clusit)
0567 {
0568 if (TrkrDefs::getTrkrId(*clusit) == TrkrDefs::mvtxId)
0569 {
0570 nmvtx++;
0571 }
0572 if (nmvtx >= _nmvtx_required)
0573 {
0574 break;
0575 }
0576 }
0577 if (nmvtx < _nmvtx_required)
0578 {
0579 continue;
0580 }
0581 if (Verbosity() > 3)
0582 {
0583 std::cout << " tr2 id " << id2 << " has nmvtx at least " << nmvtx << std::endl;
0584 }
0585 }
0586
0587
0588 if (Verbosity() > 3)
0589 {
0590 std::cout << "Check DCA for tracks " << id1 << " and " << id2 << std::endl;
0591 }
0592
0593 findDcaTwoTracks(tr1, tr2);
0594 }
0595 }
0596 }
0597
0598 void PHSimpleVertexFinder::checkDCAsZF(SvtxTrackMap *track_map)
0599 {
0600
0601
0602
0603
0604 std::vector<unsigned int> cumulative_trackid_vec;
0605 std::vector<unsigned int> cumulative_nmvtx_vec;
0606 std::vector<unsigned int> cumulative_nintt_vec;
0607 std::vector<std::vector<Acts::Vector3>> cumulative_global_vec;
0608 std::vector<std::vector<TrkrDefs::cluskey>> cumulative_cluskey_vec;
0609 std::vector<std::vector<float>> cumulative_fitpars_vec;
0610
0611 for (auto & tr1_it : *track_map)
0612 {
0613 auto id1 = tr1_it.first;
0614 auto *tr1 = tr1_it.second;
0615
0616
0617
0618 TrackSeed *siliconseed = tr1->get_silicon_seed();
0619 if (_require_mvtx)
0620 {
0621 if (!siliconseed)
0622 {
0623 continue;
0624 }
0625 }
0626 TrackSeed *tpcseed = tr1->get_tpc_seed();
0627
0628 std::vector<Acts::Vector3> global_vec;
0629 std::vector<TrkrDefs::cluskey> cluskey_vec;
0630
0631
0632 if(siliconseed)
0633 {
0634 getTrackletClusterList(siliconseed, cluskey_vec);
0635 if(Verbosity() > 0)
0636 {
0637 std::cout << " after silicon: silicon cluskey_vec size " << cluskey_vec.size() << std::endl;
0638 for(unsigned long i : cluskey_vec)
0639 {
0640 std::cout << i << std::endl;
0641 }
0642 }
0643 }
0644 if(tpcseed)
0645 {
0646
0647 getTrackletClusterList(tpcseed, cluskey_vec);
0648 if(Verbosity() > 0)
0649 {
0650 std::cout << " after tpc: cluskey_vec size " << cluskey_vec.size() << std::endl;
0651 for(unsigned long i : cluskey_vec)
0652 {
0653 std::cout << i << std::endl;
0654 }
0655 }
0656 }
0657
0658 unsigned int nmvtx = 0;
0659 unsigned int nintt = 0;
0660 for (auto& key : cluskey_vec)
0661 {
0662 if (TrkrDefs::getTrkrId(key) == TrkrDefs::mvtxId)
0663 {
0664 nmvtx++;
0665 }
0666 if(TrkrDefs::getTrkrId(key) == TrkrDefs::inttId)
0667 {
0668 nintt++;
0669 }
0670 }
0671
0672
0673 TrackFitUtils::getTrackletClusters(_tGeometry, _cluster_map, global_vec, cluskey_vec);
0674
0675 std::vector<float> fitpars = TrackFitUtils::fitClustersZeroField(global_vec, cluskey_vec, true);
0676
0677 if (Verbosity() > 1)
0678 {
0679 if(fitpars.size() == 4)
0680 {
0681 std::cout << " Track " << id1 << " dy/dx " << fitpars[0] << " y intercept " << fitpars[1]
0682 << " dx/dz " << fitpars[2] << " Z0 " << fitpars[3] << std::endl;
0683 }
0684 else
0685 {
0686 std::cout << " Track " << id1 << " ZF line fits failed, fitpars is empty" << std::endl;
0687 }
0688 }
0689
0690 cumulative_trackid_vec.push_back(id1);
0691 cumulative_nmvtx_vec.push_back(nmvtx);
0692 cumulative_nintt_vec.push_back(nintt);
0693 cumulative_global_vec.push_back(global_vec);
0694 cumulative_cluskey_vec.push_back(cluskey_vec);
0695 cumulative_fitpars_vec.push_back(fitpars);
0696 }
0697
0698 for(unsigned int i1 = 0; i1 < cumulative_trackid_vec.size(); ++i1)
0699 {
0700 if(cumulative_fitpars_vec[i1].empty()) { continue; }
0701
0702 for(unsigned int i2 = i1; i2 < cumulative_trackid_vec.size(); ++i2)
0703 {
0704 if(cumulative_fitpars_vec[i2].empty()) { continue; }
0705
0706
0707 Eigen::Vector3d a1(0.0, cumulative_fitpars_vec[i1][1],cumulative_fitpars_vec[i1][3]);
0708 Eigen::Vector3d a2(0.0, cumulative_fitpars_vec[i2][1],cumulative_fitpars_vec[i2][3]);
0709
0710 Eigen::Vector3d b1(1.0, cumulative_fitpars_vec[i1][0],cumulative_fitpars_vec[i1][2]);
0711 Eigen::Vector3d b2(1.0, cumulative_fitpars_vec[i2][0],cumulative_fitpars_vec[i2][2]);
0712
0713 Eigen::Vector3d PCA1(0, 0, 0);
0714 Eigen::Vector3d PCA2(0, 0, 0);
0715 double dca = dcaTwoLines(a1, b1, a2, b2, PCA1, PCA2);
0716
0717
0718
0719 if (fabs(dca) < _active_dcacut
0720 && (PCA1.x() > _beamline_x_cut_lo && PCA1.x() < _beamline_x_cut_hi)
0721 && (PCA1.y() > _beamline_y_cut_lo && PCA1.y() < _beamline_y_cut_hi)
0722 && (PCA2.x() > _beamline_x_cut_lo && PCA2.x() < _beamline_x_cut_hi)
0723 && (PCA2.y() > _beamline_y_cut_lo && PCA2.y() < _beamline_y_cut_hi)
0724 )
0725 {
0726 int id1 = cumulative_trackid_vec[i1];
0727 int id2 = cumulative_trackid_vec[i2];
0728
0729 if (Verbosity() > 3)
0730 {
0731 std::cout << " good match for tracks " << id1 << " and " << id2 << std::endl;
0732 std::cout << " a1.x " << a1.x() << " a1.y " << a1.y() << " a1.z " << a1.z() << std::endl;
0733 std::cout << " a2.x " << a2.x() << " a2.y " << a2.y() << " a2.z " << a2.z() << std::endl;
0734 std::cout << " PCA1.x() " << PCA1.x() << " PCA1.y " << PCA1.y() << " PCA1.z " << PCA1.z() << std::endl;
0735 std::cout << " PCA2.x() " << PCA2.x() << " PCA2.y " << PCA2.y() << " PCA2.z " << PCA2.z() << std::endl;
0736 std::cout << " dca " << dca << std::endl;
0737 }
0738
0739
0740 _track_pair_map.insert(std::make_pair(id1, std::make_pair(id2, dca)));
0741 _track_pair_pca_map.insert(std::make_pair(id1, std::make_pair(id2, std::make_pair(PCA1, PCA2))));
0742 }
0743 }
0744 }
0745
0746 return;
0747 }
0748
0749 void PHSimpleVertexFinder::getTrackletClusterList(TrackSeed* tracklet, std::vector<TrkrDefs::cluskey>& cluskey_vec)
0750 {
0751 for (auto clusIter = tracklet->begin_cluster_keys();
0752 clusIter != tracklet->end_cluster_keys();
0753 ++clusIter)
0754 {
0755 auto key = *clusIter;
0756 auto *cluster = _cluster_map->findCluster(key);
0757 if (!cluster)
0758 {
0759 std::cout << PHWHERE << "Failed to get cluster with key " << key << std::endl;
0760 continue;
0761 }
0762
0763
0764 auto surf = _tGeometry->maps().getSurface(key, cluster);
0765 if (!surf)
0766 {
0767 continue;
0768 }
0769
0770
0771 unsigned int layer = TrkrDefs::getLayer(key);
0772 if (layer == 7 || layer == 22 || layer == 23 || layer == 38 || layer == 39)
0773 {
0774 continue;
0775 }
0776
0777
0778 if (layer > 2 && layer < 7)
0779 {
0780 continue;
0781 }
0782
0783
0784 cluskey_vec.push_back(key);
0785
0786 }
0787 }
0788
0789 void PHSimpleVertexFinder::checkDCAs()
0790 {
0791
0792 for (auto tr1_it = _track_map->begin(); tr1_it != _track_map->end(); ++tr1_it)
0793 {
0794 auto id1 = tr1_it->first;
0795 auto *tr1 = tr1_it->second;
0796 if (tr1->get_quality() > _qual_cut)
0797 {
0798 continue;
0799 }
0800 if (_require_mvtx)
0801 {
0802 unsigned int nmvtx = 0;
0803 TrackSeed *siliconseed = tr1->get_silicon_seed();
0804 if (!siliconseed)
0805 {
0806 continue;
0807 }
0808
0809 for (auto clusit = siliconseed->begin_cluster_keys(); clusit != siliconseed->end_cluster_keys(); ++clusit)
0810 {
0811 if (TrkrDefs::getTrkrId(*clusit) == TrkrDefs::mvtxId)
0812 {
0813 nmvtx++;
0814 }
0815 if (nmvtx >= _nmvtx_required)
0816 {
0817 break;
0818 }
0819 }
0820 if (nmvtx < _nmvtx_required)
0821 {
0822 continue;
0823 }
0824 if (Verbosity() > 3)
0825 {
0826 std::cout << " tr1 id " << id1 << " has nmvtx at least " << nmvtx << std::endl;
0827 }
0828 }
0829
0830
0831 for (auto tr2_it = std::next(tr1_it); tr2_it != _track_map->end(); ++tr2_it)
0832 {
0833 auto id2 = tr2_it->first;
0834 auto *tr2 = tr2_it->second;
0835 if (tr2->get_quality() > _qual_cut)
0836 {
0837 continue;
0838 }
0839 if (_require_mvtx)
0840 {
0841 unsigned int nmvtx = 0;
0842 TrackSeed *siliconseed = tr2->get_silicon_seed();
0843 if (!siliconseed)
0844 {
0845 continue;
0846 }
0847
0848 for (auto clusit = siliconseed->begin_cluster_keys(); clusit != siliconseed->end_cluster_keys(); ++clusit)
0849 {
0850 if (TrkrDefs::getTrkrId(*clusit) == TrkrDefs::mvtxId)
0851 {
0852 nmvtx++;
0853 }
0854 if (nmvtx >= _nmvtx_required)
0855 {
0856 break;
0857 }
0858 }
0859 if (nmvtx < _nmvtx_required)
0860 {
0861 continue;
0862 }
0863 if (Verbosity() > 3)
0864 {
0865 std::cout << " tr2 id " << id2 << " has nmvtx at least " << nmvtx << std::endl;
0866 }
0867 }
0868
0869
0870 if (Verbosity() > 3)
0871 {
0872 std::cout << "Check DCA for tracks " << id1 << " and " << id2 << std::endl;
0873 }
0874
0875 findDcaTwoTracks(tr1, tr2);
0876 }
0877 }
0878 }
0879
0880 void PHSimpleVertexFinder::findDcaTwoTracks(SvtxTrack *tr1, SvtxTrack *tr2)
0881 {
0882 if (tr1->get_pt() < _track_pt_cut)
0883 {
0884 return;
0885 }
0886 if (tr2->get_pt() < _track_pt_cut)
0887 {
0888 return;
0889 }
0890
0891 unsigned int id1 = tr1->get_id();
0892 unsigned int id2 = tr2->get_id();
0893
0894
0895
0896 Eigen::Vector3d a1(tr1->get_x(), tr1->get_y(), tr1->get_z());
0897 Eigen::Vector3d b1(tr1->get_px() / tr1->get_p(), tr1->get_py() / tr1->get_p(), tr1->get_pz() / tr1->get_p());
0898 Eigen::Vector3d a2(tr2->get_x(), tr2->get_y(), tr2->get_z());
0899 Eigen::Vector3d b2(tr2->get_px() / tr2->get_p(), tr2->get_py() / tr2->get_p(), tr2->get_pz() / tr2->get_p());
0900
0901 Eigen::Vector3d PCA1(0, 0, 0);
0902 Eigen::Vector3d PCA2(0, 0, 0);
0903 double dca = dcaTwoLines(a1, b1, a2, b2, PCA1, PCA2);
0904
0905 if (Verbosity() > 3)
0906 {
0907 std::cout << " pair dca is " << dca << " _active_dcacut is " << _active_dcacut
0908 << " PCA1.x " << PCA1.x() << " PCA1.y " << PCA1.y()
0909 << " PCA2.x " << PCA2.x() << " PCA2.y " << PCA2.y() << std::endl;
0910 }
0911
0912
0913 if (fabs(dca) < _active_dcacut
0914 && (PCA1.x() > _beamline_x_cut_lo && PCA1.x() < _beamline_x_cut_hi)
0915 && (PCA1.y() > _beamline_y_cut_lo && PCA1.y() < _beamline_y_cut_hi)
0916 && (PCA2.x() > _beamline_x_cut_lo && PCA2.x() < _beamline_x_cut_hi)
0917 && (PCA2.y() > _beamline_y_cut_lo && PCA2.y() < _beamline_y_cut_hi) )
0918 {
0919 if (Verbosity() > 3)
0920 {
0921 std::cout << " good match for tracks " << tr1->get_id() << " and " << tr2->get_id() << " with pT " << tr1->get_pt() << " and " << tr2->get_pt() << std::endl;
0922 std::cout << " a1.x " << a1.x() << " a1.y " << a1.y() << " a1.z " << a1.z() << std::endl;
0923 std::cout << " a2.x " << a2.x() << " a2.y " << a2.y() << " a2.z " << a2.z() << std::endl;
0924 std::cout << " PCA1.x() " << PCA1.x() << " PCA1.y " << PCA1.y() << " PCA1.z " << PCA1.z() << std::endl;
0925 std::cout << " PCA2.x() " << PCA2.x() << " PCA2.y " << PCA2.y() << " PCA2.z " << PCA2.z() << std::endl;
0926 std::cout << " dca " << dca << std::endl;
0927 }
0928
0929
0930 _track_pair_map.insert(std::make_pair(id1, std::make_pair(id2, dca)));
0931 _track_pair_pca_map.insert(std::make_pair(id1, std::make_pair(id2, std::make_pair(PCA1, PCA2))));
0932 }
0933
0934 return;
0935 }
0936
0937 double PHSimpleVertexFinder::dcaTwoLines(const Eigen::Vector3d &a1, const Eigen::Vector3d &b1,
0938 const Eigen::Vector3d &a2, const Eigen::Vector3d &b2,
0939 Eigen::Vector3d &PCA1, Eigen::Vector3d &PCA2)
0940 {
0941
0942
0943
0944
0945
0946
0947
0948
0949 auto bcrossb = b1.cross(b2);
0950 auto mag_bcrossb = bcrossb.norm();
0951
0952 auto aminusa = a2 - a1;
0953
0954
0955
0956 double dca = 999;
0957 if (mag_bcrossb != 0)
0958 {
0959 dca = bcrossb.dot(aminusa) / mag_bcrossb;
0960 }
0961 else
0962 {
0963 return dca;
0964 }
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982 double X = b1.dot(b2) - b1.dot(b1) * b2.dot(b2) / b2.dot(b1);
0983 double Y = (a2.dot(b2) - a1.dot(b2)) - (a2.dot(b1) - a1.dot(b1)) * b2.dot(b2) / b2.dot(b1);
0984 double c = Y / X;
0985
0986 double F = b1.dot(b1) / b2.dot(b1);
0987 double G = -(a2.dot(b1) - a1.dot(b1)) / b2.dot(b1);
0988 double d = c * F + G;
0989
0990
0991 PCA1 = a1 + c * b1;
0992 PCA2 = a2 + d * b2;
0993
0994 return dca;
0995 }
0996
0997 std::vector<std::set<unsigned int>> PHSimpleVertexFinder::findConnectedTracks()
0998 {
0999 std::vector<std::set<unsigned int>> connected_tracks;
1000 std::set<unsigned int> connected;
1001 std::set<unsigned int> used;
1002 for (auto it : _track_pair_map)
1003 {
1004 unsigned int id1 = it.first;
1005 unsigned int id2 = it.second.first;
1006 double dca12 = it.second.second;
1007
1008 if(Verbosity() > 2)
1009 {
1010 auto rt = _track_pair_pca_map.equal_range(id1);
1011 for (auto ct = rt.first; ct != rt.second; ++ct)
1012 {
1013 unsigned int idb = ct->second.first;
1014 if(idb==id2)
1015 {
1016 auto pca1=ct->second.second.first;
1017 auto pca2=ct->second.second.second;
1018 std::cout << "Begin search on id1 = " << id1 << " and id2 = " << id2 << " dca12 = " << dca12 << std::endl;
1019 std::cout << " id1 " << id1 << " pca1 " << pca1.x() << " " << pca1.y() << " " << pca1.z() << std::endl;
1020 std::cout << " id2 " << id2 << " pca1 " << pca2.x() << " " << pca2.y() << " " << pca2.z() << std::endl;
1021 }
1022 }
1023 }
1024
1025 if ((used.contains(id1)) && (used.contains(id2)))
1026 {
1027 if (Verbosity() > 2)
1028 {
1029 std::cout << " tracks " << id1 << " and " << id2 << " are both in used , skip them" << std::endl;
1030 }
1031 continue;
1032 }
1033 if ((!used.contains(id1)) && (!used.contains(id2)))
1034 {
1035 if (Verbosity() > 2)
1036 {
1037 auto rt1 = _track_pair_pca_map.equal_range(id1);
1038 for (auto ct = rt1.first; ct != rt1.second; ++ct)
1039 {
1040 unsigned int ida = ct->first;
1041 unsigned int idb = ct->second.first;
1042
1043 if(idb==id2)
1044 {
1045 auto pcaa=ct->second.second.first;
1046 auto pcab=ct->second.second.second;
1047 std::cout << " tracks " << id1 << " and " << id2 << " dca = " << dca12
1048 << " are both not in used, start a new connected set" << std::endl;
1049 std::cout << " ida " << ida << " pcaa " << pcaa.x() << " " << pcaa.y() << " " << pcaa.z() << std::endl;
1050 std::cout << " idb " << idb << " pcab " << pcab.x() << " " << pcab.y() << " " << pcab.z() << std::endl;
1051 }
1052 }
1053 }
1054
1055 if (!connected.empty())
1056 {
1057 if (Verbosity() > 2)
1058 {
1059 std::cout << " closing out set with size " << connected.size() << std::endl;
1060 }
1061 connected_tracks.push_back(connected);
1062 connected.clear();
1063 }
1064 }
1065
1066
1067 connected.insert(id1);
1068 used.insert(id1);
1069 connected.insert(id2);
1070 used.insert(id2);
1071 for (auto cit : _track_pair_map)
1072 {
1073 unsigned int id3 = cit.first;
1074 unsigned int id4 = cit.second.first;
1075 double dca34 = cit.second.second;
1076
1077 if ((connected.contains(id3)) || (connected.contains(id4)))
1078 {
1079 if (Verbosity() > 2)
1080 {
1081
1082 auto rt2 = _track_pair_pca_map.equal_range(id3);
1083 for (auto ct = rt2.first; ct != rt2.second; ++ct)
1084 {
1085 unsigned int ida = ct->first;
1086 unsigned int idb = ct->second.first;
1087
1088 if(idb==id4)
1089 {
1090 auto pcaa=ct->second.second.first;
1091 auto pcab=ct->second.second.second;
1092 std::cout << " found connection to " << id3 << " and " << id4 << " dca34 = " << dca34
1093 << " pca dz = " << pcaa.z() - pcab.z() << std::endl;
1094 std::cout << " id3 " << ida << " pca3 " << pcaa.x() << " " << pcaa.y() << " " << pcaa.z() << std::endl;
1095 std::cout << " id4 " << idb << " pca4 " << pcab.x() << " " << pcab.y() << " " << pcab.z() << std::endl;
1096 }
1097 }
1098 }
1099 connected.insert(id3);
1100 used.insert(id3);
1101 connected.insert(id4);
1102 used.insert(id4);
1103 }
1104 }
1105 }
1106
1107
1108 if (!connected.empty())
1109 {
1110 if (Verbosity() > 2)
1111 {
1112 std::cout << " closing out last connected set with size " << connected.size() << std::endl;
1113 }
1114 connected_tracks.push_back(connected);
1115 connected.clear();
1116 }
1117
1118 if (Verbosity() > 2)
1119 {
1120 std::cout << "connected_tracks size " << connected_tracks.size() << std::endl;
1121 }
1122
1123 return connected_tracks;
1124 }
1125
1126 void PHSimpleVertexFinder::removeOutlierTrackPairs()
1127 {
1128
1129
1130 for (auto it : _vertex_set)
1131 {
1132 unsigned int vtxid = it;
1133 if (Verbosity() > 1)
1134 {
1135 std::cout << "calculate average position for vertex " << vtxid << std::endl;
1136 }
1137
1138
1139 std::vector<double> vx;
1140 std::vector<double> vy;
1141 std::vector<double> vz;
1142
1143 double pca_median_x = 0.;
1144 double pca_median_y = 0.;
1145 double pca_median_z = 0.;
1146
1147 Eigen::Vector3d new_pca_avge(0., 0., 0.);
1148 double new_wt = 0.0;
1149
1150 auto ret = _vertex_track_map.equal_range(vtxid);
1151
1152
1153 for (auto cit = ret.first; cit != ret.second; ++cit)
1154 {
1155 unsigned int tr1id = cit->second;
1156 if (Verbosity() > 2)
1157 {
1158 std::cout << " vectors: get entries for track " << tr1id << " for vertex " << vtxid << std::endl;
1159 }
1160
1161
1162 auto pca_range = _track_pair_pca_map.equal_range(tr1id);
1163 for (auto pit = pca_range.first; pit != pca_range.second; ++pit)
1164 {
1165 unsigned int tr2id = pit->second.first;
1166
1167 Eigen::Vector3d PCA1 = pit->second.second.first;
1168 Eigen::Vector3d PCA2 = pit->second.second.second;
1169
1170 if (Verbosity() > 2)
1171 {
1172 std::cout << " vectors: tr1id " << tr1id << " tr2id " << tr2id
1173 << " PCA1 " << PCA1.x() << " " << PCA1.y() << " " << PCA1.z()
1174 << " PCA2 " << PCA2.x() << " " << PCA2.y() << " " << PCA2.z()
1175 << std::endl;
1176 }
1177
1178 vx.push_back(PCA1.x());
1179 vx.push_back(PCA2.x());
1180 vy.push_back(PCA1.y());
1181 vy.push_back(PCA2.y());
1182 vz.push_back(PCA1.z());
1183 vz.push_back(PCA2.z());
1184 }
1185 }
1186
1187
1188
1189 if (vx.size() < 3)
1190 {
1191 new_pca_avge.x() = getAverage(vx);
1192 new_pca_avge.y() = getAverage(vy);
1193 new_pca_avge.z() = getAverage(vz);
1194 _vertex_position_map.insert(std::make_pair(vtxid, new_pca_avge));
1195 if (Verbosity() > 1)
1196 {
1197 std::cout << " Vertex has only 2 tracks, use average for PCA: " << new_pca_avge.x() << " " << new_pca_avge.y() << " " << new_pca_avge.z() << std::endl;
1198 }
1199
1200
1201 continue;
1202 }
1203
1204 pca_median_x = getMedian(vx);
1205 pca_median_y = getMedian(vy);
1206 pca_median_z = getMedian(vz);
1207 if (Verbosity() > 1)
1208 {
1209 std::cout << "Median values: x " << pca_median_x << " y " << pca_median_y << " z : " << pca_median_z << std::endl;
1210 }
1211
1212
1213 for (auto cit = ret.first; cit != ret.second; ++cit)
1214 {
1215 unsigned int tr1id = cit->second;
1216 if (Verbosity() > 2)
1217 {
1218 std::cout << " average: get entries for track " << tr1id << " for vertex " << vtxid << std::endl;
1219 }
1220
1221
1222 auto pca_range = _track_pair_pca_map.equal_range(tr1id);
1223 for (auto pit = pca_range.first; pit != pca_range.second; ++pit)
1224 {
1225 unsigned int tr2id = pit->second.first;
1226
1227 Eigen::Vector3d PCA1 = pit->second.second.first;
1228 Eigen::Vector3d PCA2 = pit->second.second.second;
1229
1230 if (
1231 fabs(PCA1.x() - pca_median_x) < _outlier_cut &&
1232 fabs(PCA1.y() - pca_median_y) < _outlier_cut &&
1233 fabs(PCA2.x() - pca_median_x) < _outlier_cut &&
1234 fabs(PCA2.y() - pca_median_y) < _outlier_cut)
1235 {
1236
1237
1238 new_pca_avge += PCA1;
1239 new_wt++;
1240 new_pca_avge += PCA2;
1241 new_wt++;
1242 }
1243 else
1244 {
1245 if (Verbosity() > 1)
1246 {
1247 std::cout << "Reject pair with tr1id " << tr1id << " tr2id " << tr2id << std::endl;
1248 }
1249 }
1250 }
1251 }
1252 if (new_wt > 0.0)
1253 {
1254 new_pca_avge = new_pca_avge / new_wt;
1255 }
1256 else
1257 {
1258
1259 new_pca_avge.x() = pca_median_x;
1260 new_pca_avge.y() = pca_median_y;
1261 new_pca_avge.z() = pca_median_z;
1262 }
1263
1264 _vertex_position_map.insert(std::make_pair(vtxid, new_pca_avge));
1265 }
1266
1267 return;
1268 }
1269
1270 double PHSimpleVertexFinder::getMedian(std::vector<double> &v)
1271 {
1272 double median = 0.0;
1273
1274 if ((v.size() % 2) == 0)
1275 {
1276
1277
1278 auto m1 = v.begin() + v.size() / 2;
1279 std::nth_element(v.begin(), m1, v.end());
1280 double median1 = v[v.size() / 2];
1281
1282 auto m2 = v.begin() + v.size() / 2 - 1;
1283 std::nth_element(v.begin(), m2, v.end());
1284 double median2 = v[v.size() / 2 - 1];
1285
1286 median = (median1 + median2) / 2.0;
1287 if (Verbosity() > 2)
1288 {
1289 std::cout << "The vector size is " << v.size()
1290 << " element m is " << v.size() / 2 << " = " << v[v.size() / 2]
1291 << " element m-1 is " << v.size() / 2 - 1 << " = " << v[v.size() / 2 - 1]
1292 << std::endl;
1293 }
1294 }
1295 else
1296 {
1297
1298 auto m = v.begin() + v.size() / 2;
1299 std::nth_element(v.begin(), m, v.end());
1300 median = v[v.size() / 2];
1301 if (Verbosity() > 2)
1302 {
1303 std::cout << "The vector size is " << v.size() << " element m is " << v.size() / 2 << " = " << v[v.size() / 2] << std::endl;
1304 }
1305 }
1306
1307 return median;
1308 }
1309 double PHSimpleVertexFinder::getAverage(std::vector<double> &v)
1310 {
1311 double avge = 0.0;
1312 double wt = 0.0;
1313 for (auto it : v)
1314 {
1315 avge += it;
1316 wt++;
1317 }
1318
1319 avge /= wt;
1320 if (Verbosity() > 2)
1321 {
1322 std::cout << " average = " << avge << std::endl;
1323 }
1324
1325 return avge;
1326 }