Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 #include "TpcPolyClusterTrkrClusterConverter.h"
0002 
0003 #include "Tpc_PolyCluster.h"
0004 #include "Tpc_PolyClusterContainer.h"
0005 #include "Tpc_PolyTrack.h"
0006 #include "Tpc_PolyTrackContainer.h"
0007 #include "TpcCrossingDecision.h"
0008 #include "TpcCrossingDecisionContainer.h"
0009 
0010 #include <fun4all/Fun4AllReturnCodes.h>
0011 
0012 #include <phool/PHCompositeNode.h>
0013 #include <phool/PHIODataNode.h>
0014 #include <phool/PHNodeIterator.h>
0015 #include <phool/PHObject.h>
0016 #include <phool/getClass.h>
0017 
0018 #include <trackbase/ActsGeometry.h>
0019 #include <trackbase/ActsSurfaceMaps.h>
0020 #include <trackbase/TpcDefs.h>
0021 #include <trackbase/TrkrClusterContainer.h>
0022 #include <trackbase/TrkrClusterContainerv4.h>
0023 #include <trackbase/TrkrClusterv5.h>
0024 #include <trackbase/TrkrDefs.h>
0025 
0026 #include <tpc/TpcClusterMover.h>
0027 
0028 #include <g4detectors/PHG4TpcGeomContainer.h>
0029 
0030 #include <Acts/Definitions/Units.hpp>
0031 
0032 #include <algorithm>
0033 #include <cmath>
0034 #include <cstdint>
0035 #include <iomanip>
0036 #include <iostream>
0037 #include <limits>
0038 #include <memory>
0039 #include <utility>
0040 #include <vector>
0041 
0042 namespace
0043 {
0044   unsigned int adc_to_uint16(const double value)
0045   {
0046     if (!std::isfinite(value) || value <= 0.0) { return 0;
0047 }
0048     return static_cast<unsigned int>(std::min(value, static_cast<double>(std::numeric_limits<unsigned short>::max())));
0049   }
0050 
0051   char size_to_char(const unsigned int value)
0052   {
0053     return static_cast<char>(std::min(value, 127U));
0054   }
0055 
0056   float finite_nonnegative_or_zero(const double value)
0057   {
0058     return std::isfinite(value) && value > 0.0 ? static_cast<float>(value) : 0.0F;
0059   }
0060 }
0061 
0062 TpcPolyClusterTrkrClusterConverter::TpcPolyClusterTrkrClusterConverter(const std::string& name)
0063   : SubsysReco(name)
0064 {
0065 }
0066 
0067 TpcPolyClusterTrkrClusterConverter::~TpcPolyClusterTrkrClusterConverter() = default;
0068 
0069 int TpcPolyClusterTrkrClusterConverter::InitRun(PHCompositeNode* topNode)
0070 {
0071   if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK) { return Fun4AllReturnCodes::ABORTRUN;
0072 }
0073   if (createNodes(topNode) != Fun4AllReturnCodes::EVENT_OK) { return Fun4AllReturnCodes::ABORTRUN;
0074 }
0075   if (!initializeClusterMover(topNode)) { return Fun4AllReturnCodes::ABORTRUN;
0076 }
0077   return Fun4AllReturnCodes::EVENT_OK;
0078 }
0079 
0080 int TpcPolyClusterTrkrClusterConverter::getNodes(PHCompositeNode* topNode)
0081 {
0082   m_polyClusters = findNode::getClass<Tpc_PolyClusterContainer>(topNode, m_polyClusterNodeName);
0083   if (!m_polyClusters)
0084   {
0085     std::cerr << Name() << "::getNodes - missing " << m_polyClusterNodeName << std::endl;
0086     return Fun4AllReturnCodes::ABORTRUN;
0087   }
0088 
0089   m_polyTracks = findNode::getClass<Tpc_PolyTrackContainer>(topNode, m_polyTrackNodeName);
0090   if (!m_polyTracks)
0091   {
0092     std::cerr << Name() << "::getNodes - missing " << m_polyTrackNodeName << std::endl;
0093     return Fun4AllReturnCodes::ABORTRUN;
0094   }
0095 
0096   m_crossingDecisions = findNode::getClass<TpcCrossingDecisionContainer>(topNode, m_crossingDecisionNodeName);
0097   if (!m_crossingDecisions)
0098   {
0099     std::cerr << Name() << "::getNodes - missing " << m_crossingDecisionNodeName << std::endl;
0100     return Fun4AllReturnCodes::ABORTRUN;
0101   }
0102 
0103   m_geometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0104   if (!m_geometry)
0105   {
0106     std::cerr << Name() << "::getNodes - missing ActsGeometry" << std::endl;
0107     return Fun4AllReturnCodes::ABORTRUN;
0108   }
0109 
0110   m_tpcGeomContainer = findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
0111   if (!m_tpcGeomContainer)
0112   {
0113     std::cerr << Name() << "::getNodes - missing TPCGEOMCONTAINER" << std::endl;
0114     return Fun4AllReturnCodes::ABORTRUN;
0115   }
0116 
0117   return Fun4AllReturnCodes::EVENT_OK;
0118 }
0119 
0120 int TpcPolyClusterTrkrClusterConverter::createNodes(PHCompositeNode* topNode)
0121 {
0122   PHNodeIterator iter(topNode);
0123   PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
0124   if (!dstNode)
0125   {
0126     dstNode = new PHCompositeNode("DST");
0127     topNode->addNode(dstNode);
0128   }
0129 
0130   m_outputClusters = findNode::getClass<TrkrClusterContainer>(topNode, m_outputNodeName);
0131   if (!m_outputClusters)
0132   {
0133     m_outputClusters = new TrkrClusterContainerv4();
0134     PHIODataNode<PHObject>* node = new PHIODataNode<PHObject>(m_outputClusters, m_outputNodeName, "PHObject");
0135     dstNode->addNode(node);
0136     std::cout << Name() << "::createNodes - created " << m_outputNodeName << " node" << std::endl;
0137   }
0138 
0139   return Fun4AllReturnCodes::EVENT_OK;
0140 }
0141 
0142 void TpcPolyClusterTrkrClusterConverter::clearOutputTpcClusters()
0143 {
0144   if (!m_outputClusters) { return;
0145 }
0146 
0147   const auto hitsetkeys = m_outputClusters->getHitSetKeys(TrkrDefs::TrkrId::tpcId);
0148   for (const auto hitsetkey : hitsetkeys)
0149   {
0150     m_outputClusters->removeClusters(hitsetkey);
0151   }
0152 }
0153 
0154 void TpcPolyClusterTrkrClusterConverter::buildTrackMap()
0155 {
0156   m_tracksBySourceId.clear();
0157   if (!m_polyTracks) { return;
0158 }
0159 
0160   for (unsigned int itrack = 0; itrack < m_polyTracks->size(); ++itrack)
0161   {
0162     const Tpc_PolyTrack* track = m_polyTracks->get_track(itrack);
0163     if (!isAcceptedTrack(track)) { continue;
0164 }
0165     m_tracksBySourceId[track->get_source_assembled_track_id()] = track;
0166   }
0167 }
0168 
0169 bool TpcPolyClusterTrkrClusterConverter::isAcceptedTrack(const Tpc_PolyTrack* track) const
0170 {
0171   if (!track || !track->isValid() || track->get_fit_status() == 0) { return false;
0172 }
0173   if (track->get_nclusters() <= 20) { return false;
0174 }
0175 
0176   const double pt = std::hypot(track->get_px(), track->get_py());
0177   return std::isfinite(pt) && pt > 0.1;
0178 }
0179 
0180 bool TpcPolyClusterTrkrClusterConverter::initializeClusterMover(PHCompositeNode* topNode)
0181 {
0182   if (!m_geometry || !m_tpcGeomContainer || !topNode) { return false;
0183 }
0184 
0185   m_clusterMover = std::make_unique<TpcClusterMover>();
0186   m_clusterMover->set_verbosity(Verbosity());
0187   m_clusterMover->initialize_geometry(m_tpcGeomContainer, m_geometry, topNode);
0188   return true;
0189 }
0190 
0191 TrkrDefs::cluskey TpcPolyClusterTrkrClusterConverter::getClusterKey(const Tpc_PolyCluster* cluster) const
0192 {
0193   if (!cluster || cluster->size_hits() == 0) { return TrkrDefs::CLUSKEYMAX;
0194 }
0195 
0196   const TrkrDefs::hitsetkey hitsetkey = cluster->get_hit_index(0).first;
0197   TrkrDefs::cluskey cluskey = cluster->get_trkr_cluster_key();
0198   const bool stored_key_is_tpc = cluskey != TrkrDefs::CLUSKEYMAX &&
0199                                  static_cast<TrkrDefs::TrkrId>(TrkrDefs::getTrkrId(cluskey)) == TrkrDefs::TrkrId::tpcId &&
0200                                  TrkrDefs::getHitSetKeyFromClusKey(cluskey) == hitsetkey;
0201   if (!stored_key_is_tpc)
0202   {
0203     cluskey = TrkrDefs::genClusKey(hitsetkey, cluster->get_cluster_id());
0204   }
0205 
0206   return cluskey;
0207 }
0208 
0209 bool TpcPolyClusterTrkrClusterConverter::localFromMovedGlobal(const Tpc_PolyCluster* cluster,
0210                                                               const TrkrDefs::cluskey cluskey,
0211                                                               const std::array<double, 3>& moved_global,
0212                                                               short crossing,
0213                                                               float& local_x,
0214                                                               float& local_y,
0215                                                               unsigned short& subsurfkey,
0216                                                               unsigned long long& surface_id) const
0217 {
0218   if (!cluster || !m_geometry || cluster->size_hits() == 0) { return false;
0219 }
0220 
0221   const TrkrDefs::hitsetkey hitsetkey = cluster->get_hit_index(0).first;
0222   const Acts::Vector3 global(moved_global[0], moved_global[1], moved_global[2]);
0223   if (!std::isfinite(global.x()) || !std::isfinite(global.y()) || !std::isfinite(global.z())) { return false;
0224 }
0225 
0226   TrkrDefs::subsurfkey new_subsurfkey = 0;
0227   Surface surface = m_geometry->get_tpc_surface_from_coords(hitsetkey, global, new_subsurfkey);
0228   if (!surface)
0229   {
0230     const auto seed_iter = m_seedSubSurfKeys.find(cluskey);
0231     if (seed_iter == m_seedSubSurfKeys.end()) { return false;
0232 }
0233     new_subsurfkey = seed_iter->second;
0234     surface = m_geometry->maps().getTpcSurface(hitsetkey, new_subsurfkey);
0235   }
0236   if (!surface) { return false;
0237 }
0238   surface_id = surface->geometryId().value();
0239 
0240   const auto& geo_context = m_geometry->geometry().getGeoContext();
0241   Acts::Vector3 local = surface->localToGlobalTransform(geo_context).inverse() * (global * Acts::UnitConstants::cm);
0242   local /= Acts::UnitConstants::cm;
0243   const unsigned int side = TpcDefs::getSide(hitsetkey);
0244   const double drift_velocity = m_geometry->get_drift_velocity();
0245   if (drift_velocity <= 0.0 || !std::isfinite(drift_velocity)) { return false;
0246 }
0247 
0248   const double half_drift = 0.5 * m_geometry->get_max_driftlength();
0249   const double z_bunch_separation = m_crossingPeriodNs * drift_velocity;
0250   const double zloc_uncorrected = (side == 0) ?
0251     local.y() + static_cast<double>(crossing) * z_bunch_separation :
0252     local.y() - static_cast<double>(crossing) * z_bunch_separation;
0253   const double tuncorrected = (side == 0) ? (zloc_uncorrected + half_drift) / drift_velocity : (half_drift - zloc_uncorrected) / drift_velocity;
0254   //const double stored_t_uncorrected = tuncorrected - m_geometry->get_tpc_tzero() - m_geometry->get_sampa_tzero_bias();
0255   const double stored_t_uncorrected = (side == 0) ?
0256       tuncorrected - m_geometry->get_tpc_tzero() + 2 * m_geometry->get_sampa_tzero_bias() :
0257       tuncorrected - m_geometry->get_tpc_tzero() - m_geometry->get_sampa_tzero_bias();
0258   if (!std::isfinite(stored_t_uncorrected)) { return false;
0259   }
0260 
0261   local_x = static_cast<float>(local.x());
0262   local_y = static_cast<float>(stored_t_uncorrected);
0263   subsurfkey = new_subsurfkey;
0264   return std::isfinite(local_x) && std::isfinite(local_y);
0265 }
0266 
0267 bool TpcPolyClusterTrkrClusterConverter::seedOutputCluster(const Tpc_PolyCluster* cluster, TrkrDefs::cluskey& cluskey)
0268 {
0269   if (!cluster || !cluster->isValid() || !m_outputClusters) { return false;
0270 }
0271   if (cluster->size_hits() == 0) { return false;
0272 }
0273 
0274   const TrkrDefs::hitsetkey hitsetkey = cluster->get_hit_index(0).first;
0275   if (static_cast<TrkrDefs::TrkrId>(TrkrDefs::getTrkrId(hitsetkey)) != TrkrDefs::TrkrId::tpcId) { return false;
0276 }
0277 
0278   cluskey = getClusterKey(cluster);
0279   if (static_cast<TrkrDefs::TrkrId>(TrkrDefs::getTrkrId(cluskey)) != TrkrDefs::TrkrId::tpcId) { return false;
0280 }
0281 
0282   const Acts::Vector3 centroid(cluster->get_centroid_x(), cluster->get_centroid_y(), cluster->get_centroid_z());
0283   if (!std::isfinite(centroid.x()) || !std::isfinite(centroid.y()) || !std::isfinite(centroid.z())) { return false;
0284 }
0285 
0286   TrkrDefs::subsurfkey subsurfkey = 0;
0287   Surface surface = m_geometry->get_tpc_surface_from_coords(hitsetkey, centroid, subsurfkey);
0288   if (!surface)
0289   {
0290     subsurfkey = 0;
0291   }
0292   m_seedSubSurfKeys[cluskey] = subsurfkey;
0293 
0294   auto out = std::make_unique<TrkrClusterv5>();
0295   out->setSubSurfKey(subsurfkey);
0296   out->setLocalX(0.0F);
0297   out->setLocalY(0.0F);
0298   m_outputClusters->addClusterSpecifyKey(cluskey, out.release());
0299   return true;
0300 }
0301 
0302 void TpcPolyClusterTrkrClusterConverter::buildMovedClusterMap()
0303 {
0304   m_movedGlobals.clear();
0305   m_seedSubSurfKeys.clear();
0306   if (!m_polyClusters || !m_clusterMover) { return;
0307 }
0308 
0309   std::map<unsigned int, std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>>> clusters_by_track;
0310   for (unsigned int icluster = 0; icluster < m_polyClusters->size(); ++icluster)
0311   {
0312     const Tpc_PolyCluster* cluster = m_polyClusters->get_cluster(icluster);
0313     if (!cluster || !cluster->isValid()) { continue;
0314 }
0315 
0316     const auto track_iter = m_tracksBySourceId.find(cluster->get_source_assembled_track_id());
0317     if (track_iter == m_tracksBySourceId.end()) { continue;
0318 }
0319 
0320     TrkrDefs::cluskey cluskey = TrkrDefs::CLUSKEYMAX;
0321     if (!seedOutputCluster(cluster, cluskey)) { continue;
0322 }
0323 
0324     const Acts::Vector3 centroid(cluster->get_centroid_x(),
0325                                  cluster->get_centroid_y(),
0326                                  cluster->get_centroid_z());
0327     m_movedGlobals[cluskey] = {{centroid.x(), centroid.y(), centroid.z()}};
0328     clusters_by_track[track_iter->first].emplace_back(cluskey, centroid);
0329   }
0330 
0331   for (const auto& track_clusters : clusters_by_track)
0332   {
0333     const auto moved_globals = m_clusterMover->processTrack(track_clusters.second);
0334     for (const auto& [cluskey, moved_global] : moved_globals)
0335     {
0336       m_movedGlobals[cluskey] = {{moved_global.x(), moved_global.y(), moved_global.z()}};
0337     }
0338   }
0339 
0340   clearOutputTpcClusters();
0341 }
0342 
0343 bool TpcPolyClusterTrkrClusterConverter::publishCluster(const Tpc_PolyCluster* cluster,
0344                                                         const Tpc_PolyTrack* track) const
0345 {
0346   if (!cluster || !cluster->isValid() || !track || !m_outputClusters) { return false;
0347 }
0348   if (cluster->size_hits() == 0) { return false;
0349 }
0350 
0351   const TrkrDefs::hitsetkey hitsetkey = cluster->get_hit_index(0).first;
0352   if (static_cast<TrkrDefs::TrkrId>(TrkrDefs::getTrkrId(hitsetkey)) != TrkrDefs::TrkrId::tpcId) { return false;
0353 }
0354 
0355   const TrkrDefs::cluskey cluskey = getClusterKey(cluster);
0356   if (static_cast<TrkrDefs::TrkrId>(TrkrDefs::getTrkrId(cluskey)) != TrkrDefs::TrkrId::tpcId) { return false;
0357 }
0358 
0359   const auto moved_iter = m_movedGlobals.find(cluskey);
0360   if (moved_iter == m_movedGlobals.end()) { return false;
0361 }
0362 
0363   if (!m_crossingDecisions) { return false;
0364 }
0365   const TpcCrossingDecision* crossing_decision =
0366       m_crossingDecisions->get_decision(track->get_source_assembled_track_id());
0367   if (!crossing_decision) { return false;
0368 }
0369   const short crossing = crossing_decision->get_selected_crossing();
0370 
0371   float local_x = std::numeric_limits<float>::quiet_NaN();
0372   float local_y = std::numeric_limits<float>::quiet_NaN();
0373   unsigned short subsurfkey = 0;
0374   unsigned long long surface_id = 0;
0375   if (!localFromMovedGlobal(cluster, cluskey, moved_iter->second, crossing, local_x, local_y, subsurfkey, surface_id))
0376   {
0377     return false;
0378   }
0379 
0380   auto out = std::make_unique<TrkrClusterv5>();
0381   const unsigned int adc = adc_to_uint16(cluster->get_adc());
0382   out->setAdc(adc);
0383   out->setMaxAdc(static_cast<uint16_t>(adc));
0384   out->setEdge(0);
0385   out->setPhiSize(size_to_char(cluster->get_phi_width()));
0386   out->setZSize(size_to_char(cluster->get_time_width()));
0387   out->setSubSurfKey(subsurfkey);
0388   out->setOverlap(0);
0389   out->setLocalX(local_x);
0390   out->setLocalY(local_y);
0391   //out->setPhiError(0.002);
0392   //out->setPhiError(0.002);
0393   out->setPhiError(finite_nonnegative_or_zero(std::hypot(cluster->get_rms_x(), cluster->get_rms_y())));
0394   out->setZError(finite_nonnegative_or_zero(std::fabs(cluster->get_rms_z())));
0395 
0396   if (Verbosity() > 1)
0397   {
0398     const uint8_t sector = TpcDefs::getSectorId(hitsetkey);
0399     const uint8_t side = TpcDefs::getSide(hitsetkey);
0400     const uint8_t layer = TrkrDefs::getLayer(hitsetkey);
0401     const Acts::Vector3 trkr_global = m_geometry ? m_geometry->getGlobalPosition(cluskey, out.get()) : Acts::Vector3(
0402       std::numeric_limits<double>::quiet_NaN(),
0403       std::numeric_limits<double>::quiet_NaN(),
0404       std::numeric_limits<double>::quiet_NaN());
0405 
0406     std::cout << Name() << "::publishCluster"
0407               << " track_id=" << track->get_track_id()
0408               << " source_track=" << track->get_source_assembled_track_id()
0409               << " crossing=" << crossing
0410               << " poly_cluster=" << cluster->get_cluster_id()
0411               << " hitsetkey=0x" << std::hex << hitsetkey
0412               << " cluskey=0x" << cluskey
0413               << " surface_id=0x" << surface_id << std::dec
0414               << " sector=" << static_cast<unsigned int>(sector)
0415               << " side=" << static_cast<unsigned int>(side)
0416               << " layer=" << static_cast<unsigned int>(layer)
0417               << " poly_pos=(" << cluster->get_centroid_x()
0418               << ", " << cluster->get_centroid_y()
0419               << ", " << cluster->get_centroid_z() << ")"
0420               << " moved_global=(" << moved_iter->second[0]
0421               << ", " << moved_iter->second[1]
0422               << ", " << moved_iter->second[2] << ")"
0423               << " trkr_local=(rphi,stored_t)=(" << out->getLocalX()
0424               << ", " << out->getLocalY() << ")"
0425               << " subsurfkey=" << static_cast<unsigned int>(out->getSubSurfKey())
0426               << " adc=" << out->getAdc()
0427               << " max_adc=" << out->getMaxAdc()
0428               << " phisize=" << out->getPhiSize()
0429               << " zsize=" << out->getZSize()
0430               << " edge=" << static_cast<unsigned int>(out->getEdge())
0431               << " overlap=" << static_cast<unsigned int>(out->getOverlap())
0432               << " phi_error=" << out->getRPhiError()
0433               << " z_error=" << out->getZError()
0434               << " trkr_global=(" << trkr_global.x()
0435               << ", " << trkr_global.y()
0436               << ", " << trkr_global.z() << ")"
0437               << " dz_check=" << trkr_global.z() - moved_iter->second[2]
0438               << std::endl;
0439   }
0440 
0441   m_outputClusters->addClusterSpecifyKey(cluskey, out.release());
0442   return true;
0443 }
0444 
0445 int TpcPolyClusterTrkrClusterConverter::process_event(PHCompositeNode* topNode)
0446 {
0447   if (!m_polyClusters || !m_polyTracks || !m_outputClusters || !m_crossingDecisions || !m_geometry || !m_tpcGeomContainer || !m_clusterMover)
0448   {
0449     if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK ||
0450         createNodes(topNode) != Fun4AllReturnCodes::EVENT_OK ||
0451         !initializeClusterMover(topNode))
0452     {
0453       return Fun4AllReturnCodes::EVENT_OK;
0454     }
0455   }
0456 
0457   clearOutputTpcClusters();
0458   buildTrackMap();
0459   buildMovedClusterMap();
0460 
0461   unsigned int nconverted = 0;
0462   unsigned int nmissingTrack = 0;
0463   unsigned int nfailed = 0;
0464   for (unsigned int icluster = 0; icluster < m_polyClusters->size(); ++icluster)
0465   {
0466     const Tpc_PolyCluster* cluster = m_polyClusters->get_cluster(icluster);
0467     if (!cluster || !cluster->isValid()) { continue;
0468 }
0469 
0470     const auto track_iter = m_tracksBySourceId.find(cluster->get_source_assembled_track_id());
0471     if (track_iter == m_tracksBySourceId.end())
0472     {
0473       ++nmissingTrack;
0474       continue;
0475     }
0476 
0477     if (publishCluster(cluster, track_iter->second)) { ++nconverted;
0478     } else { ++nfailed;
0479 }
0480   }
0481 
0482   if (Verbosity() > 0)
0483   {
0484     std::cout << Name() << "::process_event - poly_clusters=" << m_polyClusters->size()
0485               << " converted=" << nconverted
0486               << " missing_track=" << nmissingTrack
0487               << " failed=" << nfailed << std::endl;
0488   }
0489 
0490   return Fun4AllReturnCodes::EVENT_OK;
0491 }