File indexing completed on 2025-12-17 09:21:01
0001
0002
0003
0004
0005
0006
0007
0008 #include "PHCASiliconSeeding.h"
0009
0010
0011 #include <fun4all/Fun4AllReturnCodes.h>
0012
0013 #include <phool/getClass.h>
0014 #include <phool/phool.h> // for PHWHERE
0015 #include <phool/recoConsts.h>
0016
0017
0018 #include <fun4allraw/MvtxRawDefs.h>
0019
0020 #include <trackbase/ActsGeometry.h>
0021 #include <trackbase/TrackFitUtils.h>
0022 #include <trackbase/TrkrCluster.h> // for TrkrCluster
0023 #include <trackbase/TrkrClusterContainer.h>
0024 #include <trackbase/InttDefs.h>
0025 #include <trackbase/TrkrClusterHitAssoc.h>
0026 #include <trackbase/TrkrClusterIterationMapv1.h>
0027 #include <trackbase/TrkrDefs.h> // for getLayer, clu...
0028 #include <trackbase_historic/TrackSeedContainer.h>
0029 #include <trackbase_historic/TrackSeedHelper.h>
0030 #include <trackbase_historic/TrackSeed_v2.h>
0031
0032
0033 #include <g4detectors/PHG4CylinderGeom.h>
0034 #include <g4detectors/PHG4CylinderGeomContainer.h>
0035 #include <intt/CylinderGeomIntt.h>
0036 #include <mvtx/CylinderGeom_Mvtx.h>
0037
0038 #include <g4mvtx/PHG4MvtxMisalignment.h>
0039
0040 #include <ffamodules/CDBInterface.h>
0041
0042
0043 #include <boost/geometry.hpp>
0044 #include <boost/geometry/geometries/box.hpp>
0045 #include <boost/geometry/geometries/point.hpp>
0046 #include <boost/geometry/index/rtree.hpp>
0047 #include <boost/geometry/policies/compare.hpp>
0048
0049 #include <algorithm>
0050 #include <iostream>
0051 #include <memory>
0052 #include <numeric>
0053 #include <unordered_set>
0054 #include <utility> // for pair, make_pair
0055 #include <vector>
0056
0057
0058 namespace
0059 {
0060
0061 template <class T>
0062 constexpr T square(const T& x)
0063 {
0064 return x * x;
0065 }
0066
0067
0068 inline double get_phi(const Acts::Vector3& position)
0069 {
0070 double phi = std::atan2(position.y(), position.x());
0071 if (phi < 0)
0072 {
0073 phi += 2. * M_PI;
0074 }
0075 return phi;
0076 }
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 }
0096
0097
0098 namespace bgi = boost::geometry::index;
0099
0100 PHCASiliconSeeding::PHCASiliconSeeding(
0101 const std::string& name,
0102 unsigned int start_layer,
0103 unsigned int end_layer,
0104 unsigned int min_clusters_per_track,
0105 float neighbor_phi_width,
0106 float eta_allowance)
0107 : PHTrackSeeding(name)
0108 , _start_layer(start_layer)
0109 , _end_layer(end_layer)
0110 , _min_clusters_per_track(min_clusters_per_track)
0111 , _eta_allowance(eta_allowance)
0112 , _drdz_allowance((2. * std::exp(-eta_allowance)) / (1 - std::exp(-1. * eta_allowance * 2)))
0113 , _neighbor_phi_width(neighbor_phi_width)
0114 {
0115 }
0116
0117 int PHCASiliconSeeding::InitializeGeometry(PHCompositeNode* topNode)
0118 {
0119
0120 m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0121 if (!m_tGeometry)
0122 {
0123 std::cout << PHWHERE << "No acts tracking geometry, can't proceed" << std::endl;
0124 return Fun4AllReturnCodes::ABORTEVENT;
0125 }
0126
0127 m_clusterMap = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
0128 if (!m_clusterMap)
0129 {
0130 std::cout << PHWHERE << "No cluster map, can't proceed" << std::endl;
0131 return Fun4AllReturnCodes::ABORTEVENT;
0132 }
0133
0134 m_clusterCrossingMap = findNode::getClass<TrkrClusterCrossingAssoc>(topNode, "TRKR_CLUSTERCROSSINGASSOC");
0135 if (!m_clusterCrossingMap)
0136 {
0137 std::cout << PHWHERE << "No cluster crossing association map, can't proceed" << std::endl;
0138 return Fun4AllReturnCodes::ABORTEVENT;
0139 }
0140
0141
0142 geom_container_mvtx = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
0143 if (!geom_container_mvtx)
0144 {
0145 std::cout << PHWHERE << "No MVTX cylinder geom container CYLINDERGEOM_MVTX, can't proceed" << std::endl;
0146 return Fun4AllReturnCodes::ABORTEVENT;
0147 }
0148
0149 mvtxmisalignment = new PHG4MvtxMisalignment();
0150 mvtxmisalignment->setAlignmentFile(CDBInterface::instance()->getUrl("MVTX_ALIGNMENT"));
0151 mvtxmisalignment->LoadMvtxStaveAlignmentParameters();
0152 v_globaldisplacement = mvtxmisalignment->get_GlobalDisplacement();
0153 radius_displacement = sqrt(v_globaldisplacement[0] * v_globaldisplacement[0] + v_globaldisplacement[1] * v_globaldisplacement[1]) * 0.1;
0154
0155 geom_container_intt = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
0156 if (!geom_container_intt)
0157 {
0158 std::cout << PHWHERE << "No INTT cylinder geom container CYLINDERGEOM_INTT, can't proceed" << std::endl;
0159 return Fun4AllReturnCodes::ABORTEVENT;
0160 }
0161
0162 return Fun4AllReturnCodes::EVENT_OK;
0163 }
0164
0165 Acts::Vector3 PHCASiliconSeeding::getGlobalPosition(TrkrDefs::cluskey key, TrkrCluster* cluster) const
0166 {
0167 return m_tGeometry->getGlobalPosition(key, cluster);
0168 }
0169
0170 void PHCASiliconSeeding::QueryTree(const bgi::rtree<PHCASiliconSeeding::pointKey, bgi::quadratic<16>>& rtree, double phimin, double z_min, double phimax, double z_max, std::vector<pointKey>& returned_values) const
0171 {
0172 bool query_both_ends = false;
0173 if (phimin < 0)
0174 {
0175 query_both_ends = true;
0176 phimin += 2 * M_PI;
0177 }
0178 if (phimax > 2 * M_PI)
0179 {
0180 query_both_ends = true;
0181 phimax -= 2 * M_PI;
0182 }
0183 if (query_both_ends)
0184 {
0185 rtree.query(bgi::intersects(box(point(phimin, z_min), point(2 * M_PI, z_max))), std::back_inserter(returned_values));
0186 rtree.query(bgi::intersects(box(point(0., z_min), point(phimax, z_max))), std::back_inserter(returned_values));
0187 }
0188 else
0189 {
0190 rtree.query(bgi::intersects(box(point(phimin, z_min), point(phimax, z_max))), std::back_inserter(returned_values));
0191 }
0192 }
0193
0194 std::pair<PHCASiliconSeeding::PositionMap, PHCASiliconSeeding::keyListPerLayer> PHCASiliconSeeding::FillGlobalPositions()
0195 {
0196 keyListPerLayer ckeys;
0197 PositionMap cachedPositions;
0198 cachedPositions.reserve(_cluster_map->size());
0199
0200 std::vector<TrkrDefs::hitsetkey> hskeys = _cluster_map->getHitSetKeys(TrkrDefs::mvtxId);
0201 std::vector<TrkrDefs::hitsetkey> intt_hskeys = _cluster_map->getHitSetKeys(TrkrDefs::inttId);
0202 hskeys.insert(hskeys.end(), intt_hskeys.begin(), intt_hskeys.end());
0203
0204 for (const auto& hitsetkey : hskeys)
0205 {
0206
0207 if (TrkrDefs::getTrkrId(hitsetkey) == TrkrDefs::mvtxId)
0208 {
0209 int strobeId = MvtxDefs::getStrobeId(hitsetkey);
0210 if (strobeId < _lowest_allowed_strobeid || strobeId > _highest_allowed_strobeid)
0211 {
0212 continue;
0213 }
0214 }
0215 if (TrkrDefs::getLayer(hitsetkey) < _start_layer || TrkrDefs::getLayer(hitsetkey) > _end_layer)
0216 {
0217 if (Verbosity() > 2)
0218 {
0219 std::cout << "skipping layer: " << TrkrDefs::getLayer(hitsetkey) << std::endl;
0220 }
0221 continue;
0222 }
0223 auto range = _cluster_map->getClusters(hitsetkey);
0224 for (auto clusIter = range.first; clusIter != range.second; ++clusIter)
0225 {
0226 TrkrDefs::cluskey ckey = clusIter->first;
0227 TrkrCluster* cluster = clusIter->second;
0228 unsigned int layer = TrkrDefs::getLayer(ckey);
0229 if (_iteration_map != nullptr && _n_iteration > 0)
0230 {
0231 if (_iteration_map->getIteration(ckey) > 0)
0232 {
0233 continue;
0234 }
0235 }
0236
0237
0238 const Acts::Vector3 globalpos_d = getGlobalPosition(ckey, cluster);
0239 const Acts::Vector3 globalpos = {globalpos_d.x(), globalpos_d.y(), globalpos_d.z()};
0240 cachedPositions.insert(std::make_pair(ckey, globalpos));
0241 ckeys[layer].push_back(ckey);
0242 }
0243 }
0244 return std::make_pair(cachedPositions, ckeys);
0245 }
0246
0247 std::vector<PHCASiliconSeeding::coordKey> PHCASiliconSeeding::FillTree(bgi::rtree<PHCASiliconSeeding::pointKey, bgi::quadratic<16>>& _rtree, const PHCASiliconSeeding::keyList& ckeys, const PHCASiliconSeeding::PositionMap& globalPositions, const int layer)
0248 {
0249
0250
0251 int n_dupli = 0;
0252 std::vector<coordKey> coords;
0253
0254
0255 for (const auto& ckey : ckeys)
0256 {
0257 const auto& globalpos_d = globalPositions.at(ckey);
0258 const double clus_phi = get_phi(globalpos_d);
0259 const double clus_z = globalpos_d.z();
0260 if (Verbosity() > 5)
0261 {
0262 std::cout << "Found cluster " << ckey << " in layer " << layer << " at global position (x,y,z) = (" << globalpos_d.x() << "," << globalpos_d.y() << "," << globalpos_d.z() << ") and (phi,z) = (" << clus_phi << "," << clus_z << ")" << std::endl;
0263 }
0264
0265
0266
0267
0268
0269
0270
0271 coords.push_back({{static_cast<float>(clus_phi), static_cast<float>(clus_z)}, ckey});
0272 _rtree.insert(std::make_pair(point(clus_phi, globalpos_d.z()), ckey));
0273 }
0274 if (Verbosity() > 5)
0275 {
0276 std::cout << "nhits in layer(" << layer << "): " << coords.size() << std::endl;
0277 }
0278 if (Verbosity() > 3)
0279 {
0280 std::cout << "number of duplicates : " << n_dupli << std::endl;
0281 }
0282 return coords;
0283 }
0284
0285 int PHCASiliconSeeding::Process(PHCompositeNode* )
0286 {
0287 if (Verbosity() > 3)
0288 {
0289 std::cout << " PHCASiliconSeeding processing... " << std::endl;
0290 Identify();
0291 }
0292 if (_n_iteration > 0)
0293 {
0294 if (!_iteration_map)
0295 {
0296 std::cerr << PHWHERE << "Cluster Iteration Map missing, aborting." << std::endl;
0297 return Fun4AllReturnCodes::ABORTEVENT;
0298 }
0299 }
0300
0301
0302 SetupDefaultLayerRadius();
0303
0304 PositionMap globalPositions;
0305 keyListPerLayer ckeys;
0306 std::tie(globalPositions, ckeys) = FillGlobalPositions();
0307
0308 int numberofseeds = 0;
0309 numberofseeds += FindSeeds(globalPositions, ckeys);
0310 if (Verbosity() > 0)
0311 {
0312 std::cout << " found " << numberofseeds << " track seeds" << std::endl;
0313 }
0314
0315 for (auto& rtree : _rtrees)
0316 {
0317 rtree.clear();
0318 }
0319
0320 return Fun4AllReturnCodes::EVENT_OK;
0321 }
0322
0323 int PHCASiliconSeeding::FindSeeds(const PHCASiliconSeeding::PositionMap& globalPositions, const PHCASiliconSeeding::keyListPerLayer& ckeys)
0324 {
0325 std::vector<std::vector<Triplet>> triplets = CreateLinks(globalPositions, ckeys);
0326 keyLists trackSeedKeyLists = FollowLinks(triplets);
0327
0328 std::vector<TrackSeed_v2> seeds = FitSeeds(trackSeedKeyLists, globalPositions);
0329 HelixPropagate(seeds, globalPositions);
0330 HelixPropagate(seeds, globalPositions);
0331
0332 publishSeeds(seeds);
0333 return seeds.size();
0334 }
0335
0336 bool PHCASiliconSeeding::ClusterTimesAreCompatible(const TrkrDefs::cluskey clus_a, const TrkrDefs::cluskey clus_b) const
0337 {
0338 const int time_index = GetClusterTimeIndex(clus_a);
0339 return ClusterTimesAreCompatible(TrkrDefs::getTrkrId(clus_a), time_index, clus_b);
0340 }
0341
0342 bool PHCASiliconSeeding::ClusterTimesAreCompatible(const uint8_t trkr_id, const int time_index, const TrkrDefs::cluskey ckey) const
0343 {
0344 if (TrkrDefs::getTrkrId(ckey) != trkr_id)
0345 {
0346 return true;
0347 }
0348
0349 if (trkr_id == TrkrDefs::mvtxId)
0350 {
0351 if (Verbosity() > 3)
0352 {
0353 std::cout << "strobe a " << time_index << " strobe b " << MvtxDefs::getStrobeId(ckey) << std::endl;
0354 }
0355 return (time_index == MvtxDefs::getStrobeId(ckey));
0356 }
0357 if (trkr_id == TrkrDefs::inttId)
0358 {
0359 short crossing = GetCleanINTTClusterCrossing(ckey);
0360 if (Verbosity() > 3)
0361 {
0362 std::cout << "crossing a " << time_index << " crossing b " << crossing << std::endl;
0363 }
0364 return (crossing != SHRT_MAX && time_index != SHRT_MAX) && (abs(crossing - time_index) <= 1);
0365 }
0366 return true;
0367 }
0368
0369 int PHCASiliconSeeding::GetClusterTimeIndex(const TrkrDefs::cluskey ckey) const
0370 {
0371 if (TrkrDefs::getTrkrId(ckey) == TrkrDefs::mvtxId)
0372 {
0373 return MvtxDefs::getStrobeId(ckey);
0374 }
0375
0376 if (TrkrDefs::getTrkrId(ckey) == TrkrDefs::inttId)
0377 {
0378 return GetCleanINTTClusterCrossing(ckey);
0379 }
0380
0381 return SHRT_MAX;
0382 }
0383
0384 short PHCASiliconSeeding::GetCleanINTTClusterCrossing(const TrkrDefs::cluskey ckey) const
0385 {
0386 std::set<short> crossings = GetINTTClusterCrossings(ckey);
0387
0388 if (crossings.empty() || crossings.size() > 2)
0389 {
0390 if (Verbosity() > 3 && crossings.size() > 2)
0391 {
0392 std::cout << "more than two INTT crossings within cluster: ";
0393
0394 for (short cross : crossings)
0395 {
0396 std::cout << cross << " ";
0397 }
0398 std::cout << std::endl;
0399 }
0400 return SHRT_MAX;
0401 }
0402 if (crossings.size() == 1)
0403
0404 {
0405 return *(crossings.begin());
0406 }
0407
0408
0409
0410 std::vector<short> crossings_vec;
0411 std::copy(crossings.begin(), crossings.end(), std::back_inserter(crossings_vec));
0412
0413 if (abs(crossings_vec[1] - crossings_vec[0]) == 1)
0414 {
0415 std::cout << "INTT: resolving off-by-one between " << crossings_vec[0] << " and " << crossings_vec[1] << std::endl;
0416 return std::min(crossings_vec[0], crossings_vec[1]);
0417 }
0418
0419 return SHRT_MAX;
0420
0421
0422 }
0423
0424 std::set<short> PHCASiliconSeeding::GetINTTClusterCrossings(const TrkrDefs::cluskey ckey) const
0425 {
0426 if (TrkrDefs::getTrkrId(ckey) != TrkrDefs::inttId)
0427 {
0428 return std::set<short>{};
0429 }
0430
0431 std::set<short> crossings;
0432 TrkrCluster* clus = m_clusterMap->findCluster(ckey);
0433 if (!clus)
0434 {
0435 return std::set<short>{};
0436 }
0437 auto crossingrange = m_clusterCrossingMap->getCrossings(ckey);
0438 for (auto iter = crossingrange.first; iter != crossingrange.second; ++iter)
0439 {
0440 crossings.insert(iter->second);
0441 }
0442 return crossings;
0443 }
0444
0445 std::vector<std::vector<PHCASiliconSeeding::Triplet>> PHCASiliconSeeding::CreateLinks(const PHCASiliconSeeding::PositionMap& globalPositions, const PHCASiliconSeeding::keyListPerLayer& ckeys)
0446 {
0447 std::vector<std::vector<Triplet>> triplets;
0448
0449 std::vector<std::vector<coordKey>> clusterdata;
0450
0451 for (size_t l = _start_layer; l <= _end_layer; l++)
0452 {
0453 const size_t l_index = l - _start_layer;
0454 _rtrees.emplace_back();
0455 triplets.emplace_back();
0456 if (l == 4)
0457
0458 {
0459 const std::vector<coordKey> l4clusters = FillTree(_rtrees[3 - _start_layer], ckeys[4], globalPositions, 3);
0460 clusterdata[3 - _start_layer].insert(clusterdata[3 - _start_layer].end(), l4clusters.begin(), l4clusters.end());
0461 }
0462 else if (l == 5)
0463 {
0464 clusterdata.push_back(FillTree(_rtrees[4 - _start_layer], ckeys[5], globalPositions, 4));
0465 }
0466 else if (l == 6)
0467 {
0468 const std::vector<coordKey> l6clusters = FillTree(_rtrees[4 - _start_layer], ckeys[6], globalPositions, 4);
0469 clusterdata[4 - _start_layer].insert(clusterdata[4 - _start_layer].end(), l6clusters.begin(), l6clusters.end());
0470 }
0471 else
0472 {
0473 clusterdata.push_back(FillTree(_rtrees[l_index], ckeys[l], globalPositions, l));
0474 }
0475 }
0476
0477
0478
0479 for (size_t l = _start_layer + 1; l <= _end_layer - 1; l++)
0480 {
0481 if (Verbosity() > 2)
0482 {
0483 std::cout << "layer " << l << " _start_layer " << _start_layer << " _end_layer " << _end_layer << std::endl;
0484 }
0485 if (l >= 4 && l <= 6)
0486 {
0487 continue;
0488 }
0489 const size_t l_index = l - _start_layer;
0490
0491 for (coordKey centerCluster : clusterdata[l_index])
0492 {
0493 std::vector<pointKey> clustersBelow;
0494 std::vector<pointKey> clustersAbove;
0495
0496 const float centerPhi = centerCluster.first[0];
0497 const float centerZ = centerCluster.first[1];
0498
0499 const float dphiwindow_below = std::max(dphi_per_layer[l], dphi_per_layer[l - 1]);
0500 const float dphiwindow_above = std::max(dphi_per_layer[l], dphi_per_layer[l + 1]);
0501
0502
0503 float center_radius = (l < 3) ? GetMvtxRadiusByPhi(centerPhi, l) : radius_per_layer.at(l);
0504 float center_radius_below = (l - 1 < 3) ? GetMvtxRadiusByPhi(centerPhi, l - 1) : radius_per_layer.at(l - 1);
0505 const float dZwindow_below = (center_radius - center_radius_below) * (1. / _drdz_allowance);
0506
0507 QueryTree(_rtrees[l_index - 1],
0508 centerPhi - dphiwindow_below,
0509 centerZ - dZwindow_below,
0510 centerPhi + dphiwindow_below,
0511 centerZ + dZwindow_below,
0512 clustersBelow);
0513
0514 if (l_index > 1)
0515 {
0516 const float dphiwindow_2below = std::max(dphi_per_layer[l], dphi_per_layer[l - 2]);
0517 const float center_radius_2below = (l - 2 < 3) ? GetMvtxRadiusByPhi(centerPhi, l - 2) : radius_per_layer.at(l - 2);
0518 const float dZwindow_2below = (center_radius - center_radius_2below) * (1. / _drdz_allowance);
0519
0520 QueryTree(_rtrees[l_index - 2],
0521 centerPhi - dphiwindow_below - dphiwindow_2below,
0522 centerZ - dZwindow_below - dZwindow_2below,
0523 centerPhi + dphiwindow_below + dphiwindow_2below,
0524 centerZ + dZwindow_below + dZwindow_2below,
0525 clustersBelow);
0526 }
0527
0528 const float center_radius_above = (l + 1 < 3) ? GetMvtxRadiusByPhi(centerPhi, l + 1) : radius_per_layer.at(l + 1);
0529 const float dZwindow_above = (center_radius_above - center_radius) * (1. / _drdz_allowance);
0530 QueryTree(_rtrees[l_index + 1],
0531 centerPhi - dphiwindow_above,
0532 centerZ - dZwindow_above,
0533 centerPhi + dphiwindow_above,
0534 centerZ + dZwindow_above,
0535 clustersAbove);
0536
0537 if (l_index < 3)
0538 {
0539 const float dphiwindow_2above = std::max(dphi_per_layer[l], dphi_per_layer[l + 2]);
0540 const float center_radius_2above = (l + 2 < 3) ? GetMvtxRadiusByPhi(centerPhi, l + 2) : radius_per_layer.at(l + 2);
0541 const float dZwindow_2above = (center_radius_2above - center_radius) * (1. / _drdz_allowance);
0542
0543 QueryTree(_rtrees[l_index + 2],
0544 centerPhi - dphiwindow_above - dphiwindow_2above,
0545 centerZ - dZwindow_above - dZwindow_2above,
0546 centerPhi + dphiwindow_above + dphiwindow_2above,
0547 centerZ + dZwindow_above + dZwindow_2above,
0548 clustersAbove);
0549 }
0550
0551 if (Verbosity() > 3)
0552 {
0553 std::cout << std::endl;
0554 std::cout << "center " << centerCluster.second << " found " << clustersBelow.size() << " clusters below, " << clustersAbove.size() << " clusters above" << std::endl;
0555 }
0556
0557 float best_cos_angle = 1e9;
0558 TrkrDefs::cluskey best_below_ckey = 0;
0559 TrkrDefs::cluskey best_above_ckey = 0;
0560
0561 std::vector<TrkrDefs::cluskey> passing_below_ckeys;
0562 std::vector<TrkrDefs::cluskey> passing_above_ckeys;
0563
0564 const TrkrDefs::cluskey center_ckey = centerCluster.second;
0565 const Acts::Vector3& gpos_center = globalPositions.at(center_ckey);
0566 const int time_center = GetClusterTimeIndex(center_ckey);
0567 const uint8_t trkrid_center = TrkrDefs::getTrkrId(center_ckey);
0568
0569 for (const pointKey& cbelow : clustersBelow)
0570 {
0571 if (!ClusterTimesAreCompatible(trkrid_center, time_center, cbelow.second))
0572 {
0573 if (Verbosity() > 3)
0574 {
0575 std::cout << "below candidate has incompatible time" << std::endl;
0576 }
0577 continue;
0578 }
0579 const Acts::Vector3& gpos_below = globalPositions.at(cbelow.second);
0580 const Acts::Vector3 delta_below = gpos_below - gpos_center;
0581
0582 for (const pointKey& cabove : clustersAbove)
0583 {
0584 if (!ClusterTimesAreCompatible(trkrid_center, time_center, cabove.second))
0585 {
0586 if (Verbosity() > 3)
0587 {
0588 std::cout << "above candidate has incompatible time" << std::endl;
0589 }
0590 continue;
0591 }
0592 const Acts::Vector3& gpos_above = globalPositions.at(cabove.second);
0593 const Acts::Vector3 delta_above = gpos_above - gpos_center;
0594
0595 float cos_angle;
0596 float dot_product;
0597 float mag2_below;
0598 float mag2_above;
0599
0600 if (Verbosity() > 3)
0601 {
0602 std::cout << "candidate triplet: " << std::endl;
0603 std::cout << "layer " << (int) TrkrDefs::getLayer(cbelow.second) << ": key " << cbelow.second << ": " << gpos_below.x() << ", " << gpos_below.y() << ", " << gpos_below.z() << std::endl;
0604 std::cout << "layer " << (int) TrkrDefs::getLayer(centerCluster.second) << ": key " << centerCluster.second << ": " << gpos_center.x() << ", " << gpos_center.y() << ", " << gpos_center.z() << std::endl;
0605 std::cout << "layer " << (int) TrkrDefs::getLayer(cabove.second) << ": key " << cabove.second << ": " << gpos_above.x() << ", " << gpos_above.y() << ", " << gpos_above.z() << std::endl;
0606 }
0607
0608 if (l >= 2 && l <= 6)
0609 {
0610 mag2_below = delta_below.x() * delta_below.x() + delta_below.y() * delta_below.y();
0611 mag2_above = delta_above.x() * delta_above.x() + delta_above.y() * delta_above.y();
0612 dot_product = delta_below.x() * delta_above.x() + delta_below.y() * delta_above.y();
0613 }
0614 else
0615 {
0616 mag2_below = delta_below.x() * delta_below.x() + delta_below.y() * delta_below.y() + delta_below.z() * delta_below.z();
0617 mag2_above = delta_above.x() * delta_above.x() + delta_above.y() * delta_above.y() + delta_above.z() * delta_above.z();
0618 dot_product = delta_below.x() * delta_above.x() + delta_below.y() * delta_above.y() + delta_below.z() * delta_above.z();
0619 }
0620
0621 cos_angle = dot_product / sqrt(mag2_below * mag2_above);
0622
0623 if (Verbosity() > 3)
0624 {
0625 std::cout << "delta_below (in x, y, z): " << std::endl;
0626 std::cout << delta_below.x() << ", " << delta_below.y() << ", " << delta_below.z() << " (magnitude " << sqrt(mag2_below) << ")" << std::endl;
0627 std::cout << "delta_above (in x, y, z): " << std::endl;
0628 std::cout << delta_above.x() << ", " << delta_above.y() << ", " << delta_above.z() << " (magnitude " << sqrt(mag2_above) << ")" << std::endl;
0629 std::cout << "dot product: " << dot_product << std::endl;
0630 std::cout << "cos(breaking angle): " << cos_angle << std::endl;
0631 std::cout << "------------------" << std::endl;
0632 }
0633
0634 if (cos_angle < _max_cos_angle)
0635 {
0636 if (_use_best)
0637 {
0638 if (cos_angle < best_cos_angle)
0639 {
0640 if (Verbosity() > 3)
0641 {
0642 std::cout << "beats best cos(angle) of " << best_cos_angle << std::endl;
0643 }
0644 best_cos_angle = cos_angle;
0645 best_below_ckey = cbelow.second;
0646 best_above_ckey = cabove.second;
0647 }
0648 }
0649 else
0650 {
0651 if (Verbosity() > 3)
0652 {
0653 std::cout << "passes straightness criterion" << std::endl;
0654 }
0655 passing_below_ckeys.push_back(cbelow.second);
0656 passing_above_ckeys.push_back(cabove.second);
0657 }
0658 }
0659 }
0660 }
0661
0662 if (_use_best && best_cos_angle < 1.)
0663 {
0664 if (Verbosity() > 3)
0665 {
0666 std::cout << "adding triplet(" << best_below_ckey << ", " << centerCluster.second << ", " << best_above_ckey << ")" << std::endl;
0667 }
0668 triplets[l_index].push_back({best_below_ckey, centerCluster.second, best_above_ckey});
0669 }
0670 else
0671 {
0672 for (size_t i = 0; i < passing_below_ckeys.size(); i++)
0673 {
0674 if (Verbosity() > 3)
0675 {
0676 std::cout << "adding triplet(" << passing_below_ckeys[i] << ", " << centerCluster.second << ", " << passing_above_ckeys[i] << ")" << std::endl;
0677 }
0678 triplets[l_index].push_back({passing_below_ckeys[i], centerCluster.second, passing_above_ckeys[i]});
0679 }
0680 }
0681 }
0682 if (Verbosity() > 1)
0683 {
0684 std::cout << "layer: " << l << " formed " << triplets[l_index].size() << " triplets" << std::endl;
0685
0686 if (Verbosity() > 3)
0687 {
0688 for (const Triplet& triplet : triplets[l_index])
0689 {
0690 std::cout << " triplet (bottom, center, top): " << (uint64_t) triplet.bottom << ", " << (uint64_t) triplet.center << ", " << (uint64_t) triplet.top << std::endl;
0691 }
0692 }
0693 }
0694 }
0695 return triplets;
0696 }
0697
0698 std::vector<PHCASiliconSeeding::keyList> PHCASiliconSeeding::FollowLinks(const std::vector<std::vector<PHCASiliconSeeding::Triplet>>& triplets)
0699 {
0700 std::vector<keyList> finishedSeeds;
0701 std::vector<keyList> growingSeeds;
0702
0703 for (const Triplet& start_triplet : triplets[1])
0704 {
0705 growingSeeds.push_back({start_triplet.bottom, start_triplet.center, start_triplet.top});
0706 }
0707 if (Verbosity() > 1)
0708 {
0709 std::cout << "Started with " << growingSeeds.size() << " stubs" << std::endl;
0710 }
0711
0712 for (size_t l = _start_layer + 1; l <= _end_layer - 1; l++)
0713 {
0714 if (Verbosity() > 1)
0715 {
0716 std::cout << "layer " << l << " _start_layer " << _start_layer << " _end_layer " << _end_layer << std::endl;
0717 std::cout << growingSeeds.size() << " still-growing seeds" << std::endl;
0718 std::cout << finishedSeeds.size() << " finished seeds" << std::endl;
0719 }
0720 std::vector<keyList> tempSeeds;
0721 const size_t l_index = l - _start_layer;
0722
0723 if (Verbosity() > 3)
0724 {
0725 std::cout << "growing current seeds" << std::endl;
0726 }
0727 for (const keyList& seed : growingSeeds)
0728 {
0729 if (Verbosity() > 3)
0730 {
0731 std::cout << "current keys: ";
0732
0733 for (const TrkrDefs::cluskey& key : seed)
0734 {
0735 std::cout << (uint64_t) key << ", ";
0736 }
0737 std::cout << std::endl;
0738 }
0739 const TrkrDefs::cluskey currentTop = seed.back();
0740 const TrkrDefs::cluskey currentCenter = seed.crbegin()[1];
0741 bool finished = true;
0742
0743 if (Verbosity() > 3)
0744 {
0745 std::cout << " searching for candidates to extend seed with top key: " << (uint64_t) currentTop << " and center key: " << (uint64_t) currentCenter << std::endl;
0746 std::cout << " number of candidate triplets " << ": " << triplets[l_index + 1].size() << std::endl;
0747 }
0748
0749 for (const Triplet& candidate_triplet : triplets[l_index + 1])
0750 {
0751 if (Verbosity() > 3)
0752 {
0753 std::cout << " candidate triplet: " << (uint64_t) candidate_triplet.bottom << ", " << (uint64_t) candidate_triplet.center << ", " << (uint64_t) candidate_triplet.top << std::endl;
0754 }
0755
0756 if (candidate_triplet.center == currentTop && candidate_triplet.bottom == currentCenter)
0757 {
0758 if (Verbosity() > 3)
0759 {
0760 std::cout << "found next candidate -- keys are " << (uint64_t) candidate_triplet.bottom << ", " << (uint64_t) candidate_triplet.center << ", " << (uint64_t) candidate_triplet.top << std::endl;
0761 }
0762 finished = false;
0763 keyList tempSeed = seed;
0764 tempSeed.push_back(candidate_triplet.top);
0765 tempSeeds.push_back(tempSeed);
0766 }
0767 }
0768
0769 if (finished)
0770 {
0771 finishedSeeds.push_back(seed);
0772 }
0773 }
0774
0775 int new_seed_count = 0;
0776 if (Verbosity() > 3)
0777 {
0778 std::cout << "starting new seeds" << std::endl;
0779 }
0780 for (const Triplet& triplet : triplets[l_index + 1])
0781 {
0782 if (Verbosity() > 3)
0783 {
0784 std::cout << " candidate triplet: " << (uint64_t) triplet.bottom << ", " << (uint64_t) triplet.center << ", " << (uint64_t) triplet.top << std::endl;
0785 }
0786 bool has_existing_seed = false;
0787 for (const keyList& seed : tempSeeds)
0788 {
0789 if (seed.back() == triplet.top && seed.crbegin()[1] == triplet.center && seed.crbegin()[2] == triplet.bottom)
0790 {
0791 if (Verbosity() > 3)
0792 {
0793 std::cout << "has existing seed with keys ";
0794
0795 for (const TrkrDefs::cluskey& key : seed)
0796 {
0797 std::cout << (uint64_t) key << ", ";
0798 }
0799 std::cout << std::endl;
0800 }
0801 has_existing_seed = true;
0802 }
0803 }
0804 if (!has_existing_seed)
0805 {
0806 if (Verbosity() > 3)
0807 {
0808 std::cout << "did not find existing seed" << std::endl;
0809 }
0810 new_seed_count++;
0811 tempSeeds.push_back({triplet.bottom, triplet.center, triplet.top});
0812 }
0813 }
0814 if (Verbosity() > 1)
0815 {
0816 std::cout << "started " << new_seed_count << " new seeds this layer" << std::endl;
0817 }
0818 growingSeeds = tempSeeds;
0819 }
0820
0821 finishedSeeds.insert(finishedSeeds.end(), growingSeeds.begin(), growingSeeds.end());
0822
0823 return finishedSeeds;
0824 }
0825
0826 float PHCASiliconSeeding::getSeedQuality(const TrackSeed_v2& seed, const PHCASiliconSeeding::PositionMap& globalPositions) const
0827 {
0828 std::vector<std::pair<double, double>> xy_pts;
0829 std::vector<std::pair<double, double>> rz_pts;
0830 std::vector<float> xyerr;
0831 std::vector<float> zerr;
0832 for (auto iter = seed.begin_cluster_keys(); iter != seed.end_cluster_keys(); ++iter)
0833 {
0834 Acts::Vector3 pos = globalPositions.at(*iter);
0835 TrkrCluster* c = m_clusterMap->findCluster(*iter);
0836
0837 xy_pts.emplace_back(pos.x(), pos.y());
0838 rz_pts.emplace_back(sqrt(pos.x() * pos.x() + pos.y() * pos.y()), pos.z());
0839 xyerr.push_back(c->getRPhiError());
0840 zerr.push_back(c->getZError());
0841 }
0842 std::vector<double> circle_residuals = TrackFitUtils::getCircleClusterResiduals(xy_pts, fabs(1. / seed.get_qOverR()), seed.get_X0(), seed.get_Y0());
0843 std::vector<double> line_residuals = TrackFitUtils::getLineClusterResiduals(rz_pts, seed.get_slope(), seed.get_Z0());
0844
0845 float chi2 = 0;
0846 for (size_t i = 0; i < circle_residuals.size(); i++)
0847 {
0848 const float total_resid2 = circle_residuals[i] * circle_residuals[i] + line_residuals[i] * line_residuals[i];
0849 const float total_err2 = xyerr[i] * xyerr[i] + zerr[i] * zerr[i];
0850 chi2 += total_resid2 / total_err2;
0851 }
0852 const int ndf = 2 * seed.size_cluster_keys() - 5;
0853 return chi2 / ndf;
0854 }
0855
0856 void PHCASiliconSeeding::HelixPropagate(std::vector<TrackSeed_v2>& seeds, const PHCASiliconSeeding::PositionMap& globalPositions) const
0857 {
0858 for (TrackSeed_v2& seed : seeds)
0859 {
0860 if (Verbosity() > 3)
0861 {
0862 std::cout << std::endl
0863 << std::endl;
0864 std::cout << "================================" << std::endl;
0865 seed.identify();
0866 }
0867
0868 std::set<size_t> layers;
0869 for (size_t layer = _start_layer; layer <= _end_layer; layer++)
0870 {
0871 if (layer == 5 || layer == 6)
0872 {
0873 continue;
0874 }
0875 layers.insert(layer);
0876 }
0877
0878 std::vector<Acts::Vector3> clusterpos;
0879 std::vector<TrkrDefs::cluskey> clusters;
0880 std::set<int> seed_strobes;
0881
0882 for (auto iter = seed.begin_cluster_keys(); iter != seed.end_cluster_keys(); ++iter)
0883 {
0884 const TrkrDefs::cluskey ckey = *iter;
0885 clusters.push_back(ckey);
0886 clusterpos.push_back(globalPositions.at(ckey));
0887 if (TrkrDefs::getTrkrId(ckey) == TrkrDefs::mvtxId)
0888 {
0889 seed_strobes.insert(MvtxDefs::getStrobeId(ckey));
0890 }
0891
0892
0893
0894 if (TrkrDefs::getLayer(ckey) == 3 || TrkrDefs::getLayer(ckey) == 4)
0895 {
0896 layers.erase(3);
0897 }
0898 else if (TrkrDefs::getLayer(ckey) == 5 || TrkrDefs::getLayer(ckey) == 6)
0899 {
0900 layers.erase(4);
0901 }
0902 else
0903 {
0904 layers.erase(TrkrDefs::getLayer(ckey));
0905 }
0906 }
0907
0908 if (Verbosity() > 1 && seed_strobes.size() > 1)
0909 {
0910 std::cout << "WARNING: seed MVTX strobes not all equal, something probably went wrong earlier! Strobe cut will be ignored when propagating this seed." << std::endl;
0911 }
0912
0913 if (Verbosity() > 3)
0914 {
0915 std::cout << "layers already covered: ";
0916
0917 for (auto iter = seed.begin_cluster_keys(); iter != seed.end_cluster_keys(); ++iter)
0918 {
0919 std::cout << (size_t) TrkrDefs::getLayer(*iter) << ", ";
0920 }
0921 std::cout << std::endl;
0922
0923 std::cout << "layers to propagate: ";
0924 for (const auto& layer : layers)
0925 {
0926 std::cout << layer << ", ";
0927 }
0928 std::cout << std::endl;
0929 }
0930
0931 std::vector<pointKey> closeClusters;
0932
0933
0934 std::vector<float> fitpars;
0935 fitpars.push_back(1. / fabs(seed.get_qOverR()));
0936 fitpars.push_back(seed.get_X0());
0937 fitpars.push_back(seed.get_Y0());
0938 fitpars.push_back(seed.get_slope());
0939 fitpars.push_back(seed.get_Z0());
0940
0941
0942 constexpr float maxRadius = 14.;
0943 const TrackFitUtils::circle_circle_intersection_output_t outer_xypt = TrackFitUtils::circle_circle_intersection(maxRadius, fitpars[0], fitpars[1], fitpars[2]);
0944 const double& xplus = std::get<0>(outer_xypt);
0945 const double& yplus = std::get<1>(outer_xypt);
0946 const double& xminus = std::get<2>(outer_xypt);
0947 const double& yminus = std::get<3>(outer_xypt);
0948
0949 if (std::isnan(xplus) || std::isnan(yplus) || std::isnan(xminus) || std::isnan(yminus))
0950 {
0951 if (Verbosity() > 3)
0952 {
0953 std::cout << "projection to outer radius failed, skipping layer" << std::endl;
0954 }
0955 continue;
0956 }
0957
0958 const float z_outer = seed.get_Z0() + seed.get_slope() * maxRadius;
0959
0960 if (Verbosity() > 3)
0961 {
0962 std::cout << "circle intersection solutions: (" << xplus << ", " << yplus << "), (" << xminus << ", " << yminus << ")" << std::endl;
0963 std::cout << "projected Z: " << z_outer << std::endl;
0964 }
0965
0966
0967 const Acts::Vector3& last_clusterpos = clusterpos.back();
0968 const float dist_plus = sqrt((xplus - last_clusterpos.x()) * (xplus - last_clusterpos.x()) + (yplus - last_clusterpos.y()) * (yplus - last_clusterpos.y()));
0969 const float dist_minus = sqrt((xminus - last_clusterpos.x()) * (xminus - last_clusterpos.x()) + (yminus - last_clusterpos.y()) * (yminus - last_clusterpos.y()));
0970
0971 float x_outer;
0972 float y_outer;
0973 if (dist_plus < dist_minus)
0974 {
0975 x_outer = xplus;
0976 y_outer = yplus;
0977 }
0978 else
0979 {
0980 x_outer = xminus;
0981 y_outer = yminus;
0982 }
0983
0984 const float phi_outer = atan2(y_outer, x_outer);
0985
0986 const float phi_min = std::min(seed.get_phi(), phi_outer);
0987 const float phi_max = std::max(seed.get_phi(), phi_outer);
0988 const float z_min = std::min(seed.get_Z0(), z_outer);
0989 const float z_max = std::max(seed.get_Z0(), z_outer);
0990
0991 if (Verbosity() > 3)
0992 {
0993 std::cout << "outer track position: (" << x_outer << ", " << y_outer << ", " << z_outer << ")" << std::endl;
0994 std::cout << "phi range: " << phi_min << " - " << phi_max << std::endl;
0995 std::cout << "z range: " << z_min << " - " << z_max << std::endl;
0996 }
0997
0998 for (const size_t layer : layers)
0999 {
1000 if (Verbosity() > 3)
1001 {
1002 std::cout << "------------------------------------" << std::endl;
1003 std::cout << "layer " << layer << ": " << std::endl;
1004 std::cout << "current seed:" << std::endl;
1005 seed.identify();
1006 }
1007 const size_t l_index = layer - _start_layer;
1008
1009
1010 float z_window = 0.;
1011 float avg_phi = (phi_min + phi_max) / 2.;
1012 if (layer == _start_layer)
1013 {
1014 const float radius_layer_next = (layer + 1 < 3) ? GetMvtxRadiusByPhi(avg_phi, layer + 1) : radius_per_layer.at(layer + 1);
1015 z_window = (radius_layer_next - radius_per_layer.at(layer)) * (1. / _drdz_allowance);
1016 }
1017 else if (layer == _end_layer)
1018 {
1019 const float radius_layer_prev = (layer - 1 < 3) ? GetMvtxRadiusByPhi(avg_phi, layer - 1) : radius_per_layer.at(layer - 1);
1020 z_window = (radius_per_layer.at(layer) - radius_layer_prev) * (1. / _drdz_allowance);
1021 }
1022 else
1023 {
1024 const float radius_layer_prev = (layer - 1 < 3) ? GetMvtxRadiusByPhi(avg_phi, layer - 1) : radius_per_layer.at(layer - 1);
1025 float z_window_prev = (radius_per_layer.at(layer) - radius_layer_prev) * (1. / _drdz_allowance);
1026 const float radius_layer_next = (layer + 1 < 3) ? GetMvtxRadiusByPhi(avg_phi, layer + 1) : radius_per_layer.at(layer + 1);
1027 float z_window_next = (radius_layer_next - radius_per_layer.at(layer)) * (1. / _drdz_allowance);
1028 z_window = std::max(z_window_prev, z_window_next);
1029 }
1030
1031 if (Verbosity() > 3)
1032 {
1033 std::cout << "HelixPropagate to layer " << layer << " with z_window " << z_window << std::endl;
1034 }
1035
1036 QueryTree(_rtrees[l_index],
1037 phi_min - dphi_per_layer[layer],
1038 z_min - z_window,
1039 phi_max + dphi_per_layer[layer],
1040 z_max + z_window,
1041 closeClusters);
1042
1043 if (Verbosity() > 3)
1044 {
1045 std::cout << "found " << closeClusters.size() << " close clusters" << std::endl;
1046 }
1047 }
1048
1049
1050
1051 TrkrDefs::cluskey best_added = 0;
1052 float best_dca3d = 1e9;
1053
1054 for (const pointKey& closeCluster : closeClusters)
1055 {
1056 if (TrkrDefs::getTrkrId(closeCluster.second) == TrkrDefs::mvtxId && seed_strobes.size() == 1 && !ClusterTimesAreCompatible(TrkrDefs::mvtxId, *(seed_strobes.begin()), closeCluster.second))
1057 {
1058 continue;
1059 }
1060
1061 if (_require_INTT_consistency && seed.get_crossing() != SHRT_MAX && TrkrDefs::getTrkrId(closeCluster.second) == TrkrDefs::inttId && !ClusterTimesAreCompatible(TrkrDefs::inttId, seed.get_crossing(), closeCluster.second))
1062 {
1063 continue;
1064 }
1065
1066 const Acts::Vector3& closeclusterpos = globalPositions.at(closeCluster.second);
1067 const Acts::Vector3 pca = TrackFitUtils::get_helix_pca(fitpars, closeclusterpos);
1068
1069 const Acts::Vector3 residual = closeclusterpos - pca;
1070 const float dca_xy = sqrt(residual.x() * residual.x() + residual.y() * residual.y());
1071 const float dca_z = fabs(residual.z());
1072 const float dca_3d = sqrt(residual.x() * residual.x() + residual.y() * residual.y() + residual.z() * residual.z());
1073
1074 if (Verbosity() > 3)
1075 {
1076 std::cout << "cluster key: " << (size_t) closeCluster.second << std::endl;
1077 std::cout << "close cluster position: (" << closeclusterpos.x() << ", " << closeclusterpos.y() << ", " << closeclusterpos.z() << ")" << std::endl;
1078 std::cout << "helix PCA: (" << pca.x() << ", " << pca.y() << ", " << pca.z() << ")" << std::endl;
1079 std::cout << "residual: (" << residual.x() << ", " << residual.y() << ", " << residual.z() << ")" << std::endl;
1080 std::cout << "DCA: " << dca_xy << " (xy) " << dca_z << " (z) " << dca_3d << " (3D)" << std::endl;
1081 }
1082 const size_t layer = TrkrDefs::getLayer(closeCluster.second);
1083 if (dca_xy <= max_dcaxy_perlayer[layer] && dca_z <= max_dcaz_perlayer[layer] && dca_3d <= best_dca3d)
1084 {
1085 if (Verbosity() > 3)
1086 {
1087 std::cout << "passed cuts" << std::endl;
1088 }
1089 best_added = closeCluster.second;
1090 best_dca3d = dca_3d;
1091 }
1092 }
1093 if (best_added != 0)
1094 {
1095 if (Verbosity() > 3)
1096 {
1097 std::cout << "adding clusterkey: " << (size_t) best_added << " with 3d dca " << best_dca3d << std::endl;
1098 }
1099 seed.insert_cluster_key(best_added);
1100 FitSeed(seed, globalPositions);
1101 }
1102 }
1103 }
1104
1105 std::vector<TrackSeed_v2> PHCASiliconSeeding::FitSeeds(const std::vector<PHCASiliconSeeding::keyList>& chains, const PHCASiliconSeeding::PositionMap& globalPositions) const
1106 {
1107 std::vector<TrackSeed_v2> clean_chains;
1108
1109 for (const auto& chain : chains)
1110 {
1111 if (chain.size() < _min_clusters_per_track)
1112 {
1113 continue;
1114 }
1115 if (Verbosity() > 3)
1116 {
1117 std::cout << "chain size: " << chain.size() << std::endl;
1118 }
1119
1120 TrackSeedHelper::position_map_t positions;
1121 std::set<short> crossings;
1122 size_t nmvtx = 0;
1123 size_t nintt = 0;
1124 for (const auto& cluskey : chain)
1125 {
1126 const auto& global = globalPositions.at(cluskey);
1127 positions.insert(std::make_pair(cluskey, global));
1128 if (TrkrDefs::getTrkrId(cluskey) == TrkrDefs::mvtxId)
1129 {
1130 nmvtx++;
1131 }
1132 if (TrkrDefs::getTrkrId(cluskey) == TrkrDefs::inttId)
1133 {
1134 nintt++;
1135 crossings.insert(GetClusterTimeIndex(cluskey));
1136 }
1137 }
1138
1139 if (nmvtx < _min_mvtx_clusters || nintt < _min_intt_clusters)
1140 {
1141 continue;
1142 }
1143
1144 TrackSeed_v2 trackseed;
1145 for (const auto& key : chain)
1146 {
1147 trackseed.insert_cluster_key(key);
1148 }
1149
1150 TrackSeedHelper::circleFitByTaubin(&trackseed, positions, _start_layer, _end_layer);
1151 if (!(positions.size() == 3 && nintt == 2))
1152 {
1153 TrackSeedHelper::lineFit(&trackseed, positions, _start_layer, 2);
1154 }
1155 else
1156 {
1157 TrackSeedHelper::lineFit(&trackseed, positions, _start_layer, _end_layer);
1158 }
1159
1160 trackseed.set_phi(TrackSeedHelper::get_phi(&trackseed, positions));
1161
1162 if (crossings.size() == 1)
1163 {
1164 trackseed.set_crossing(*crossings.begin());
1165 }
1166 else if (crossings.size() == 2)
1167 {
1168 std::vector<short> crossings_vec;
1169 std::copy(crossings.begin(), crossings.end(), std::back_inserter(crossings_vec));
1170 if (abs(crossings_vec[1] - crossings_vec[0]) == 1)
1171 {
1172 trackseed.set_crossing(std::min(crossings_vec[0], crossings_vec[1]));
1173 }
1174 else
1175 {
1176 if (Verbosity() > 1)
1177 {
1178 std::cout << "Warning: seed has multiple crossings within INTT clusters, setting to SHRTMAX" << std::endl;
1179 }
1180 trackseed.set_crossing(SHRT_MAX);
1181 }
1182 }
1183 else
1184 {
1185 if (crossings.size() > 2 && Verbosity() > 1)
1186 {
1187 std::cout << "Warning: seed has multiple crossings within INTT clusters, setting to SHRTMAX" << std::endl;
1188 }
1189 trackseed.set_crossing(SHRT_MAX);
1190 }
1191
1192 clean_chains.push_back(trackseed);
1193 if (Verbosity() > 2)
1194 {
1195 std::cout << "pushed clean chain with " << trackseed.size_cluster_keys() << " clusters" << std::endl;
1196 }
1197 }
1198
1199 return clean_chains;
1200 }
1201
1202 void PHCASiliconSeeding::FitSeed(TrackSeed_v2& seed, const PositionMap& globalPositions) const
1203 {
1204 if (Verbosity() > 3)
1205 {
1206 std::cout << "fitting seed:" << std::endl;
1207 seed.identify();
1208 }
1209 TrackSeedHelper::position_map_t positions;
1210 std::set<short> crossings;
1211 size_t nintt = 0;
1212 for (auto clusiter = seed.begin_cluster_keys(); clusiter != seed.end_cluster_keys(); ++clusiter)
1213 {
1214 TrkrDefs::cluskey key = *clusiter;
1215 const auto& global = globalPositions.at(key);
1216 positions.insert(std::make_pair(key, global));
1217
1218 if (TrkrDefs::getTrkrId(key) == TrkrDefs::inttId)
1219 {
1220 nintt++;
1221 crossings.insert(GetClusterTimeIndex(key));
1222 }
1223 }
1224
1225 TrackSeedHelper::circleFitByTaubin(&seed, positions, _start_layer, _end_layer);
1226 if (!(positions.size() == 3 && nintt == 2))
1227 {
1228 TrackSeedHelper::lineFit(&seed, positions, _start_layer, 2);
1229 }
1230 else
1231 {
1232 TrackSeedHelper::lineFit(&seed, positions, _start_layer, _end_layer);
1233 }
1234
1235 seed.set_phi(TrackSeedHelper::get_phi(&seed, positions));
1236
1237 if (crossings.size() == 1)
1238 {
1239 seed.set_crossing(*crossings.begin());
1240 }
1241 else if (crossings.size() == 2)
1242 {
1243 std::vector<short> crossings_vec;
1244 std::copy(crossings.begin(), crossings.end(), std::back_inserter(crossings_vec));
1245 if (abs(crossings_vec[1] - crossings_vec[0]) == 1)
1246 {
1247 seed.set_crossing(std::min(crossings_vec[0], crossings_vec[1]));
1248 }
1249 else
1250 {
1251 if (Verbosity() > 1)
1252 {
1253 std::cout << "Warning: seed has multiple crossings within INTT clusters, setting to SHRTMAX" << std::endl;
1254 }
1255 seed.set_crossing(SHRT_MAX);
1256 }
1257 }
1258 else
1259 {
1260 if (crossings.size() > 2 && Verbosity() > 1)
1261 {
1262 std::cout << "Warning: seed has multiple crossings within INTT clusters, setting to SHRTMAX" << std::endl;
1263 }
1264 seed.set_crossing(SHRT_MAX);
1265 }
1266 if (Verbosity() > 3)
1267 {
1268 std::cout << "after fit:" << std::endl;
1269 seed.identify();
1270 }
1271 }
1272
1273 void PHCASiliconSeeding::publishSeeds(const std::vector<TrackSeed_v2>& seeds) const
1274 {
1275 for (const auto& seed : seeds)
1276 {
1277 auto pseed = std::make_unique<TrackSeed_v2>(seed);
1278 if (Verbosity() > 4)
1279 {
1280 pseed->identify();
1281 }
1282 if (timingMismatch(*pseed))
1283 {
1284 continue;
1285 }
1286 _track_map->insert(pseed.get());
1287 }
1288 }
1289 bool PHCASiliconSeeding::timingMismatch(const TrackSeed& seed) const
1290 {
1291 std::set<int> mvtx_strobes;
1292 std::set<int> intt_crossings;
1293
1294 for (auto it = seed.begin_cluster_keys(); it != seed.end_cluster_keys(); ++it)
1295 {
1296 TrkrDefs::cluskey cluskey = *it;
1297 const unsigned int trkrid = TrkrDefs::getTrkrId(cluskey);
1298 if (trkrid == TrkrDefs::TrkrId::mvtxId)
1299 {
1300 mvtx_strobes.insert(MvtxDefs::getStrobeId(cluskey));
1301 }
1302 if (trkrid == TrkrDefs::TrkrId::inttId)
1303 {
1304 intt_crossings.insert(InttDefs::getTimeBucketId(cluskey));
1305 }
1306 }
1307
1308 if (mvtx_strobes.size() > 1)
1309 {
1310 return true;
1311 }
1312 if (intt_crossings.size() > 2)
1313 {
1314 return true;
1315 }
1316 int crossing1 = *intt_crossings.begin();
1317 int crossing2 = *intt_crossings.rbegin();
1318
1319 if (abs(crossing2 - crossing1) > 2)
1320 {
1321 return true;
1322 }
1323
1324 int mvtx_strobe = *mvtx_strobes.begin();
1325 int strobecrossinglow = (mvtx_strobe - 1) * _strobe_width;
1326 int strobecrossinghigh = (mvtx_strobe + 1) * _strobe_width;
1327 if (crossing1 < strobecrossinglow || crossing1 > strobecrossinghigh)
1328 {
1329 if (crossing2 < strobecrossinglow || crossing2 > strobecrossinghigh)
1330 {
1331 return true;
1332 }
1333 }
1334
1335 return false;
1336 }
1337 int PHCASiliconSeeding::Setup(PHCompositeNode* topNode)
1338 {
1339 if (Verbosity() > 0)
1340 {
1341 std::cout << "Called Setup" << std::endl;
1342 }
1343 if (Verbosity() > 0)
1344 {
1345 std::cout << "topNode:" << topNode << std::endl;
1346 }
1347 PHTrackSeeding::set_track_map_name(_module_trackmap_name);
1348 PHTrackSeeding::Setup(topNode);
1349 auto* recoConsts = recoConsts::instance();
1350 int runnumber = recoConsts->get_IntFlag("RUNNUMBER");
1351 float defstrobe = _strobe_width;
1352 _strobe_width = MvtxRawDefs::getStrobeLength(runnumber) * 10;
1353 if(std::isnan(_strobe_width))
1354 {
1355 _strobe_width = defstrobe;
1356 }
1357
1358 int ret = InitializeGeometry(topNode);
1359 if (ret != Fun4AllReturnCodes::EVENT_OK)
1360 {
1361 return ret;
1362 }
1363
1364 for (size_t i = _start_layer; i <= _end_layer; ++i)
1365 {
1366 if (i >= 3 && i <= 6)
1367 {
1368
1369
1370 max_dcaz_perlayer[i] = std::max<float>(_propagate_max_dcaz, 1.);
1371 max_dcaxy_perlayer[i] = _propagate_max_dcaxy;
1372 dphi_per_layer[i] = _neighbor_phi_width;
1373 }
1374 else
1375 {
1376 max_dcaz_perlayer[i] = _propagate_max_dcaz;
1377 max_dcaxy_perlayer[i] = _propagate_max_dcaxy;
1378 dphi_per_layer[i] = _neighbor_phi_width;
1379 }
1380 }
1381
1382 return Fun4AllReturnCodes::EVENT_OK;
1383 }
1384
1385 void PHCASiliconSeeding::SetupDefaultLayerRadius()
1386 {
1387
1388 PHG4CylinderGeomContainer::ConstRange mvtxlayerrange = geom_container_mvtx->get_begin_end();
1389 for (PHG4CylinderGeomContainer::ConstIterator layeriter = mvtxlayerrange.first;
1390 layeriter != mvtxlayerrange.second;
1391 ++layeriter)
1392 {
1393 int layer = layeriter->second->get_layer();
1394 auto* layergeom = dynamic_cast<CylinderGeom_Mvtx*>(geom_container_mvtx->GetLayerGeom(layer));
1395 if (layergeom)
1396 {
1397 radius_per_layer[layer] = layergeom->get_radius();
1398 if (Verbosity() > 0)
1399 {
1400 std::cout << "PHCASiliconSeeding::SetupLayerRadius - MVTX layer " << layer << " radius: " << layergeom->get_radius() << " cm" << std::endl;
1401 }
1402 }
1403 }
1404
1405
1406 PHG4CylinderGeomContainer::ConstRange inttlayerrange = geom_container_intt->get_begin_end();
1407 for (PHG4CylinderGeomContainer::ConstIterator layeriter = inttlayerrange.first;
1408 layeriter != inttlayerrange.second;
1409 ++layeriter)
1410 {
1411 int layer = layeriter->second->get_layer();
1412 auto* layergeom = dynamic_cast<CylinderGeomIntt*>(geom_container_intt->GetLayerGeom(layer));
1413 if (layergeom)
1414 {
1415 radius_per_layer[layer] = layergeom->get_radius();
1416 if (Verbosity() > 0)
1417 {
1418 std::cout << "PHCASiliconSeeding::SetupLayerRadius - INTT layer " << layer << " radius: " << layergeom->get_radius() << " cm" << std::endl;
1419 }
1420 }
1421 }
1422 }
1423
1424 float PHCASiliconSeeding::GetMvtxRadiusByPhi(float clusphi, int layer) const
1425 {
1426 float phi0 = std::atan2(v_globaldisplacement[1], v_globaldisplacement[0]);
1427 if (phi0 < 0)
1428 {
1429 phi0 += 2 * M_PI;
1430 }
1431
1432 float radius_original = radius_per_layer.at(layer);
1433 float radius_corrected = radius_original * (1.0 + (radius_displacement / radius_original) * std::cos(clusphi - phi0));
1434 return radius_corrected;
1435 }
1436
1437 int PHCASiliconSeeding::End()
1438 {
1439 if (Verbosity() > 0)
1440 {
1441 std::cout << "Called End " << std::endl;
1442 }
1443 return Fun4AllReturnCodes::EVENT_OK;
1444 }