File indexing completed on 2025-08-06 08:18:02
0001
0002
0003
0004
0005
0006
0007 #include "TpcClusterMover.h"
0008
0009 #include <fun4all/Fun4AllReturnCodes.h>
0010 #include <trackbase/TrackFitUtils.h>
0011
0012 #include <g4detectors/PHG4TpcCylinderGeom.h>
0013 #include <g4detectors/PHG4TpcCylinderGeomContainer.h>
0014 #include <climits>
0015 #include <cmath>
0016 #include <iostream>
0017
0018 namespace
0019 {
0020 [[maybe_unused]] std::ostream& operator << (std::ostream& out, const Acts::Vector3& v )
0021 {
0022 out << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")";
0023 return out;
0024 }
0025 }
0026
0027 TpcClusterMover::TpcClusterMover()
0028 {
0029
0030 inner_tpc_spacing = (mid_tpc_min_radius - inner_tpc_min_radius) / 16.0;
0031 mid_tpc_spacing = (outer_tpc_min_radius - mid_tpc_min_radius) / 16.0;
0032 outer_tpc_spacing = (outer_tpc_max_radius - outer_tpc_min_radius) / 16.0;
0033 for (int i = 0; i < 16; ++i)
0034 {
0035 layer_radius[i] = inner_tpc_min_radius + (double) i * inner_tpc_spacing + 0.5 * inner_tpc_spacing;
0036 }
0037 for (int i = 0; i < 16; ++i)
0038 {
0039 layer_radius[i + 16] = mid_tpc_min_radius + (double) i * mid_tpc_spacing + 0.5 * mid_tpc_spacing;
0040 }
0041 for (int i = 0; i < 16; ++i)
0042 {
0043 layer_radius[i + 32] = outer_tpc_min_radius + (double) i * outer_tpc_spacing + 0.5 * outer_tpc_spacing;
0044 }
0045 }
0046
0047 void TpcClusterMover::initialize_geometry(PHG4TpcCylinderGeomContainer *cellgeo)
0048 {
0049 if (_verbosity > 0)
0050 {
0051 std::cout << "TpcClusterMover: Initializing layer radii for Tpc from cell geometry object" << std::endl;
0052 }
0053
0054 int layer = 0;
0055 PHG4TpcCylinderGeomContainer::ConstRange layerrange = cellgeo->get_begin_end();
0056 for (PHG4TpcCylinderGeomContainer::ConstIterator layeriter = layerrange.first;
0057 layeriter != layerrange.second;
0058 ++layeriter)
0059 {
0060 layer_radius[layer] = layeriter->second->get_radius();
0061 layer++;
0062 }
0063 }
0064
0065
0066 std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>> TpcClusterMover::processTrack(const std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>>& global_in)
0067 {
0068
0069
0070
0071
0072 std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>> global_moved;
0073
0074 std::vector<Acts::Vector3> tpc_global_vec;
0075 std::vector<TrkrDefs::cluskey> tpc_cluskey_vec;
0076
0077 for (const auto& [ckey,global]:global_in)
0078 {
0079 const auto trkrid = TrkrDefs::getTrkrId(ckey);
0080 if (trkrid == TrkrDefs::tpcId)
0081 {
0082 tpc_cluskey_vec.push_back(ckey);
0083 tpc_global_vec.push_back(global);
0084 }
0085 else
0086 {
0087
0088 global_moved.emplace_back(ckey,global);
0089 }
0090 }
0091
0092
0093 if (tpc_global_vec.size() < 3)
0094 {
0095 if (_verbosity > 0)
0096 {
0097 std::cout << " -- skip this tpc track, not enough clusters: " << tpc_global_vec.size() << std::endl;
0098 }
0099 return global_in;
0100 }
0101
0102
0103 const auto [R, X0, Y0] = TrackFitUtils::circle_fit_by_taubin(tpc_global_vec);
0104
0105
0106 const auto [A, B] = TrackFitUtils::line_fit(tpc_global_vec);
0107
0108
0109 for (unsigned int i = 0; i < tpc_global_vec.size(); ++i)
0110 {
0111 TrkrDefs::cluskey cluskey = tpc_cluskey_vec[i];
0112 unsigned int layer = TrkrDefs::getLayer(cluskey);
0113 Acts::Vector3 global = tpc_global_vec[i];
0114
0115
0116 double target_radius = layer_radius[layer - 7];
0117 int ret = get_circle_circle_intersection(target_radius, R, X0, Y0, global[0], global[1], _x_proj, _y_proj);
0118 if (ret == Fun4AllReturnCodes::ABORTEVENT)
0119 {
0120 continue;
0121 }
0122
0123 _z_proj = B + A * target_radius;
0124
0125
0126 double cluster_radius = sqrt(global[0] * global[0] + global[1] * global[1]);
0127 ret = get_circle_circle_intersection(cluster_radius, R, X0, Y0, global[0], global[1], _x_start, _y_start);
0128 if (ret == Fun4AllReturnCodes::ABORTEVENT)
0129 {
0130 continue;
0131 }
0132
0133 _z_start = B + A * cluster_radius;
0134
0135
0136 double xnew = global[0] - (_x_start - _x_proj);
0137 double ynew = global[1] - (_y_start - _y_proj);
0138 double znew = global[2] - (_z_start - _z_proj);
0139
0140
0141
0142
0143 Acts::Vector3 global_new(xnew, ynew, znew);
0144
0145
0146 global_moved.emplace_back(cluskey, global_new);
0147
0148 if (_verbosity > 2)
0149 {
0150 std::cout << "Cluster " << cluskey << " xstart " << _x_start << " xproj " << _x_proj << " ystart " << _y_start << " yproj " << _y_proj
0151 << " zstart " << _z_start << " zproj " << _z_proj << std::endl;
0152 std::cout << " layer " << layer << " layer radius " << target_radius << " cluster radius " << cluster_radius << std::endl;
0153 std::cout << " global in " << global[0] << " " << global[1] << " " << global[2] << std::endl;
0154 std::cout << " global new " << global_new[0] << " " << global_new[1] << " " << global_new[2] << std::endl;
0155 }
0156 }
0157
0158 return global_moved;
0159 }
0160
0161 int TpcClusterMover::get_circle_circle_intersection(double target_radius, double R, double X0, double Y0, double xclus, double yclus, double &x, double &y)
0162 {
0163
0164 const auto [xplus, yplus, xminus, yminus] = TrackFitUtils::circle_circle_intersection(target_radius, R, X0, Y0);
0165
0166
0167 if (std::isnan(xplus))
0168 {
0169 {
0170 if (_verbosity > 1)
0171 {
0172 std::cout << " circle/circle intersection calculation failed, skip this cluster" << std::endl;
0173 std::cout << " target_radius " << target_radius << " fitted R " << R << " fitted X0 " << X0 << " fitted Y0 " << Y0 << std::endl;
0174 }
0175 }
0176 return Fun4AllReturnCodes::ABORTEVENT;
0177 }
0178
0179
0180 if (fabs(xclus - xplus) < 5.0 && fabs(yclus - yplus) < 5.0)
0181 {
0182 x = xplus;
0183 y = yplus;
0184 }
0185 else
0186 {
0187 x = xminus;
0188 y = yminus;
0189 }
0190 return Fun4AllReturnCodes::EVENT_OK;
0191 }