23 #include <phfield/PHFieldConfigv2.h>
40 #include <boost/geometry.hpp>
41 #include <boost/geometry/geometries/box.hpp>
42 #include <boost/geometry/geometries/point.hpp>
43 #include <boost/geometry/index/rtree.hpp>
44 #include <boost/geometry/policies/compare.hpp>
47 #include <Eigen/Dense>
56 #include <unordered_set>
62 #define LogDebug(exp) if(Verbosity()>0) std::cout << "DEBUG: " << __FILE__ << ": " << __LINE__ << ": " << exp
64 #define LogDebug(exp) (void)0
67 #define LogError(exp) if(Verbosity()>0) std::cout << "ERROR: " << __FILE__ << ": " << __LINE__ << ": " << exp
68 #define LogWarning(exp) if(Verbosity()>0) std::cout << "WARNING: " << __FILE__ << ": " << __LINE__ << ": " << exp
74 typedef bg::model::point<float, 3, bg::cs::cartesian>
point;
75 typedef bg::model::box<point>
box;
76 typedef std::pair<point, TrkrDefs::cluskey>
pointKey;
79 typedef std::vector<TrkrDefs::cluskey>
keylist;
86 template<
typename T,
size_t N>
98 h = h * 31 + hasher(a[
i]);
103 template<
typename A,
typename B>
113 return (hashA(a.first)*31+hashB(a.second));
122 template<
class T>
inline constexpr
T square(
const T&
x ) {
return x*
x; }
127 double phi = std::atan2( position.y(), position.x() );
128 if( phi < 0 ) phi += 2.*M_PI;
136 return std::log((norm+position.z())/(norm-position.z()))/2;
143 {
return std::make_pair(std::array<float,3>({p.first.get<0>(),p.first.get<1>(),p.first.get<2>()}),p.second); }
145 std::vector<coordKey> fromPointKey(
const std::vector<pointKey>& p)
147 std::vector<coordKey>
output;
148 output.resize(p.size());
150 {
return fromPointKey(
point); } );
155 double breaking_angle(
double x1,
double y1,
double z1,
double x2,
double y2,
double z2)
157 double l1 = sqrt(x1*x1+y1*y1+z1*z1);
158 double l2 = sqrt(x2*x2+y2*y2+z2*z2);
159 double sx = (x1/l1+x2/
l2);
160 double sy = (y1/l1+y2/
l2);
161 double sz = (z1/l1+z2/
l2);
162 double dx = (x1/l1-x2/
l2);
163 double dy = (y1/l1-y2/
l2);
164 double dz = (z1/l1-z2/
l2);
165 return 2*atan2(sqrt(dx*dx+dy*dy+dz*dz),sqrt(sx*sx+sy*sy+sz*sz));
176 unsigned int start_layer,
177 unsigned int end_layer,
178 unsigned int min_nhits_per_cluster,
179 unsigned int min_clusters_per_track,
180 unsigned int nlayers_maps,
182 unsigned int nlayers_tpc,
183 float neighbor_phi_width,
184 float neighbor_eta_width,
186 float cosTheta_limit)
188 , _nlayers_maps(nlayers_maps)
189 , _nlayers_intt(nlayers_intt)
190 , _nlayers_tpc(nlayers_tpc)
191 , _start_layer(start_layer)
192 , _end_layer(end_layer)
193 , _min_nhits_per_cluster(min_nhits_per_cluster)
194 , _min_clusters_per_track(min_clusters_per_track)
195 , _neighbor_phi_width(neighbor_phi_width)
196 , _neighbor_eta_width(neighbor_eta_width)
197 , _max_sin_phi(maxSinPhi)
198 , _cosTheta_limit(cosTheta_limit)
204 tGeometry = findNode::getClass<ActsGeometry>(topNode,
"ActsGeometry");
207 std::cout <<
PHWHERE <<
"No acts tracking geometry, can't proceed" << std::endl;
227 double phimin_2pi =
phimin;
228 double phimax_2pi = phimax;
229 if (phimin < 0) phimin_2pi = 2*M_PI+
phimin;
230 if (phimax > 2*M_PI) phimax_2pi = phimax-2*M_PI;
231 rtree.query(bgi::intersects(
box(
point(phimin_2pi, etamin, lmin),
point(phimax_2pi, etamax, lmax))), std::back_inserter(returned_values));
238 std::cout <<
"fill tree..." << std::endl;
246 for (
int j = 0;
j < 60; ++
j) nlayer[
j] = 0;
250 for(
auto clusIter = range.first; clusIter != range.second; ++clusIter ){
255 if (layer < _start_layer || layer >=
_end_layer){
256 if(
Verbosity()>0) std::cout <<
"layer: " << layer << std::endl;
270 std::cout <<
"CaSeeder: Cluster: " << ckey << std::endl;
271 std::cout <<
" Global before: " << global_before[0] <<
" " << global_before[1] <<
" " << global_before[2] << std::endl;
272 std::cout <<
" Global after : " << globalpos_d[0] <<
" " << globalpos_d[1] <<
" " << globalpos_d[2] << std::endl;
275 const Acts::Vector3 globalpos = { globalpos_d.x(), globalpos_d.y(), globalpos_d.z()};
276 cachedPositions.insert(std::make_pair(ckey, globalpos));
278 const double clus_phi = get_phi( globalpos );
279 const double clus_eta = get_eta( globalpos );
280 const double clus_l =
layer;
283 std::cout <<
"Found cluster " << ckey <<
" in layer " << layer << std::endl;
285 std::vector<pointKey> testduplicate;
286 QueryTree(
_rtree, clus_phi - 0.00001, clus_eta - 0.00001, layer - 0.5, clus_phi + 0.00001, clus_eta + 0.00001, layer + 0.5, testduplicate);
287 if (!testduplicate.empty())
294 _rtree.insert(std::make_pair(
point(clus_phi, globalpos_d.z(), clus_l), ckey));
298 if(
Verbosity()>1)
for (
int j = 0;
j < 60; ++
j) std::cout <<
"nhits in layer " <<
j <<
": " << nlayer[
j] << std::endl;
299 if(
Verbosity()>0) std::cout <<
"fill time: " <<
t_fill->get_accumulated_time() / 1000. <<
" sec" << std::endl;
300 if(
Verbosity()>0) std::cout <<
"number of duplicates : " << n_dupli << std::endl;
301 return cachedPositions;
308 std::cout <<
" Process... " << std::endl;
313 std::cerr <<
PHWHERE <<
"Cluster Iteration Map missing, aborting." << std::endl;
323 if(
Verbosity()>0) std::cout <<
"Initial RTree fill time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
325 int numberofseeds = 0;
328 if(
Verbosity()>0) std::cout <<
"number of seeds " << numberofseeds << std::endl;
329 if(
Verbosity()>0) std::cout <<
"Kalman filtering time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
338 std::vector<pointKey> allClusters;
339 std::vector<std::unordered_set<keylink>> belowLinks;
340 std::vector<std::unordered_set<keylink>> aboveLinks;
352 if(
Verbosity()>0) std::cout <<
"allClusters search time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
353 LogDebug(
" number of clusters: " << allClusters.size() << std::endl);
356 std::pair<std::vector<std::unordered_set<keylink>>,std::vector<std::unordered_set<keylink>>> links =
CreateLinks(fromPointKey(allClusters), globalPositions);
357 std::vector<std::vector<keylink>> biLinks =
FindBiLinks(links.first,links.second);
358 std::vector<keylist> trackSeedKeyLists =
FollowBiLinks(biLinks,globalPositions);
359 std::vector<TrackSeed_v1> seeds =
RemoveBadClusters(trackSeedKeyLists, globalPositions);
367 size_t nclusters = 0;
369 double cluster_find_time = 0;
370 double rtree_query_time = 0;
371 double transform_time = 0;
372 double compute_best_angle_time = 0;
373 double set_insert_time = 0;
375 std::vector<std::unordered_set<keylink>> belowLinks;
376 std::vector<std::unordered_set<keylink>> aboveLinks;
380 for (
auto StartCluster = clusters.begin(); StartCluster != clusters.end(); ++StartCluster)
384 double StartPhi = StartCluster->first[0];
386 unsigned int StartLayer = StartCluster->first[2];
389 const auto& globalpos = globalPositions.at(StartCluster->second);
390 double StartX = globalpos(0);
391 double StartY = globalpos(1);
392 double StartZ = globalpos(2);
394 cluster_find_time +=
t_seed->elapsed();
396 LogDebug(
" starting cluster:" << std::endl);
397 LogDebug(
" z: " << StartZ << std::endl);
398 LogDebug(
" phi: " << StartPhi << std::endl);
399 LogDebug(
" layer: " << StartLayer << std::endl);
401 std::vector<pointKey> ClustersAbove;
402 std::vector<pointKey> ClustersBelow;
406 (
double) StartLayer - 1.5,
409 (
double) StartLayer - 0.5,
414 (
double) StartLayer + 0.5,
417 (
double) StartLayer + 1.5,
420 rtree_query_time +=
t_seed->elapsed();
422 LogDebug(
" entries in below layer: " << ClustersBelow.size() << std::endl);
423 LogDebug(
" entries in above layer: " << ClustersAbove.size() << std::endl);
424 std::vector<std::array<double,3>> delta_below;
425 std::vector<std::array<double,3>> delta_above;
428 delta_below.resize(ClustersBelow.size());
429 delta_above.resize(ClustersAbove.size());
432 std::transform(ClustersBelow.begin(),ClustersBelow.end(),delta_below.begin(),
434 const auto& belowpos = globalPositions.at(BelowCandidate.second);
435 return std::array<double,3>{belowpos(0)-StartX,
437 belowpos(2)-StartZ};});
439 std::transform(ClustersAbove.begin(),ClustersAbove.end(),delta_above.begin(),
441 const auto& abovepos = globalPositions.at(AboveCandidate.second);
442 return std::array<double,3>{abovepos(0)-StartX,
444 abovepos(2)-StartZ};});
446 transform_time +=
t_seed->elapsed();
451 double maxCosPlaneAngle = -0.95;
453 std::vector<coordKey> bestBelowClusters;
454 std::vector<coordKey> bestAboveClusters;
455 for(
size_t iAbove = 0; iAbove<delta_above.size(); ++iAbove)
457 for(
size_t iBelow = 0; iBelow<delta_below.size(); ++iBelow)
462 double angle = breaking_angle(
463 delta_below[iBelow][0],
464 delta_below[iBelow][1],
465 delta_below[iBelow][2],
466 delta_above[iAbove][0],
467 delta_above[iAbove][1],
468 delta_above[iAbove][2]);
469 if(cos(angle) < maxCosPlaneAngle)
475 bestBelowClusters.push_back(fromPointKey(ClustersBelow[iBelow]));
476 bestAboveClusters.push_back(fromPointKey(ClustersAbove[iAbove]));
563 compute_best_angle_time +=
t_seed->elapsed();
568 for(
auto cluster : bestBelowClusters) belowLinks[layer_index].insert(
keylink{{*StartCluster,cluster}});
569 for(
auto cluster : bestAboveClusters) aboveLinks[layer_index].insert(
keylink{{*StartCluster,cluster}});
571 set_insert_time +=
t_seed->elapsed();
573 LogDebug(
" max collinearity: " << maxCosPlaneAngle << std::endl);
578 std::cout <<
"triplet forming time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
579 std::cout <<
"starting cluster setup: " << cluster_find_time / 1000 <<
" s" << std::endl;
580 std::cout <<
"RTree query: " << rtree_query_time /1000 <<
" s" << std::endl;
581 std::cout <<
"Transform: " << transform_time /1000 <<
" s" << std::endl;
582 std::cout <<
"Compute best triplet: " << compute_best_angle_time /1000 <<
" s" << std::endl;
583 std::cout <<
"Set insert: " << set_insert_time /1000 <<
" s" << std::endl;
587 return std::make_pair(belowLinks,aboveLinks);
590 std::vector<std::vector<keylink>>
PHCASeeding::FindBiLinks(
const std::vector<std::unordered_set<keylink>>& belowLinks,
const std::vector<std::unordered_set<keylink>>& aboveLinks)
const
593 std::vector<std::vector<keylink>> bidirectionalLinks;
597 for(
auto belowLink = belowLinks[
layer].
begin(); belowLink != belowLinks[
layer].end(); ++belowLink)
599 if((*belowLink)[1].second==0)
continue;
602 auto sameAboveLinkExists = aboveLinks[end_layer_index].find(reversed);
603 if(sameAboveLinkExists != aboveLinks[end_layer_index].
end())
605 bidirectionalLinks[
layer].push_back((*belowLink));
610 if(
Verbosity()>0) std::cout <<
"bidirectional link forming time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
613 return bidirectionalLinks;
620 auto& a_pos = globalPositions.at(a);
621 auto& b_pos = globalPositions.at(b);
622 auto& c_pos = globalPositions.at(c);
623 double hypot_length = sqrt(square<double>(c_pos.x()-a_pos.x())+square<double>(c_pos.y()-a_pos.y())+square<double>(c_pos.z()-a_pos.z()));
624 double break_angle = breaking_angle(
630 c_pos.z()-b_pos.z());
631 return 2*sin(break_angle)/hypot_length;
638 std::vector<keylist> trackSeedPairs;
643 for(
auto startCand = bidirectionalLinks[
layer].
begin(); startCand != bidirectionalLinks[
layer].end(); ++startCand)
645 bool has_above_link =
false;
646 unsigned int imax = 1;
647 if(
layer==_nlayers_tpc-2) imax = 1;
648 for(
unsigned int i=1;
i<=imax;
i++)
650 has_above_link = has_above_link || std::any_of(bidirectionalLinks[
layer+
i].
begin(),bidirectionalLinks[
layer+
i].
end(),[&](
keylink k){
return (*startCand)[0]==k[1];});
659 trackSeedPairs.push_back({(*startCand)[0].second,(*startCand)[1].second});
665 std::vector<keylist> trackSeedKeyLists;
666 for(
auto& trackKeyChain : trackSeedPairs)
670 for(
auto& testlink : bidirectionalLinks[trackHead_layer])
672 if(testlink[0].second==trackHead)
675 trackSeedTriplet.push_back(trackKeyChain[0]);
676 trackSeedTriplet.push_back(trackKeyChain[1]);
677 trackSeedTriplet.push_back(testlink[1].second);
678 trackSeedKeyLists.push_back(trackSeedTriplet);
684 if(
Verbosity()>0) std::cout <<
"starting cluster finding time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
691 std::vector<keylist> tempSeedKeyLists = trackSeedKeyLists;
692 trackSeedKeyLists.clear();
694 while(tempSeedKeyLists.size()>0)
696 if(
Verbosity()>0) std::cout <<
"temp size: " << tempSeedKeyLists.size() << std::endl;
697 if(
Verbosity()>0) std::cout <<
"final size: " << trackSeedKeyLists.size() << std::endl;
698 std::vector<keylist> newtempSeedKeyLists;
699 for(
auto&
seed : tempSeedKeyLists)
704 for(
auto& link : bidirectionalLinks[trackHead_layer])
706 if(link[0].second != trackHead)
continue;
707 auto& head_pos = globalPositions.at(trackHead);
708 auto& prev_pos = globalPositions.at(
seed.rbegin()[1]);
709 float x1 = head_pos.x();
710 float y1 = head_pos.y();
711 float z1 = head_pos.z();
712 float x2 = prev_pos.x();
713 float y2 = prev_pos.y();
714 float z2 = prev_pos.z();
715 float dr_12 = sqrt(x1*x1+y1*y1)-sqrt(x2*x2+y2*y2);
717 auto& test_pos = globalPositions.at(testCluster);
718 float xt = test_pos.x();
719 float yt = test_pos.y();
720 float zt = test_pos.z();
721 float new_dr = sqrt(xt*xt+yt*yt)-sqrt(x1*x1+y1*y1);
722 if(fabs( (z1-z2)/dr_12 - (zt-z1)/new_dr )>0.5)
continue;
723 auto& third_pos = globalPositions.at(
seed.rbegin()[2]);
724 float x3 = third_pos.x();
725 float y3 = third_pos.y();
726 float dr_23 = sqrt(x2*x2+y2*y2)-sqrt(x3*x3+y3*y3);
727 float phi1 = atan2(y1,x1);
728 float phi2 = atan2(y2,x2);
729 float phi3 = atan2(y3,x3);
730 float dphi12 = std::fmod(phi1-phi2,M_PI);
731 float dphi23 = std::fmod(phi2-phi3,M_PI);
732 float d2phidr2 = dphi12/(dr_12*dr_12)-dphi23/(dr_23*dr_23);
733 float new_dphi = std::fmod(atan2(yt,xt)-atan2(y1,x1),M_PI);
734 float new_d2phidr2 = new_dphi/(new_dr*new_dr)-dphi12/(dr_12*dr_12);
735 if(
seed.size()<6 && fabs(d2phidr2-new_d2phidr2)<.005)
739 newseed.push_back(link[1].second);
740 newtempSeedKeyLists.push_back(newseed);
745 trackSeedKeyLists.push_back(
seed);
748 if(
Verbosity()>0) std::cout <<
"new temp size: " << newtempSeedKeyLists.size() << std::endl;
749 tempSeedKeyLists = newtempSeedKeyLists;
808 if(
Verbosity()>0) std::cout <<
"keychain assembly time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
810 LogDebug(
" track key chains assembled: " << trackSeedKeyLists.size() << std::endl);
811 LogDebug(
" track key chain lengths: " << std::endl);
812 for(
auto trackKeyChain = trackSeedKeyLists.begin(); trackKeyChain != trackSeedKeyLists.end(); ++trackKeyChain)
814 LogDebug(
" " << trackKeyChain->size() << std::endl);
817 LogDebug(
" track key associations:" << std::endl);
818 for(
size_t i=0;
i<trackSeedKeyLists.size();++
i)
820 LogDebug(
" seed " <<
i <<
":" << std::endl);
822 double lasteta = -100;
823 double lastphi = -100;
824 for(
size_t j=0;
j<trackSeedKeyLists[
i].size();++
j)
826 const auto& globalpos = globalPositions.at(trackSeedKeyLists[
i][
j]);
827 const double clus_phi = get_phi( globalpos );
828 const double clus_eta = get_eta( globalpos );
829 const double etajump = clus_eta-lasteta;
830 const double phijump = clus_phi-lastphi;
834 if((fabs(etajump)>0.1 && lasteta!=-100) || (fabs(phijump)>1 && lastphi!=-100))
836 LogDebug(
" Eta or Phi jump too large! " << std::endl);
839 LogDebug(
" (eta,phi,layer) = (" << clus_eta <<
"," << clus_phi <<
"," << lay <<
") " <<
840 " (x,y,z) = (" << globalpos(0) <<
"," << globalpos(1) <<
"," << globalpos(2) <<
")" << std::endl);
845 std::cout <<
" eta, phi, layer = (" << clus_eta <<
"," << clus_phi <<
"," << lay <<
") " <<
846 " (x,y,z) = (" << globalpos(0) <<
"," << globalpos(1) <<
"," << globalpos(2) <<
")" << std::endl;
852 LogDebug(
" Total large jumps: " << jumpcount << std::endl);
854 if(
Verbosity()>0) std::cout <<
"eta-phi sanity check time: " <<
t_seed->get_accumulated_time() / 1000 <<
" s" << std::endl;
856 return trackSeedKeyLists;
861 if(
Verbosity()>0) std::cout <<
"removing bad clusters" << std::endl;
862 std::vector<TrackSeed_v1> clean_chains;
864 for(
const auto& chain : chains)
866 if(chain.size()<3)
continue;
867 if(
Verbosity()>0) std::cout <<
"chain size: " << chain.size() << std::endl;
870 for(
const auto& ckey:chain )
872 const auto &global = globalPositions.at(ckey);
873 xy_pts.emplace_back( global.x(), global.y() );
880 if( std::isnan(
R ) )
continue;
887 for(
size_t i=0;
i<chain.size();
i++)
893 clean_chains.push_back(trackseed);
904 for(
const auto&
seed:seeds )
906 auto pseed = std::make_unique<TrackSeed_v1>(
seed);
908 { pseed->identify(); }
916 std::cout <<
"Called Setup" << std::endl;
917 if(
Verbosity()>0) std::cout <<
"topNode:" << topNode << std::endl;
926 m_dcc = findNode::getClass<TpcDistortionCorrectionContainer>(topNode,
"TpcDistortionCorrectionContainerStatic");
928 { std::cout <<
"PHCASeeding::Setup - found static TPC distortion correction container" << std::endl; }
930 t_fill = std::make_unique<PHTimer>(
"t_fill");
931 t_seed = std::make_unique<PHTimer>(
"t_seed");
936 std::unique_ptr<PHField> field_map;
947 char *calibrationsroot = getenv(
"CALIBRATIONROOT");
950 std::string(
"/Field/Map/sphenix3dtrackingmapxyz.root");
967 if(
Verbosity()>0) std::cout <<
"Called End " << std::endl;