Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:18:31

0001 
0002 #include "PHSiliconCosmicSeeding.h"
0003 
0004 #include <fun4all/Fun4AllReturnCodes.h>
0005 #include <phool/PHCompositeNode.h>
0006 #include <phool/PHDataNode.h>
0007 #include <phool/PHNode.h>
0008 #include <phool/PHNodeIterator.h>
0009 #include <phool/PHObject.h>
0010 #include <phool/PHTimer.h>
0011 #include <phool/getClass.h>
0012 #include <phool/phool.h>
0013 
0014 #include <trackbase/TrackFitUtils.h>
0015 #include <trackbase/TrkrCluster.h>
0016 #include <trackbase/TrkrClusterContainer.h>
0017 #include <trackbase_historic/TrackSeed.h>
0018 #include <trackbase_historic/TrackSeedContainer.h>
0019 #include <trackbase_historic/TrackSeedContainer_v1.h>
0020 #include <trackbase_historic/TrackSeed_v2.h>
0021 #include <trackbase_historic/TrackSeedHelper.h>
0022 
0023 namespace
0024 {
0025   template <class T>
0026   inline constexpr T square(const T &x)
0027   {
0028     return x * x;
0029   }
0030   template <class T>
0031   inline constexpr T r(const T &x, const T &y)
0032   {
0033     return std::sqrt(square(x) + square(y));
0034   }
0035 }  // namespace
0036 
0037 //____________________________________________________________________________..
0038 PHSiliconCosmicSeeding::PHSiliconCosmicSeeding(const std::string &name)
0039   : SubsysReco(name)
0040 {
0041 }
0042 
0043 //____________________________________________________________________________..
0044 PHSiliconCosmicSeeding::~PHSiliconCosmicSeeding() = default;
0045 
0046 //____________________________________________________________________________..
0047 int PHSiliconCosmicSeeding::Init(PHCompositeNode * /*unused*/)
0048 {
0049   return Fun4AllReturnCodes::EVENT_OK;
0050 }
0051 
0052 //____________________________________________________________________________..
0053 int PHSiliconCosmicSeeding::InitRun(PHCompositeNode *topNode)
0054 {
0055   int ret = createNodes(topNode);
0056   if (ret != Fun4AllReturnCodes::EVENT_OK)
0057   {
0058     return ret;
0059   }
0060   ret = getNodes(topNode);
0061   if (ret != Fun4AllReturnCodes::EVENT_OK)
0062   {
0063     return ret;
0064   }
0065 
0066   return Fun4AllReturnCodes::EVENT_OK;
0067 }
0068 
0069 //____________________________________________________________________________..
0070 int PHSiliconCosmicSeeding::process_event(PHCompositeNode * /*unused*/)
0071 {
0072   PHSiliconCosmicSeeding::PositionMap clusterPositions;
0073   std::set<TrkrDefs::TrkrId> detectors;
0074   detectors.insert(TrkrDefs::TrkrId::mvtxId);
0075   detectors.insert(TrkrDefs::TrkrId::inttId);
0076   for (const auto &det : detectors)
0077   {
0078     for (const auto &hitsetkey : m_clusterContainer->getHitSetKeys(det))
0079     {
0080       auto range = m_clusterContainer->getClusters(hitsetkey);
0081       for (auto citer = range.first; citer != range.second; ++citer)
0082       {
0083         const auto ckey = citer->first;
0084         const auto cluster = citer->second;
0085         const auto global = m_tGeometry->getGlobalPosition(ckey, cluster);
0086         clusterPositions.insert(std::make_pair(ckey, global));
0087       }
0088     }
0089   }
0090   if (Verbosity() > 2)
0091   {
0092     std::cout << "cluster map size is " << clusterPositions.size() << std::endl;
0093   }
0094 
0095   //! to protect against events with hot channels. Cosmics should not produce more than
0096   //! 500 clusters in the silicon
0097   if (clusterPositions.size() > 500)
0098   {
0099     return Fun4AllReturnCodes::ABORTEVENT;
0100   }
0101   auto doublets = makeDoublets(clusterPositions);
0102 
0103   if (Verbosity() > 2)
0104   {
0105     std::cout << "doublets size is " << doublets.size() << std::endl;
0106     if (doublets.size() > 0)
0107     {
0108       std::cout << "nonzero doublet size" << std::endl;
0109     }
0110   }
0111 
0112   auto longseeds = addClustersOnLine(doublets, clusterPositions);
0113 
0114   if (Verbosity() > 2)
0115   {
0116     std::cout << "longseeds size is " << longseeds.size() << std::endl;
0117   }
0118   auto finalseeds = combineSeeds(longseeds);
0119   if (Verbosity() > 2)
0120   {
0121     std::cout << "final seeds size is " << finalseeds.size() << std::endl;
0122   }
0123 
0124   pruneSeeds(finalseeds, clusterPositions);
0125   for (auto &s : finalseeds)
0126   {
0127     //! make some quality cuts on the seeds
0128     if (s.ckeys.size() < 3)
0129     {
0130       continue;
0131     }
0132     int nmaps = 0;
0133     int nintt = 0;
0134     for (auto &key : s.ckeys)
0135     {
0136       if (TrkrDefs::getTrkrId(key) == TrkrDefs::TrkrId::mvtxId)
0137       {
0138         nmaps++;
0139       }
0140       if (TrkrDefs::getTrkrId(key) == TrkrDefs::TrkrId::inttId)
0141       {
0142         nintt++;
0143       }
0144     }
0145     if (nmaps > 3 && nmaps < 9 && nintt > 2 && nintt < 7)
0146     {
0147       std::unique_ptr<TrackSeed_v2> si_seed = std::make_unique<TrackSeed_v2>();
0148       for (auto &key : s.ckeys)
0149       {
0150         si_seed->insert_cluster_key(key);
0151       }
0152       TrackSeedHelper::circleFitByTaubin(si_seed.get(), clusterPositions, 0, 7);
0153       TrackSeedHelper::lineFit(si_seed.get(), clusterPositions, 0, 7);
0154 
0155       // calculate phi and assign
0156       si_seed->set_phi(TrackSeedHelper::get_phi(si_seed.get(), clusterPositions));
0157 
0158       if (Verbosity() > 3)
0159       {
0160         si_seed->identify();
0161       }
0162       m_seedContainer->insert(si_seed.get());
0163     }
0164   }
0165 
0166   return Fun4AllReturnCodes::EVENT_OK;
0167 }
0168 
0169 void PHSiliconCosmicSeeding::pruneSeeds(SeedVector &seeds, PositionMap &clusterPositions)
0170 {
0171   SeedVector prunedSeeds;
0172   for (auto &s : seeds)
0173   {
0174     TrackFitUtils::position_vector_t xypoints;
0175     for (auto &key : s.ckeys)
0176     {
0177       auto pos = clusterPositions.find(key)->second;
0178       xypoints.push_back(std::make_pair(pos.x(), pos.y()));
0179     }
0180 
0181     auto xyLineParams = TrackFitUtils::line_fit(xypoints);
0182     float lineSlope = std::get<0>(xyLineParams);
0183     float lineIntercept = std::get<1>(xyLineParams);
0184     std::set<TrkrDefs::cluskey> newKeys;
0185     for (auto &key : s.ckeys)
0186     {
0187       auto pos = clusterPositions.find(key)->second;
0188       float distance = std::abs(lineSlope * pos.x() - pos.y() + lineIntercept) / std::sqrt(lineSlope * lineSlope + 1);
0189       if (distance < 0.5)
0190       {
0191         newKeys.insert(key);
0192       }
0193     }
0194     s.ckeys = newKeys;
0195   }
0196   return;
0197 }
0198 PHSiliconCosmicSeeding::SeedVector
0199 PHSiliconCosmicSeeding::combineSeeds(SeedVector &seeds)
0200 {
0201   SeedVector newseeds;
0202   std::vector<TrkrDefs::cluskey> overlapKeys;
0203   for (size_t i = 0; i < seeds.size(); i++)
0204   {
0205     auto &s1 = seeds[i];
0206     for (size_t j = i; j < seeds.size(); j++)
0207     {
0208       auto &s2 = seeds[j];
0209 
0210       std::set_intersection(s1.ckeys.begin(), s1.ckeys.end(),
0211                             s2.ckeys.begin(), s2.ckeys.end(), std::back_inserter(overlapKeys));
0212       if (overlapKeys.size() > 1)
0213       {
0214         if (Verbosity() > 3)
0215         {
0216           std::cout << "duplicate seeds found with " << std::endl;
0217           for (auto &key : s1.ckeys)
0218           {
0219             std::cout << key << ", ";
0220           }
0221           std::cout << std::endl;
0222           for (auto &key : s2.ckeys)
0223           {
0224             std::cout << key << ", ";
0225           }
0226           std::cout << std::endl;
0227         }
0228         //! check it isn't already in there
0229         bool found = false;
0230         for (auto &newseed : newseeds)
0231         {
0232           overlapKeys.clear();
0233           std::set_intersection(s1.ckeys.begin(), s1.ckeys.end(),
0234                                 newseed.ckeys.begin(), newseed.ckeys.end(), std::back_inserter(overlapKeys));
0235           if (overlapKeys.size() > 1)
0236           {
0237             found = true;
0238             break;
0239           }
0240         }
0241         if (found)
0242         {
0243           break;
0244         }
0245 
0246         newseeds.push_back(s1);
0247         break;
0248       }
0249       overlapKeys.clear();
0250     }
0251   }
0252   if (Verbosity() > 3)
0253   {
0254     std::cout << "final seeds " << std::endl;
0255     for (auto &s : newseeds)
0256     {
0257       for (auto &key : s.ckeys)
0258       {
0259         std::cout << key << ", ";
0260       }
0261       std::cout << std::endl;
0262     }
0263   }
0264   return newseeds;
0265 }
0266 PHSiliconCosmicSeeding::SeedVector PHSiliconCosmicSeeding::addClustersOnLine(SeedVector &doublets, PositionMap &clusterPositions)
0267 {
0268   SeedVector longseeds;
0269   for (auto doublet : doublets)
0270   {
0271     TrackFitUtils::position_vector_t xypoints;
0272     for (auto &key : doublet.ckeys)
0273     {
0274       auto pos = clusterPositions.find(key)->second;
0275       xypoints.push_back(std::make_pair(pos.x(), pos.y()));
0276     }
0277     std::vector<TrkrDefs::cluskey> newClusKeysxy;
0278     std::vector<Acts::Vector3> newClusPosxy;
0279     auto xyparams = TrackFitUtils::line_fit(xypoints);
0280     float nxyclusters = TrackFitUtils::addClustersOnLine(xyparams, true, 0.7,
0281                                                          m_tGeometry, m_clusterContainer, newClusPosxy, newClusKeysxy, 0, 7);
0282     if (nxyclusters > 1)
0283     {
0284       for (auto &newkey : newClusKeysxy)
0285       {
0286         doublet.ckeys.insert(newkey);
0287       }
0288     }
0289     if (doublet.ckeys.size() > 3 && doublet.ckeys.size() < 20)
0290     {
0291       longseeds.push_back(doublet);
0292     }
0293   }
0294 
0295   if (Verbosity() > 2)
0296   {
0297     std::cout << "num seeds " << longseeds.size() << std::endl;
0298     int i = 0;
0299     for (auto &s : longseeds)
0300     {
0301       std::cout << "seed has " << s.ckeys.size() << " clusters" << std::endl;
0302       std::cout << "seed " << i << " has keys " << std::endl;
0303       for (auto &key : s.ckeys)
0304       {
0305         std::cout << "    " << key << ", ";
0306       }
0307       std::cout << std::endl;
0308       i++;
0309     }
0310   }
0311 
0312   return longseeds;
0313 }
0314 PHSiliconCosmicSeeding::SeedVector PHSiliconCosmicSeeding::makeDoublets(PositionMap &clusterPositions)
0315 {
0316   SeedVector doublets;
0317   std::set<TrkrDefs::cluskey> keys;
0318 
0319   for (auto iter = clusterPositions.begin(); iter != clusterPositions.end(); ++iter)
0320   {
0321     auto key1 = iter->first;
0322     auto pos1 = iter->second;
0323     for (auto iter2 = iter; iter2 != clusterPositions.end(); ++iter2)
0324     {
0325       auto key2 = iter2->first;
0326       auto pos2 = iter2->second;
0327       if (key1 == key2)
0328       {
0329         continue;
0330       }
0331       float dist = (pos2 - pos1).norm();
0332       if (Verbosity() > 5)
0333       {
0334         std::cout << "checking keys " << key1 << ", " << key2 << " with dist apart " << dist << std::endl;
0335         std::cout << "positions are " << pos1.transpose() << "    ,     "
0336                   << pos2.transpose() << std::endl;
0337       }
0338       if (dist > m_maxDoubletDistance)
0339       {
0340         continue;
0341       }
0342       // skip doublets that are too close together
0343       if (dist < 0.1)
0344       {
0345         continue;
0346       }
0347       PHSiliconCosmicSeeding::seed doub;
0348       doub.xyslope = (pos2.y() - pos1.y()) / (pos2.x() - pos1.x());
0349       doub.xyintercept = pos1.y() - doub.xyslope * pos1.x();
0350       doub.rzslope = (r(pos2.x(), pos2.y()) - r(pos1.x(), pos1.y())) / (pos2.z() - pos1.z());
0351       doub.rzintercept = pos1.z() * doub.rzslope + r(pos1.x(), pos1.y());
0352 
0353       keys.insert(key1);
0354       keys.insert(key2);
0355       doub.ckeys = keys;
0356       keys.clear();
0357       doublets.push_back(doub);
0358     }
0359   }
0360   return doublets;
0361 }
0362 //____________________________________________________________________________..
0363 int PHSiliconCosmicSeeding::End(PHCompositeNode * /*unused*/)
0364 {
0365   return Fun4AllReturnCodes::EVENT_OK;
0366 }
0367 
0368 int PHSiliconCosmicSeeding::getNodes(PHCompositeNode *topNode)
0369 {
0370   m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0371   if (!m_tGeometry)
0372   {
0373     std::cout << PHWHERE << "No acts reco geometry, bailing."
0374               << std::endl;
0375     return Fun4AllReturnCodes::ABORTEVENT;
0376   }
0377   m_clusterContainer = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
0378   if (!m_clusterContainer)
0379   {
0380     std::cout << PHWHERE << "No cluster container on node tree, bailing."
0381               << std::endl;
0382     return Fun4AllReturnCodes::ABORTEVENT;
0383   }
0384   return Fun4AllReturnCodes::EVENT_OK;
0385 }
0386 
0387 int PHSiliconCosmicSeeding::createNodes(PHCompositeNode *topNode)
0388 {
0389   PHNodeIterator iter(topNode);
0390 
0391   PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0392 
0393   if (!dstNode)
0394   {
0395     std::cerr << "DST node is missing, quitting" << std::endl;
0396     throw std::runtime_error("Failed to find DST node in PHSiliconCosmicSeeding::createNodes");
0397   }
0398 
0399   PHNodeIterator dstIter(dstNode);
0400   PHCompositeNode *svtxNode = dynamic_cast<PHCompositeNode *>(dstIter.findFirst("PHCompositeNode", "SVTX"));
0401 
0402   if (!svtxNode)
0403   {
0404     svtxNode = new PHCompositeNode("SVTX");
0405     dstNode->addNode(svtxNode);
0406   }
0407 
0408   m_seedContainer = findNode::getClass<TrackSeedContainer>(topNode, m_trackMapName);
0409   if (!m_seedContainer)
0410   {
0411     m_seedContainer = new TrackSeedContainer_v1;
0412     PHIODataNode<PHObject> *trackNode =
0413         new PHIODataNode<PHObject>(m_seedContainer, m_trackMapName, "PHObject");
0414     svtxNode->addNode(trackNode);
0415   }
0416 
0417   return Fun4AllReturnCodes::EVENT_OK;
0418 }