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 }
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 * )
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 * )
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
0096
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
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
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
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
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 * )
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 }