Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHActsKDTreeSeeding.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHActsKDTreeSeeding.cc
1 
2 #include "PHActsKDTreeSeeding.h"
3 
5 
7 #include <phool/PHDataNode.h>
8 #include <phool/PHNode.h>
9 #include <phool/PHNodeIterator.h>
10 #include <phool/PHObject.h>
11 #include <phool/PHTimer.h>
12 #include <phool/getClass.h>
13 #include <phool/phool.h>
14 
19 
20 #include <intt/CylinderGeomIntt.h>
21 
24 
26 #include <trackbase/InttDefs.h>
27 #include <trackbase/MvtxDefs.h>
29 #include <trackbase/TrkrCluster.h>
32 #include <trackbase/TrkrDefs.h>
33 
35 #include <Acts/Seeding/Seed.hpp>
42 
43 #include <optional>
44 
45 namespace
46 {
47  template <class T>
48  inline constexpr T square(const T& x)
49  {
50  return x * x;
51  }
52 } // namespace
53 
54 //____________________________________________________________________________..
56  : SubsysReco(name)
57 {
58 }
59 
60 //____________________________________________________________________________..
62 {
63 }
64 
65 //____________________________________________________________________________..
67 {
69 }
70 
71 //____________________________________________________________________________..
73 {
74  int ret = getNodes(topNode);
76  return ret;
77  ret = createNodes(topNode);
79  return ret;
80 
82 
83  auto beginend = m_geomContainerIntt->get_begin_end();
84  int i = 0;
85  for (auto iter = beginend.first; iter != beginend.second; ++iter)
86  {
87  m_nInttLayerRadii[i] = iter->second->get_radius();
88  i++;
89  }
90 
92 }
93 
94 //____________________________________________________________________________..
96 {
97  if (m_nIteration > 0)
98  {
99  m_iterationMap = findNode::getClass<TrkrClusterIterationMapv1>(topNode, "CLUSTER_ITERATION_MAP");
100  if (!m_iterationMap)
101  {
102  std::cerr << PHWHERE << "Cluster Iteration Map missing, aborting." << std::endl;
104  }
105  }
106 
107  auto seeds = runSeeder();
108 
109  fillTrackSeedContainer(seeds);
110 
112 }
113 
115 {
117 
118  auto spacePoints = getMvtxSpacePoints();
119 
120  std::function<std::pair<Acts::Vector3, Acts::Vector2>(
121  const SpacePoint* sp)>
122  create_coordinates = [](const SpacePoint* sp)
123  {
124  Acts::Vector3 position(sp->x(), sp->y(), sp->z());
125  Acts::Vector2 variance(sp->varianceR(), sp->varianceZ());
126  return std::make_pair(position, variance);
127  };
128 
131  spacePoints, create_coordinates);
132  if (Verbosity() > 1)
133  {
134  std::cout << "Acts::OrthogonalSeeder found " << seeds.size()
135  << " seeds " << std::endl;
136  }
137 
138  return seeds;
139 }
140 
142 {
143  for (auto& seed : seeds)
144  {
145  auto siseed = std::make_unique<TrackSeed_v1>();
146  std::map<TrkrDefs::cluskey, Acts::Vector3> positions;
147 
148  for (auto& spptr : seed.sp())
149  {
150  auto ckey = spptr->Id();
151  siseed->insert_cluster_key(ckey);
152  auto globalPosition = m_tGeometry->getGlobalPosition(
153  ckey,
154  m_clusterMap->findCluster(ckey));
155  positions.insert(std::make_pair(ckey, globalPosition));
156  }
157 
158  siseed->circleFitByTaubin(positions, 0, 8);
159  siseed->lineFit(positions, 0, 8);
160 
162  findInttMatches(positions, *siseed);
163 
164  for (const auto& [key, pos] : positions)
165  {
167  {
168  siseed->insert_cluster_key(key);
169  }
170  }
171 
173  siseed->set_Z0(seed.z() / Acts::UnitConstants::cm);
174  if (Verbosity() > 2)
175  {
176  std::cout << "Found seed" << std::endl;
177  siseed->identify();
178  }
179 
180  m_seedContainer->insert(siseed.get());
181  }
182 }
183 
185  std::map<TrkrDefs::cluskey, Acts::Vector3>& clusters,
186  TrackSeed& seed)
187 {
188  const float R = fabs(1. / seed.get_qOverR());
189  const float X0 = seed.get_X0();
190  const float Y0 = seed.get_Y0();
191  const float B = seed.get_Z0();
192  const float m = seed.get_slope();
193 
194  double xProj[m_nInttLayers];
195  double yProj[m_nInttLayers];
196  double zProj[m_nInttLayers];
197 
199  for (int layer = 0; layer < m_nInttLayers; ++layer)
200  {
203  R, X0, Y0);
204  double xplus = std::get<0>(cci);
205  double yplus = std::get<1>(cci);
206  double xminus = std::get<2>(cci);
207  double yminus = std::get<3>(cci);
208 
210  if (std::isnan(xplus))
211  {
212  if (Verbosity() > 2)
213  {
214  std::cout << "Circle intersection calc failed, skipping"
215  << std::endl;
216  std::cout << "layer radius " << m_nInttLayerRadii[layer]
217  << " and circ rad " << R << " with center " << X0
218  << ", " << Y0 << std::endl;
219  }
220 
221  continue;
222  }
223 
226  Acts::Vector3 lastclusglob = Acts::Vector3::Zero();
227  for (const auto& [key, pos] : clusters)
228  {
229  float lastclusglobr = sqrt(square(lastclusglob(0)) + square(lastclusglob(1)));
230  float thisr = sqrt(square(pos(0)) + square(pos(1)));
231  if (thisr > lastclusglobr) lastclusglob = pos;
232  }
233 
234  const double lastClusPhi = atan2(lastclusglob(1), lastclusglob(0));
235  const double plusPhi = atan2(yplus, xplus);
236  const double minusPhi = atan2(yminus, xminus);
237 
238  if (fabs(lastClusPhi - plusPhi) < fabs(lastClusPhi - minusPhi))
239  {
240  xProj[layer] = xplus;
241  yProj[layer] = yplus;
242  }
243  else
244  {
245  xProj[layer] = xminus;
246  yProj[layer] = yminus;
247  }
248 
249  zProj[layer] = m * m_nInttLayerRadii[layer] + B;
250 
251  if (Verbosity() > 2)
252  {
253  std::cout << "Projected point is : " << xProj[layer] << ", "
254  << yProj[layer] << ", " << zProj[layer] << std::endl;
255  }
256  }
257 
258  matchInttClusters(clusters, xProj, yProj, zProj);
259 }
260 
262  std::map<TrkrDefs::cluskey, Acts::Vector3>& clusters,
263  const double xProj[],
264  const double yProj[],
265  const double zProj[])
266 {
267  for (int inttlayer = 0; inttlayer < m_nInttLayers; inttlayer++)
268  {
269  const double projR = std::sqrt(square(xProj[inttlayer]) + square(yProj[inttlayer]));
270  const double projPhi = std::atan2(yProj[inttlayer], xProj[inttlayer]);
271  const double projRphi = projR * projPhi;
272 
273  for (const auto& hitsetkey : m_clusterMap->getHitSetKeys(TrkrDefs::TrkrId::inttId, inttlayer + 3))
274  {
275  double ladderLocation[3] = {0., 0., 0.};
276 
277  // Add three to skip the mvtx layers for comparison
278  // to projections
279  auto layerGeom = dynamic_cast<CylinderGeomIntt*>(m_geomContainerIntt->GetLayerGeom(inttlayer + 3));
280 
282  layerGeom->find_segment_center(surf, m_tGeometry, ladderLocation);
283 
284  const double ladderphi = atan2(ladderLocation[1], ladderLocation[0]) + layerGeom->get_strip_phi_tilt();
285  const auto stripZSpacing = layerGeom->get_strip_z_spacing();
286  float dphi = ladderphi - projPhi;
287  if (dphi > M_PI)
288  {
289  dphi -= 2. * M_PI;
290  }
291  else if (dphi < -1 * M_PI)
292  {
293  dphi += 2. * M_PI;
294  }
295 
299  if (fabs(dphi) > 0.2)
300  {
301  continue;
302  }
303 
304  TVector3 projectionLocal(0, 0, 0);
305  TVector3 projectionGlobal(xProj[inttlayer], yProj[inttlayer], zProj[inttlayer]);
306 
307  projectionLocal = layerGeom->get_local_from_world_coords(surf,
308  m_tGeometry,
309  projectionGlobal);
310 
311  auto range = m_clusterMap->getClusters(hitsetkey);
312  for (auto clusIter = range.first; clusIter != range.second; ++clusIter)
313  {
314  const auto cluskey = clusIter->first;
315  const auto cluster = clusIter->second;
316 
319  if (fabs(projectionLocal[1] - cluster->getLocalX()) < m_rPhiSearchWin and
320  fabs(projectionLocal[2] - cluster->getLocalY()) < stripZSpacing / 2.)
321  {
323  const auto globalPos = m_tGeometry->getGlobalPosition(
324  cluskey, cluster);
325  clusters.insert(std::make_pair(cluskey, globalPos));
326 
327  if (Verbosity() > 4)
328  {
329  std::cout << "Matched INTT cluster with cluskey " << cluskey
330  << " and position " << globalPos.transpose()
331  << std::endl
332  << " with projections rphi "
333  << projRphi << " and inttclus rphi " << cluster->getLocalX()
334  << " and proj z " << zProj[inttlayer] << " and inttclus z "
335  << cluster->getLocalY() << " in layer " << inttlayer
336  << " with search windows " << m_rPhiSearchWin
337  << " in rphi and strip z spacing " << stripZSpacing
338  << std::endl;
339  }
340  }
341  }
342  }
343  }
344 }
345 
346 std::vector<const SpacePoint*> PHActsKDTreeSeeding::getMvtxSpacePoints()
347 {
348  std::vector<const SpacePoint*> spVec;
349  unsigned int numSiliconHits = 0;
350 
352  {
353  auto range = m_clusterMap->getClusters(hitsetkey);
354  for (auto clusIter = range.first; clusIter != range.second; ++clusIter)
355  {
356  const auto cluskey = clusIter->first;
357  const auto cluster = clusIter->second;
358  if (m_iterationMap != NULL && m_nIteration > 0)
359  {
361  {
362  continue;
363  }
364  }
365 
368  if (!surface)
369  {
370  continue;
371  }
372 
373  auto sp = makeSpacePoint(surface, cluskey, cluster).release();
374  spVec.push_back(sp);
375  numSiliconHits++;
376  }
377  }
378 
379  if (Verbosity() > 1)
380  {
381  std::cout << "Total number of silicon hits to seed find with is "
382  << numSiliconHits << std::endl;
383  }
384 
385  return spVec;
386 }
387 
389  const TrkrDefs::cluskey key,
390  TrkrCluster* clus)
391 {
394  Acts::Vector3 globalPos(0, 0, 0);
395  Acts::Vector3 mom(1, 1, 1);
396  globalPos = surf->localToGlobal(m_tGeometry->geometry().getGeoContext(),
397  localPos, mom);
398 
399  Acts::SquareMatrix2 localCov = Acts::SquareMatrix2::Zero();
400 
401  localCov(0, 0) = clus->getActsLocalError(0, 0) * Acts::UnitConstants::cm2;
402  localCov(1, 1) = clus->getActsLocalError(1, 1) * Acts::UnitConstants::cm2;
403 
404  float x = globalPos.x();
405  float y = globalPos.y();
406  float z = globalPos.z();
407  float r = std::sqrt(x * x + y * y);
408 
419 
420  Acts::RotationMatrix3 rotLocalToGlobal =
421  surf->referenceFrame(m_tGeometry->geometry().getGeoContext(), globalPos, mom);
422  auto scale = 2 / std::hypot(x, y);
424  jacXyzToRhoZ(0, Acts::ePos0) = scale * x;
425  jacXyzToRhoZ(0, Acts::ePos1) = scale * y;
426  jacXyzToRhoZ(1, Acts::ePos2) = 1;
427  // compute Jacobian from local coordinates to rho/z
429  jacXyzToRhoZ *
430  rotLocalToGlobal.block<3, 2>(Acts::ePos0, Acts::ePos0);
431  // compute rho/z variance
432  Acts::ActsVector<2> var = (jac * localCov * jac.transpose()).diagonal();
433 
434  /*
435  * From Acts v17 to v19 the scattering uncertainty value allowed was changed.
436  * This led to a decrease in efficiency. To offset this, we scale the
437  * uncertainties by a tuned factor that gives the v17 performance
438  * Track reconstruction is an art as much as it is a science...
439  */
440  SpacePointPtr spPtr(new SpacePoint{key, x, y, z, r, surf->geometryId(), var[0] * m_uncfactor, var[1] * m_uncfactor});
441 
442  if (Verbosity() > 2)
443  {
444  std::cout << "Space point has "
445  << x << ", " << y << ", " << z << " with local coords "
446  << localPos.transpose()
447  << " with rphi/z variances " << localCov(0, 0)
448  << ", " << localCov(1, 1) << " and rotated variances "
449  << var[0] << ", " << var[1]
450  << " and cluster key "
451  << key << " and geo id "
452  << surf->geometryId() << std::endl;
453  }
454 
455  return spPtr;
456 }
457 
458 //____________________________________________________________________________..
460 {
462 }
463 
465 {
466  m_geomContainerIntt = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
467  if (!m_geomContainerIntt)
468  {
469  std::cout << PHWHERE << "CYLINDERGEOM_INTT node not found on node tree"
470  << std::endl;
472  }
473 
474  m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
475  if (!m_tGeometry)
476  {
477  std::cout << PHWHERE << "No ActsGeometry on node tree. Bailing."
478  << std::endl;
480  }
481 
482  if (m_useTruthClusters)
483  m_clusterMap = findNode::getClass<TrkrClusterContainer>(topNode,
484  "TRKR_CLUSTER_TRUTH");
485  else
486  m_clusterMap = findNode::getClass<TrkrClusterContainer>(topNode,
487  "TRKR_CLUSTER");
488 
489  if (!m_clusterMap)
490  {
491  std::cout << PHWHERE << "No cluster container on the node tree. Bailing."
492  << std::endl;
494  }
495 
497 }
498 
500 {
501  PHNodeIterator iter(topNode);
502 
503  PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
504 
505  if (!dstNode)
506  {
507  std::cerr << "DST node is missing, quitting" << std::endl;
508  throw std::runtime_error("Failed to find DST node in PHActsKDTreeSeeding::createNodes");
509  }
510 
511  PHNodeIterator dstIter(dstNode);
512  PHCompositeNode* svtxNode = dynamic_cast<PHCompositeNode*>(dstIter.findFirst("PHCompositeNode", "SVTX"));
513 
514  if (!svtxNode)
515  {
516  svtxNode = new PHCompositeNode("SVTX");
517  dstNode->addNode(svtxNode);
518  }
519 
520  m_seedContainer = findNode::getClass<TrackSeedContainer>(topNode, m_trackMapName);
521  if (!m_seedContainer)
522  {
524  PHIODataNode<PHObject>* trackNode =
526  svtxNode->addNode(trackNode);
527  }
528 
530 }
531 
533 {
534  Acts::SeedFilterConfig filterCfg;
535  filterCfg.maxSeedsPerSpM = m_maxSeedsPerSpM;
536 
537  m_seedFinderConfig.seedFilter =
538  std::make_unique<Acts::SeedFilter<SpacePoint>>(
539  Acts::SeedFilter<SpacePoint>(filterCfg));
540 
541  m_seedFinderConfig.rMax = m_rMax;
542  m_seedFinderConfig.deltaRMinTopSP = m_deltaRMinTopSP;
543  m_seedFinderConfig.deltaRMaxTopSP = m_deltaRMaxTopSP;
544  m_seedFinderConfig.deltaRMinBottomSP = m_deltaRMinBottomSP;
545  m_seedFinderConfig.deltaRMaxBottomSP = m_deltaRMaxBottomSP;
546  m_seedFinderConfig.collisionRegionMin = m_collisionRegionMin;
547  m_seedFinderConfig.collisionRegionMax = m_collisionRegionMax;
548  m_seedFinderConfig.zMin = m_zMin;
549  m_seedFinderConfig.zMax = m_zMax;
550  m_seedFinderConfig.maxSeedsPerSpM = m_maxSeedsPerSpM;
551  m_seedFinderConfig.cotThetaMax = m_cotThetaMax;
552  m_seedFinderConfig.sigmaScattering = m_sigmaScattering;
553  m_seedFinderConfig.radLengthPerSeed = m_radLengthPerSeed;
554  m_seedFinderConfig.minPt = m_minPt;
558  m_seedFinderConfig.impactMax = m_impactMax;
559  m_seedFinderConfig.rMinMiddle = m_rMinMiddle;
560  m_seedFinderConfig.rMaxMiddle = m_rMaxMiddle;
561 
563  m_seedFinderConfig.toInternalUnits().calculateDerivedQuantities();
566 }