Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-08-31 08:21:25

0001 #include "TpcPolyTrackSeedConverter.h"
0002 
0003 #include "Tpc_PolyTrack.h"
0004 #include "Tpc_PolyTrackContainer.h"
0005 #include "TpcCrossingDecision.h"
0006 #include "TpcCrossingDecisionContainer.h"
0007 
0008 #include <fun4all/Fun4AllReturnCodes.h>
0009 
0010 #include <phool/PHCompositeNode.h>
0011 #include <phool/PHIODataNode.h>
0012 #include <phool/PHNodeIterator.h>
0013 #include <phool/PHObject.h>
0014 #include <phool/getClass.h>
0015 
0016 #include <trackbase/ActsGeometry.h>
0017 #include <trackbase/TpcDefs.h>
0018 #include <trackbase/TrkrDefs.h>
0019 #include <trackbase_historic/SvtxTrackSeed_v2.h>
0020 #include <trackbase_historic/TrackSeedContainer_v1.h>
0021 #include <trackbase_historic/TrackSeedHelper.h>
0022 #include <trackbase_historic/TrackSeed_v2.h>
0023 
0024 #include <cmath>
0025 #include <iostream>
0026 #include <memory>
0027 
0028 TpcPolyTrackSeedConverter::TpcPolyTrackSeedConverter(const std::string& name)
0029   : SubsysReco(name)
0030   , m_inputNodeName("TPC_POLYTRACKS")
0031   , m_outputNodeName("TpcTrackSeedContainer")
0032 {
0033 }
0034 
0035 int TpcPolyTrackSeedConverter::InitRun(PHCompositeNode* topNode)
0036 {
0037   if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK) { return Fun4AllReturnCodes::ABORTRUN;
0038 }
0039   if (createNodes(topNode) != Fun4AllReturnCodes::EVENT_OK) { return Fun4AllReturnCodes::ABORTRUN;
0040 }
0041   return Fun4AllReturnCodes::EVENT_OK;
0042 }
0043 
0044 int TpcPolyTrackSeedConverter::getNodes(PHCompositeNode* topNode)
0045 {
0046   m_polyTracks = findNode::getClass<Tpc_PolyTrackContainer>(topNode, m_inputNodeName);
0047   if (!m_polyTracks)
0048   {
0049     std::cerr << Name() << "::getNodes - missing " << m_inputNodeName << std::endl;
0050     return Fun4AllReturnCodes::ABORTRUN;
0051   }
0052 
0053   m_crossingDecisions = findNode::getClass<TpcCrossingDecisionContainer>(topNode, m_crossingDecisionNodeName);
0054   if (!m_crossingDecisions)
0055   {
0056     std::cerr << Name() << "::getNodes - missing " << m_crossingDecisionNodeName << std::endl;
0057     return Fun4AllReturnCodes::ABORTRUN;
0058   }
0059 
0060   m_geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0061   if (!m_geometry)
0062   {
0063     std::cerr << Name() << "::getNodes - missing ActsGeometry" << std::endl;
0064     return Fun4AllReturnCodes::ABORTRUN;
0065   }
0066   return Fun4AllReturnCodes::EVENT_OK;
0067 }
0068 
0069 int TpcPolyTrackSeedConverter::createNodes(PHCompositeNode* topNode)
0070 {
0071   PHNodeIterator iter(topNode);
0072   PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
0073   if (!dstNode)
0074   {
0075     dstNode = new PHCompositeNode("DST");
0076     topNode->addNode(dstNode);
0077   }
0078 
0079   PHNodeIterator dstIter(dstNode);
0080   PHCompositeNode* svtxNode = dynamic_cast<PHCompositeNode*>(dstIter.findFirst("PHCompositeNode", "SVTX"));
0081   if (!svtxNode)
0082   {
0083     svtxNode = new PHCompositeNode("SVTX");
0084     dstNode->addNode(svtxNode);
0085   }
0086 
0087   m_trackSeeds = findNode::getClass<TrackSeedContainer>(topNode, m_outputNodeName);
0088   if (!m_trackSeeds)
0089   {
0090     m_trackSeeds = new TrackSeedContainer_v1();
0091     PHIODataNode<PHObject>* node = new PHIODataNode<PHObject>(m_trackSeeds, m_outputNodeName, "PHObject");
0092     svtxNode->addNode(node);
0093     std::cout << Name() << "::createNodes - created " << m_outputNodeName << " node" << std::endl;
0094   }
0095 
0096   return Fun4AllReturnCodes::EVENT_OK;
0097 }
0098 
0099 bool TpcPolyTrackSeedConverter::isValidTrack(const Tpc_PolyTrack* track) const
0100 {
0101   if (!track || track->get_fit_status() == 0) { return false;
0102 }
0103   if (track->size_cluster_keys() == 0) { return false;
0104 }
0105   if (track->get_nclusters() != track->size_cluster_keys()) { return false;
0106 }
0107   if (track->get_nclusters() <= 20) { return false;
0108 }
0109 
0110   const double pt = std::hypot(track->get_px(), track->get_py());
0111   if (!std::isfinite(pt) || pt <= 0.1) { return false;
0112 }
0113 
0114   for (unsigned int i = 0; i < track->size_cluster_keys(); ++i)
0115   {
0116     if (track->get_cluster_key(i) == TrkrDefs::CLUSKEYMAX) { return false;
0117 }
0118   }
0119 
0120   return std::isfinite(track->get_seed_x0()) &&
0121          std::isfinite(track->get_seed_y0()) &&
0122          std::isfinite(track->get_seed_z0()) &&
0123          std::isfinite(track->get_seed_phi()) &&
0124          std::isfinite(track->get_seed_slope()) &&
0125          std::isfinite(track->get_seed_q_over_r()) &&
0126          std::fabs(track->get_seed_q_over_r()) > 0.0;
0127 }
0128 
0129 bool TpcPolyTrackSeedConverter::publishSeed(const Tpc_PolyTrack* track) const
0130 {
0131   if (!track || !m_crossingDecisions || !m_geometry || !m_trackSeeds) { return false;
0132 }
0133 
0134   const TpcCrossingDecision* crossing_decision =
0135       m_crossingDecisions->get_decision(track->get_source_assembled_track_id());
0136   if (!crossing_decision) { return false;
0137 }
0138 
0139   const short crossing = crossing_decision->get_selected_crossing();
0140   const double drift_velocity = m_geometry->get_drift_velocity();
0141   if (drift_velocity <= 0.0 || !std::isfinite(drift_velocity)) { return false;
0142 }
0143 
0144   unsigned int side = 2;
0145   for (unsigned int i = 0; i < track->size_cluster_keys(); ++i)
0146   {
0147     const TrkrDefs::cluskey cluster_key = track->get_cluster_key(i);
0148     if (TrkrDefs::getTrkrId(cluster_key) != TrkrDefs::tpcId) { continue;
0149 }
0150     side = TpcDefs::getSide(cluster_key);
0151     break;
0152   }
0153   if (side > 1) { return false;
0154 }
0155 
0156   const double z_bunch_separation = m_crossingPeriodNs * drift_velocity;
0157   const double z0_uncorrected = (side == 0) ?
0158       track->get_seed_z0() + static_cast<double>(crossing) * z_bunch_separation :
0159       track->get_seed_z0() - static_cast<double>(crossing) * z_bunch_separation;
0160   if (!std::isfinite(z0_uncorrected)) { return false;
0161 }
0162 
0163   const double q_over_r = track->get_seed_q_over_r();
0164   const double helix_radius = std::fabs(1.0 / q_over_r);
0165   const double helix_sign = q_over_r > 0.0 ? 1.0 : -1.0;
0166   const double helix_center_x = track->get_seed_x0() - helix_sign * helix_radius * std::sin(track->get_seed_phi());
0167   const double helix_center_y = track->get_seed_y0() + helix_sign * helix_radius * std::cos(track->get_seed_phi());
0168   if (!std::isfinite(helix_center_x) || !std::isfinite(helix_center_y)) { return false;
0169 }
0170 
0171   auto seed = std::make_unique<TrackSeed_v2>();
0172   seed->set_X0(static_cast<float>(helix_center_x));
0173   seed->set_Y0(static_cast<float>(helix_center_y));
0174   seed->set_Z0(static_cast<float>(z0_uncorrected));
0175   seed->set_phi(static_cast<float>(track->get_seed_phi()));
0176   seed->set_slope(static_cast<float>(track->get_seed_slope()));
0177   seed->set_qOverR(static_cast<float>(q_over_r));
0178   seed->set_crossing(crossing);
0179 
0180   for (unsigned int i = 0; i < track->size_cluster_keys(); ++i)
0181   {
0182     seed->insert_cluster_key(track->get_cluster_key(i));
0183   }
0184 
0185   const auto* converted_seed = m_trackSeeds->insert(seed.get());
0186 
0187   if (Verbosity() > 1 && converted_seed)
0188   {
0189     std::cout << Name() << "::publishSeed"
0190               << " track_id=" << track->get_track_id()
0191               << " source_track=" << track->get_source_assembled_track_id()
0192               << " crossing=" << crossing
0193               << " side=" << side
0194               << " drift_velocity=" << drift_velocity
0195               << " helix_radius=" << helix_radius
0196               << " poly_seed=(x0=" << track->get_seed_x0()
0197               << ", y0=" << track->get_seed_y0()
0198               << ", z0=" << track->get_seed_z0()
0199               << ", phi=" << track->get_seed_phi()
0200               << ", slope=" << track->get_seed_slope()
0201               << ", qOverR=" << track->get_seed_q_over_r() << ")"
0202               << " converted_seed=(x0=" << converted_seed->get_X0()
0203               << ", y0=" << converted_seed->get_Y0()
0204               << ", z0=" << converted_seed->get_Z0()
0205               << ", phi=" << converted_seed->get_phi()
0206               << ", slope=" << converted_seed->get_slope()
0207               << ", qOverR=" << converted_seed->get_qOverR() << ")"
0208               << " ncluster_keys=" << track->size_cluster_keys()
0209               << std::endl;
0210   }
0211 
0212   return converted_seed != nullptr;
0213 }
0214 
0215 int TpcPolyTrackSeedConverter::process_event(PHCompositeNode* topNode)
0216 {
0217   if (!m_polyTracks || !m_trackSeeds || !m_crossingDecisions || !m_geometry)
0218   {
0219     if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK ||
0220         createNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
0221     {
0222       return Fun4AllReturnCodes::EVENT_OK;
0223     }
0224   }
0225 
0226   m_trackSeeds->Reset();
0227 
0228   unsigned int naccepted = 0;
0229   for (unsigned int itrack = 0; itrack < m_polyTracks->size(); ++itrack)
0230   {
0231     const Tpc_PolyTrack* track = m_polyTracks->get_track(itrack);
0232     if (!isValidTrack(track)) { continue;
0233 }
0234     if (publishSeed(track)) { ++naccepted;
0235 }
0236   }
0237 
0238   if (Verbosity() > 0)
0239   {
0240     std::cout << Name() << "::process_event - poly_tracks=" << m_polyTracks->size()
0241               << " tpc_seeds=" << naccepted << std::endl;
0242   }
0243 
0244   return Fun4AllReturnCodes::EVENT_OK;
0245 }