File indexing completed on 2025-08-06 08:18:33
0001 #include "PHTpcClusterMover.h"
0002
0003
0004
0005 #include <trackbase/TrackFitUtils.h>
0006 #include <trackbase/TrkrClusterContainerv4.h>
0007 #include <trackbase/TrkrClusterv3.h> // for TrkrCluster
0008 #include <trackbase/TrkrDefs.h> // for cluskey, getLayer, TrkrId
0009 #include <trackbase_historic/ActsTransformations.h>
0010 #include <trackbase_historic/SvtxTrack.h> // for SvtxTrack, SvtxTrack::C...
0011 #include <trackbase_historic/SvtxTrackMap.h>
0012
0013 #include <g4detectors/PHG4TpcCylinderGeom.h>
0014 #include <g4detectors/PHG4TpcCylinderGeomContainer.h>
0015
0016 #include <fun4all/Fun4AllReturnCodes.h>
0017
0018 #include <phool/PHCompositeNode.h>
0019 #include <phool/getClass.h>
0020 #include <phool/phool.h>
0021
0022 #include <TF1.h>
0023
0024 #include <cmath> // for sqrt, fabs, atan2, cos
0025 #include <iostream> // for operator<<, basic_ostream
0026 #include <map> // for map
0027 #include <set> // for _Rb_tree_const_iterator
0028 #include <utility> // for pair, make_pair
0029
0030
0031 PHTpcClusterMover::PHTpcClusterMover(const std::string &name)
0032 : SubsysReco(name)
0033 {
0034 }
0035
0036
0037 int PHTpcClusterMover::InitRun(PHCompositeNode *topNode)
0038 {
0039 int ret = GetNodes(topNode);
0040 if (ret != Fun4AllReturnCodes::EVENT_OK)
0041 {
0042 return ret;
0043 }
0044 for (int layer = 7; layer < 7 + 48; layer++)
0045 {
0046 PHG4TpcCylinderGeom *GeoLayer = _tpc_geom_container->GetLayerCellGeom(layer);
0047 std::cout << "PHTpcClusterMover:: layer = " << layer << " layer_radius " << GeoLayer->get_radius() << std::endl;
0048 layer_radius[layer - 7] = GeoLayer->get_radius();
0049 }
0050
0051 return ret;
0052 }
0053
0054
0055 int PHTpcClusterMover::process_event(PHCompositeNode * )
0056 {
0057 if (Verbosity() > 0)
0058 {
0059 std::cout << PHWHERE << " track map size " << _track_map->size() << std::endl;
0060 }
0061
0062
0063 for (auto &phtrk_iter : *_track_map)
0064 {
0065 _track = phtrk_iter.second;
0066
0067 const auto crossing = _track->get_crossing();
0068 assert(crossing != SHRT_MAX);
0069
0070 if (Verbosity() >= 1)
0071 {
0072 std::cout << std::endl
0073 << __LINE__
0074 << ": Processing track itrack: " << phtrk_iter.first
0075 << ": nhits: " << _track->size_cluster_keys()
0076 << ": Total tracks: " << _track_map->size()
0077 << ": phi: " << _track->get_phi()
0078 << std::endl;
0079 }
0080
0081
0082 std::vector<Acts::Vector3> globalClusterPositions;
0083 std::map<TrkrDefs::cluskey, Acts::Vector3> tpc_clusters;
0084
0085 for (auto key_iter = _track->begin_cluster_keys(); key_iter != _track->end_cluster_keys(); ++key_iter)
0086 {
0087 const TrkrDefs::cluskey &cluster_key = *key_iter;
0088 const unsigned int trkrId = TrkrDefs::getTrkrId(cluster_key);
0089
0090
0091
0092 if (trkrId != TrkrDefs::tpcId)
0093 {
0094
0095 if (_corrected_cluster_map->findCluster(cluster_key))
0096 {
0097 continue;
0098 }
0099
0100
0101 auto cluster = _cluster_map->findCluster(cluster_key);
0102 if (!cluster)
0103 {
0104 continue;
0105 }
0106
0107
0108 auto newclus = new TrkrClusterv3;
0109 newclus->CopyFrom(cluster);
0110
0111
0112 _corrected_cluster_map->addClusterSpecifyKey(cluster_key, newclus);
0113 continue;
0114 }
0115
0116
0117 auto tpc_clus = _cluster_map->findCluster(cluster_key);
0118 const auto global = m_globalPositionWrapper.getGlobalPositionDistortionCorrected(cluster_key, tpc_clus, crossing);
0119
0120
0121 globalClusterPositions.push_back(global);
0122 tpc_clusters.insert(std::make_pair(cluster_key, global));
0123 }
0124
0125
0126 if (globalClusterPositions.size() < 3)
0127 {
0128 if (Verbosity() > 3)
0129 {
0130 std::cout << PHWHERE << " -- skip this tpc track, not enough clusters: " << globalClusterPositions.size() << std::endl;
0131 }
0132 continue;
0133 }
0134
0135
0136 const auto [R, X0, Y0] = TrackFitUtils::circle_fit_by_taubin(globalClusterPositions);
0137 if (Verbosity() > 10)
0138 {
0139 std::cout << " Fitted circle has R " << R << " X0 " << X0 << " Y0 " << Y0 << std::endl;
0140 }
0141
0142
0143
0144
0145
0146 const auto [A, B] = TrackFitUtils::line_fit(globalClusterPositions);
0147 if (Verbosity() > 10)
0148 {
0149 std::cout << " Fitted line has A " << A << " B " << B << std::endl;
0150 }
0151
0152
0153 for (const auto &[cluskey, global] : tpc_clusters)
0154 {
0155 const unsigned int layer = TrkrDefs::getLayer(cluskey);
0156
0157
0158 double target_radius = layer_radius[layer - 7];
0159 int ret = get_circle_circle_intersection(target_radius, R, X0, Y0, global[0], global[1], _x_proj, _y_proj);
0160 if (ret == Fun4AllReturnCodes::ABORTEVENT)
0161 {
0162 continue;
0163 }
0164
0165 _z_proj = B + A * target_radius;
0166
0167
0168 double cluster_radius = sqrt(global[0] * global[0] + global[1] * global[1]);
0169 ret = get_circle_circle_intersection(cluster_radius, R, X0, Y0, global[0], global[1], _x_start, _y_start);
0170 if (ret == Fun4AllReturnCodes::ABORTEVENT)
0171 {
0172 continue;
0173 }
0174
0175 _z_start = B + A * cluster_radius;
0176
0177
0178 double xnew = global[0] - (_x_start - _x_proj);
0179 double ynew = global[1] - (_y_start - _y_proj);
0180 double znew = global[2] - (_z_start - _z_proj);
0181
0182
0183
0184
0185
0186 Acts::Vector3 global_new(xnew, ynew, znew);
0187
0188 TrkrDefs::subsurfkey subsurfkey;
0189 TrkrDefs::hitsetkey tpcHitSetKey = TrkrDefs::getHitSetKeyFromClusKey(cluskey);
0190 Surface surface = _tGeometry->get_tpc_surface_from_coords(
0191 tpcHitSetKey,
0192 global_new,
0193 subsurfkey);
0194
0195 if (!surface)
0196 {
0197
0198
0199 std::cout << PHWHERE << "Failed to find surface for cluster " << cluskey << std::endl;
0200 continue;
0201 }
0202
0203
0204 TrkrCluster *cluster = _cluster_map->findCluster(cluskey);
0205
0206
0207
0208
0209 if (_corrected_cluster_map->findCluster(cluskey))
0210 {
0211 continue;
0212 }
0213
0214
0215 auto newclus = new TrkrClusterv3;
0216
0217
0218 newclus->CopyFrom(cluster);
0219
0220
0221 newclus->setSubSurfKey(subsurfkey);
0222
0223
0224 Acts::Vector3 normal = surface->normal(_tGeometry->geometry().getGeoContext(), Acts::Vector3(1,1,1),Acts::Vector3(1,1,1));
0225 auto local = surface->globalToLocal(_tGeometry->geometry().getGeoContext(),
0226 global * Acts::UnitConstants::cm,
0227 normal);
0228
0229 Acts::Vector2 localPos;
0230 if (local.ok())
0231 {
0232 localPos = local.value() / Acts::UnitConstants::cm;
0233 }
0234 else
0235 {
0236
0237 Acts::Vector3 center = surface->center(_tGeometry->geometry().getGeoContext()) / Acts::UnitConstants::cm;
0238 double clusRadius = sqrt(xnew * xnew + ynew * ynew);
0239 double clusphi = atan2(ynew, xnew);
0240 double rClusPhi = clusRadius * clusphi;
0241 double surfRadius = sqrt(center(0) * center(0) + center(1) * center(1));
0242 double surfPhiCenter = atan2(center[1], center[0]);
0243 double surfRphiCenter = surfPhiCenter * surfRadius;
0244 double surfZCenter = center[2];
0245
0246 localPos(0) = rClusPhi - surfRphiCenter;
0247 localPos(1) = znew - surfZCenter;
0248 }
0249
0250 if (Verbosity() > 4)
0251 {
0252 std::cout << "*** cluster_radius " << cluster_radius << " cluster x,y,z: " << global[0] << " " << global[1] << " " << global[2] << std::endl;
0253 std::cout << " projection_radius " << target_radius << " proj x,y,z: " << _x_proj << " " << _y_proj << " " << _z_proj << std::endl;
0254 std::cout << " traj_start_radius " << cluster_radius << " start x,y,z: " << _x_start << " " << _y_start << " " << _z_start << std::endl;
0255 std::cout << " moved_clus_radius " << target_radius << " final x,y,z: " << xnew << " " << ynew << " " << znew << std::endl;
0256 }
0257
0258
0259 newclus->setLocalX(localPos(0));
0260 newclus->setLocalY(localPos(1));
0261
0262
0263 _corrected_cluster_map->addClusterSpecifyKey(cluskey, newclus);
0264 }
0265
0266
0267 }
0268
0269 return Fun4AllReturnCodes::EVENT_OK;
0270 }
0271
0272 int PHTpcClusterMover::End(PHCompositeNode * )
0273 {
0274 return Fun4AllReturnCodes::EVENT_OK;
0275 }
0276
0277 int PHTpcClusterMover::GetNodes(PHCompositeNode *topNode)
0278 {
0279
0280 _tpc_geom_container = findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
0281 if (!_tpc_geom_container)
0282 {
0283 std::cout << PHWHERE << " ERROR: Can't find node CYLINDERCELLGEOM_SVTX" << std::endl;
0284 return Fun4AllReturnCodes::ABORTEVENT;
0285 }
0286
0287
0288 _cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
0289 if (!_cluster_map)
0290 {
0291 std::cout << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << std::endl;
0292 return Fun4AllReturnCodes::ABORTEVENT;
0293 }
0294
0295
0296 _track_map = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
0297 if (!_track_map)
0298 {
0299 std::cout << PHWHERE << " ERROR: Can't find SvtxTrackMap: " << std::endl;
0300 return Fun4AllReturnCodes::ABORTEVENT;
0301 }
0302
0303
0304 _tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0305 if (!_tGeometry)
0306 {
0307 std::cout << PHWHERE << "Error, can't find acts tracking geometry" << std::endl;
0308 return Fun4AllReturnCodes::ABORTEVENT;
0309 }
0310
0311
0312 m_globalPositionWrapper.loadNodes(topNode);
0313
0314
0315 _corrected_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "CORRECTED_TRKR_CLUSTER");
0316 if (!_corrected_cluster_map)
0317 {
0318 std::cout << "Creating node CORRECTED_TRKR_CLUSTER" << std::endl;
0319
0320 PHNodeIterator iter(topNode);
0321
0322
0323 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0324 if (!dstNode)
0325 {
0326 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
0327 return Fun4AllReturnCodes::ABORTRUN;
0328 }
0329 PHNodeIterator dstiter(dstNode);
0330 PHCompositeNode *DetNode =
0331 dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0332 if (!DetNode)
0333 {
0334 DetNode = new PHCompositeNode("TRKR");
0335 dstNode->addNode(DetNode);
0336 }
0337
0338 _corrected_cluster_map = new TrkrClusterContainerv4;
0339 PHIODataNode<PHObject> *TrkrClusterContainerNode =
0340 new PHIODataNode<PHObject>(_corrected_cluster_map, "CORRECTED_TRKR_CLUSTER", "PHObject");
0341 DetNode->addNode(TrkrClusterContainerNode);
0342 }
0343 else
0344 {
0345 _corrected_cluster_map->Reset();
0346 }
0347
0348 return Fun4AllReturnCodes::EVENT_OK;
0349 }
0350
0351 int PHTpcClusterMover::get_circle_circle_intersection(double target_radius, double R, double X0, double Y0, double xclus, double yclus, double &x, double &y)
0352 {
0353
0354 const auto [xplus, yplus, xminus, yminus] = TrackFitUtils::circle_circle_intersection(target_radius, R, X0, Y0);
0355
0356
0357 if (std::isnan(xplus))
0358 {
0359 if (Verbosity() > 0)
0360 {
0361 std::cout << " circle/circle intersection calculation failed, skip this cluster" << std::endl;
0362 std::cout << " target_radius " << target_radius << " fitted R " << R << " fitted X0 " << X0 << " fitted Y0 " << Y0 << std::endl;
0363 }
0364 return Fun4AllReturnCodes::ABORTEVENT;
0365 }
0366
0367
0368 if (fabs(xclus - xplus) < 5.0 && fabs(yclus - yplus) < 5.0)
0369 {
0370 x = xplus;
0371 y = yplus;
0372 }
0373 else
0374 {
0375 x = xminus;
0376 y = yminus;
0377 }
0378 return Fun4AllReturnCodes::EVENT_OK;
0379 }