File indexing completed on 2025-08-06 08:18:25
0001 #include "MakeSourceLinks.h"
0002
0003 #include <trackbase/TrkrCluster.h>
0004 #include <trackbase/InttDefs.h>
0005 #include <trackbase/MvtxDefs.h>
0006 #include <trackbase/TpcDefs.h>
0007 #include <trackbase/ActsSourceLink.h>
0008 #include <trackbase/TrkrCluster.h>
0009 #include <trackbase/TrkrClusterContainer.h>
0010 #include <trackbase/ActsGeometry.h>
0011 #include <trackbase/alignmentTransformationContainer.h>
0012
0013 #include <trackbase_historic/ActsTransformations.h>
0014 #include <trackbase_historic/SvtxTrack.h>
0015 #include <trackbase_historic/SvtxTrackState.h>
0016 #include <trackbase_historic/SvtxTrackState_v2.h>
0017 #include <trackbase_historic/TrackSeed.h>
0018
0019 #include <tpc/TpcGlobalPositionWrapper.h>
0020 #include <tpc/TpcClusterZCrossingCorrection.h>
0021
0022 #include <g4detectors/PHG4TpcCylinderGeomContainer.h>
0023
0024 #include <Acts/EventData/ParticleHypothesis.hpp>
0025 #include <Acts/EventData/SourceLink.hpp>
0026
0027 #include <phool/PHTimer.h>
0028 #include <phool/phool.h>
0029
0030 namespace
0031 {
0032 template <class T>
0033 inline T square(const T& x)
0034 {
0035 return x * x;
0036 }
0037
0038 [[maybe_unused]] std::ostream& operator << (std::ostream& out, const Acts::Vector3& v )
0039 {
0040 out << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")";
0041 return out;
0042 }
0043
0044
0045 [[maybe_unused]] std::ostream& operator << (std::ostream& out, const Acts::Vector2& v )
0046 {
0047 out << "(" << v.x() << ", " << v.y() << ")";
0048 return out;
0049 }
0050
0051 }
0052
0053 void MakeSourceLinks::initialize(PHG4TpcCylinderGeomContainer* cellgeo)
0054 {
0055
0056 if (cellgeo)
0057 {
0058 _clusterMover.initialize_geometry(cellgeo);
0059 }
0060
0061 }
0062
0063
0064 SourceLinkVec MakeSourceLinks::getSourceLinks(
0065 TrackSeed* track,
0066 ActsTrackFittingAlgorithm::MeasurementContainer& measurements,
0067 TrkrClusterContainer* clusterContainer,
0068 ActsGeometry* tGeometry,
0069 const TpcGlobalPositionWrapper& globalPositionWrapper,
0070 alignmentTransformationContainer* transformMapTransient,
0071 std::set< Acts::GeometryIdentifier>& transient_id_set,
0072 short int crossing
0073 )
0074 {
0075 if(m_verbosity > 1) { std::cout << "Entering MakeSourceLinks::getSourceLinks " << std::endl; }
0076
0077 SourceLinkVec sourcelinks;
0078
0079 if (m_pp_mode && crossing == SHRT_MAX)
0080 {
0081
0082 if(m_verbosity > 1)
0083 { std::cout << "Seed has no crossing, and in pp mode: skip this seed" << std::endl; }
0084 return sourcelinks;
0085 }
0086
0087 PHTimer SLTrackTimer("SLTrackTimer");
0088 SLTrackTimer.stop();
0089 SLTrackTimer.restart();
0090
0091
0092 std::vector<TrkrDefs::cluskey> cluster_vec;
0093
0094 for (auto clusIter = track->begin_cluster_keys();
0095 clusIter != track->end_cluster_keys();
0096 ++clusIter)
0097 {
0098 auto key = *clusIter;
0099 auto cluster = clusterContainer->findCluster(key);
0100 if (!cluster)
0101 {
0102 if (m_verbosity > 0)
0103 {std::cout << "MakeSourceLinks: Failed to get cluster with key " << key << " for track seed" << std::endl;}
0104 continue;
0105 }
0106 else
0107 if(m_verbosity > 0)
0108 {std::cout << "MakeSourceLinks: Found cluster with key " << key << " for track seed " << std::endl;}
0109
0110
0111 auto surf = tGeometry->maps().getSurface(key, cluster);
0112 if (!surf)
0113 {
0114 continue;
0115 }
0116
0117 const unsigned int trkrid = TrkrDefs::getTrkrId(key);
0118 const unsigned int clus_layer = TrkrDefs::getLayer(key);
0119 if(m_verbosity > 1) { std::cout << " Cluster key " << key << " layer " << clus_layer << " trkrid " << trkrid << " crossing " << crossing << std::endl; }
0120
0121
0122
0123 if (trkrid == TrkrDefs::tpcId)
0124 {
0125 Acts::Vector3 global = globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing );
0126 Acts::Vector3 nominal_global_in = tGeometry->getGlobalPosition(key, cluster);
0127 Acts::Vector3 global_in = tGeometry->getGlobalPosition(key, cluster);
0128
0129
0130 double cluster_crossing_corrected_z= TpcClusterZCrossingCorrection::correctZ(global_in.z(), TpcDefs::getSide(key), crossing);
0131 double crossing_correction = cluster_crossing_corrected_z - global_in.z();
0132 global_in.z() = cluster_crossing_corrected_z;
0133
0134 if(m_verbosity > 2)
0135 {
0136 unsigned int this_layer = TrkrDefs::getLayer(key);
0137 unsigned int this_side = TpcDefs::getSide(key);
0138 if(this_layer == 28)
0139 {
0140 std::cout << " crossing " << crossing << " layer " << this_layer << " side " << this_side << " clusterkey " << key << std::endl
0141 << " nominal global_in " << nominal_global_in(0) << " " << nominal_global_in(1) << " " << nominal_global_in(2)
0142 << " global_in " << global_in(0) << " " << global_in(1) << " " << global_in(2)
0143 << " corr glob " << global(0) << " " << global(1) << " " << global(2) << std::endl
0144 << " distortion " << global(0)-global_in(0) << " "
0145 << global(1) - global_in(1) << " " << global(2) - global_in(2)
0146 << " cluster crossing z correction " << crossing_correction
0147 << std::endl;
0148 }
0149 }
0150
0151
0152 auto correction_translation = (global - global_in)*Acts::UnitConstants::cm;
0153 Acts::Vector3 correction_rotation(0,0,0);
0154 Acts::Transform3 tcorr = tGeometry->makeAffineTransform(correction_rotation, correction_translation);
0155
0156 auto this_surf = tGeometry->maps().getSurface(key, cluster);
0157 Acts::GeometryIdentifier id = this_surf->geometryId();
0158
0159 auto check_cluster = clusterContainer->findCluster(key);
0160 Acts::Vector2 check_local2d = tGeometry->getLocalCoords(key, check_cluster) * Acts::UnitConstants::cm;
0161 Acts::Vector3 check_local3d (check_local2d(0), check_local2d(1), 0);
0162 Acts::GeometryContext temp_transient_geocontext;
0163 temp_transient_geocontext = transformMapTransient;
0164 Acts::Vector3 check_before_pos_surf = this_surf->localToGlobal( temp_transient_geocontext,
0165 check_local2d,
0166 Acts::Vector3(1,1,1));
0167 if(m_verbosity > 2)
0168 {
0169 unsigned int this_layer = TrkrDefs::getLayer(key);
0170 if(this_layer == 28)
0171 {
0172 std::cout << "Check global from transient transform BEFORE via surface method " << check_before_pos_surf(0)/10.0 << " "
0173 << " " << check_before_pos_surf(1)/10.0 << " " << check_before_pos_surf(2)/10.0 << std::endl;
0174 }
0175 }
0176
0177
0178 auto ctxt = tGeometry->geometry().getGeoContext();
0179 alignmentTransformationContainer* transformMap = ctxt.get<alignmentTransformationContainer*>();
0180 auto corrected_transform = tcorr * transformMap->getTransform(id);
0181 transformMapTransient->replaceTransform(id, corrected_transform);
0182 transient_id_set.insert(id);
0183
0184 Acts::Vector3 check_after_pos_surf = this_surf->localToGlobal( temp_transient_geocontext,
0185 check_local2d,
0186 Acts::Vector3(1,1,1));
0187 if(m_verbosity > 2)
0188 {
0189 unsigned int this_layer = TrkrDefs::getLayer(key);
0190 if(this_layer == 28)
0191 {
0192 std::cout << "Check global from transient transform AFTER via surface method " << check_after_pos_surf(0)/10.0 << " "
0193 << " " << check_after_pos_surf(1)/10.0 << " " << check_after_pos_surf(2)/10.0 << std::endl;
0194 }
0195 }
0196 }
0197
0198
0199 cluster_vec.push_back(key);
0200
0201 }
0202
0203 Acts::GeometryContext transient_geocontext;
0204 transient_geocontext = transformMapTransient;
0205
0206
0207 for(auto& cluskey : cluster_vec)
0208 {
0209 if (m_ignoreLayer.find(TrkrDefs::getLayer(cluskey)) != m_ignoreLayer.end())
0210 {
0211 if (m_verbosity > 3)
0212 {
0213 std::cout << PHWHERE << "skipping cluster in layer "
0214 << (unsigned int) TrkrDefs::getLayer(cluskey) << std::endl;
0215 }
0216 continue;
0217 }
0218
0219
0220 auto cluster = clusterContainer->findCluster(cluskey);
0221 Acts::Vector2 localPos = tGeometry->getLocalCoords(cluskey, cluster, crossing);
0222
0223 Surface surf = tGeometry->maps().getSurface(cluskey, cluster);
0224
0225 Acts::ActsVector<2> loc;
0226 loc[Acts::eBoundLoc0] = localPos(0) * Acts::UnitConstants::cm;
0227 loc[Acts::eBoundLoc1] = localPos(1) * Acts::UnitConstants::cm;
0228
0229 std::array<Acts::BoundIndices, 2> indices =
0230 {Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc1};
0231 Acts::ActsSquareMatrix<2> cov = Acts::ActsSquareMatrix<2>::Zero();
0232
0233
0234 Acts::Vector3 global = tGeometry->getGlobalPosition(cluskey, cluster);
0235 double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]);
0236 auto para_errors = _ClusErrPara.get_clusterv5_modified_error(cluster, clusRadius, cluskey);
0237 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = para_errors.first * Acts::UnitConstants::cm2;
0238 cov(Acts::eBoundLoc0, Acts::eBoundLoc1) = 0;
0239 cov(Acts::eBoundLoc1, Acts::eBoundLoc0) = 0;
0240 cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = para_errors.second * Acts::UnitConstants::cm2;
0241
0242 ActsSourceLink::Index index = measurements.size();
0243
0244 SourceLink sl(surf->geometryId(), index, cluskey);
0245 Acts::SourceLink actsSL{sl};
0246 Acts::Measurement<Acts::BoundIndices, 2> meas(actsSL, indices, loc, cov);
0247 if (m_verbosity > 3)
0248 {
0249 unsigned int this_layer = TrkrDefs::getLayer(cluskey);
0250 if (this_layer == 28)
0251 {
0252 std::cout << "source link in layer " << this_layer << " for cluskey " << cluskey << " is " << sl.index() << ", loc : "
0253 << loc.transpose() << std::endl
0254 << ", cov : " << cov.transpose() << std::endl
0255 << " geo id " << sl.geometryId() << std::endl;
0256 std::cout << "Surface original transform: " << std::endl;
0257 surf.get()->toStream(tGeometry->geometry().getGeoContext(), std::cout);
0258 std::cout << std::endl << "Surface transient transform: " << std::endl;
0259 surf.get()->toStream(transient_geocontext, std::cout);
0260 std::cout << std::endl;
0261 std::cout << "Corrected surface transform:" << std::endl;
0262 std::cout << transformMapTransient->getTransform(surf->geometryId()).matrix() << std::endl;
0263 std::cout << "Cluster error " << cluster->getRPhiError() << " , " << cluster->getZError() << std::endl;
0264 std::cout << "For key " << cluskey << " with local pos " << std::endl
0265 << localPos(0) << ", " << localPos(1)
0266 << std::endl << std::endl;
0267 }
0268 }
0269
0270 sourcelinks.push_back(actsSL);
0271 measurements.push_back(meas);
0272 }
0273
0274 SLTrackTimer.stop();
0275 auto SLTime = SLTrackTimer.get_accumulated_time();
0276
0277 if (m_verbosity > 1)
0278 {
0279 std::cout << "PHActsTrkFitter Source Links generation time: "
0280 << SLTime << std::endl;
0281 }
0282 return sourcelinks;
0283 }
0284
0285 void MakeSourceLinks::resetTransientTransformMap(
0286 alignmentTransformationContainer* transformMapTransient,
0287 std::set< Acts::GeometryIdentifier>& transient_id_set,
0288 ActsGeometry* tGeometry )
0289 {
0290 if(m_verbosity > 2) { std::cout << "Resetting TransientTransformMap with transient_id_set size " << transient_id_set.size() << std::endl; }
0291
0292
0293 for(auto& id : transient_id_set)
0294 {
0295 auto ctxt = tGeometry->geometry().getGeoContext();
0296 alignmentTransformationContainer* transformMap = ctxt.get<alignmentTransformationContainer*>();
0297 auto transform = transformMap->getTransform(id);
0298 transformMapTransient->replaceTransform(id, transform);
0299
0300 }
0301 transient_id_set.clear();
0302 }
0303
0304
0305
0306 SourceLinkVec MakeSourceLinks::getSourceLinksClusterMover(
0307 TrackSeed* track,
0308 ActsTrackFittingAlgorithm::MeasurementContainer& measurements,
0309 TrkrClusterContainer* clusterContainer,
0310 ActsGeometry* tGeometry,
0311 const TpcGlobalPositionWrapper& globalPositionWrapper,
0312 short int crossing
0313 )
0314 {
0315 if(m_verbosity > 1) { std::cout << "Entering MakeSourceLinks::getSourceLinksClusterMover for seed "
0316 << " with crossing " << crossing
0317 << std::endl; }
0318
0319 SourceLinkVec sourcelinks;
0320
0321 if (m_pp_mode && crossing == SHRT_MAX)
0322 {
0323
0324 if(m_verbosity > 1)
0325 { std::cout << "Seed has no crossing, and in pp mode: skip this seed" << std::endl; }
0326
0327 return sourcelinks;
0328 }
0329
0330 PHTimer SLTrackTimer("SLTrackTimer");
0331 SLTrackTimer.stop();
0332 SLTrackTimer.restart();
0333
0334
0335 std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>> global_raw;
0336
0337 for (auto clusIter = track->begin_cluster_keys();
0338 clusIter != track->end_cluster_keys();
0339 ++clusIter)
0340 {
0341 auto key = *clusIter;
0342 auto cluster = clusterContainer->findCluster(key);
0343 if (!cluster)
0344 {
0345 if (m_verbosity > 0)
0346 {std::cout << "Failed to get cluster with key " << key << " for track " << track << std::endl;}
0347 else
0348 {std::cout << "PHActsTrkFitter :: Key: " << key << " for track " << track << std::endl;}
0349 continue;
0350 }
0351
0352
0353
0354 auto surf = tGeometry->maps().getSurface(key, cluster);
0355 if (!surf)
0356 {
0357 continue;
0358 }
0359
0360 const unsigned int trkrid = TrkrDefs::getTrkrId(key);
0361
0362 if(m_verbosity > 1) { std::cout << " Cluster key " << key << " trkrid " << trkrid << " crossing " << crossing << std::endl; }
0363
0364
0365
0366 const Acts::Vector3 global = globalPositionWrapper.getGlobalPositionDistortionCorrected(key, cluster, crossing );
0367
0368 if (trkrid == TrkrDefs::tpcId)
0369 {
0370 if(m_verbosity > 2)
0371 {
0372 unsigned int this_layer = TrkrDefs::getLayer(key);
0373 if(this_layer == 28)
0374 {
0375 unsigned int this_side = TpcDefs::getSide(key);
0376 Acts::Vector3 nominal_global_in = tGeometry->getGlobalPosition(key, cluster);
0377 Acts::Vector3 global_in = tGeometry->getGlobalPosition(key, cluster);
0378 double cluster_crossing_corrected_z= TpcClusterZCrossingCorrection::correctZ(global_in.z(), TpcDefs::getSide(key), crossing);
0379 double crossing_correction = cluster_crossing_corrected_z - global_in.z();
0380 global_in.z() = cluster_crossing_corrected_z;
0381
0382 std::cout << " crossing " << crossing << " layer " << this_layer << " side " << this_side << " clusterkey " << key << std::endl
0383 << " nominal global_in " << nominal_global_in(0) << " " << nominal_global_in(1) << " " << nominal_global_in(2) << std::endl
0384 << " global_in " << global_in(0) << " " << global_in(1) << " " << global_in(2) << std::endl
0385 << " corr glob " << global(0) << " " << global(1) << " " << global(2) << std::endl
0386 << " distortion " << global(0)-global_in(0) << " "
0387 << global(1) - global_in(1) << " " << global(2) - global_in(2)
0388 << " cluster crossing z correction " << crossing_correction
0389 << std::endl;
0390 }
0391 }
0392 }
0393
0394
0395 global_raw.emplace_back(std::make_pair(key, global));
0396
0397 }
0398
0399
0400 auto global_moved = _clusterMover.processTrack(global_raw);
0401
0402 if (m_verbosity > 1)
0403 {
0404 std::cout << "Cluster global positions after mover puts them on readout surface:" << std::endl;
0405 }
0406
0407
0408 for(auto&& [cluskey, global] : global_moved)
0409 {
0410 if (m_ignoreLayer.find(TrkrDefs::getLayer(cluskey)) != m_ignoreLayer.end())
0411 {
0412 if (m_verbosity > 3)
0413 {
0414 std::cout << PHWHERE << "skipping cluster in layer "
0415 << (unsigned int) TrkrDefs::getLayer(cluskey) << std::endl;
0416 }
0417 continue;
0418 }
0419
0420 auto cluster = clusterContainer->findCluster(cluskey);
0421 Surface surf = tGeometry->maps().getSurface(cluskey, cluster);
0422 if(std::isnan(global.x()) || std::isnan(global.y()))
0423 {
0424 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - invalid position"
0425 << " key: " << cluskey
0426 << " layer: " << (int)TrkrDefs::getLayer(cluskey)
0427 << " position: " << global
0428 << std::endl;
0429 }
0430
0431
0432 auto trkrid = TrkrDefs::getTrkrId(cluskey);
0433 if (trkrid == TrkrDefs::tpcId)
0434 {
0435 TrkrDefs::hitsetkey hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(cluskey);
0436 TrkrDefs::subsurfkey new_subsurfkey = 0;
0437 surf = tGeometry->get_tpc_surface_from_coords(hitsetkey, global, new_subsurfkey);
0438 }
0439
0440 if (!surf)
0441 {
0442 if(m_verbosity > 2) { std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Failed to find surface for cluskey " << cluskey << std::endl; }
0443 continue;
0444 }
0445
0446
0447 Acts::Vector2 localPos;
0448 global *= Acts::UnitConstants::cm;
0449
0450 Acts::Vector3 normal = surf->normal(tGeometry->geometry().getGeoContext(),Acts::Vector3(1,1,1), Acts::Vector3(1,1,1));
0451 auto local = surf->globalToLocal(tGeometry->geometry().getGeoContext(), global, normal);
0452
0453 if (local.ok())
0454 {
0455 localPos = local.value() / Acts::UnitConstants::cm;
0456 }
0457 else
0458 {
0459 if(m_verbosity > 2) { std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Taking manual calculation for global to local " << std::endl; }
0460
0461
0462
0463 Acts::Vector3 loct = surf->transform(tGeometry->geometry().getGeoContext()).inverse() * global ;
0464 loct /= Acts::UnitConstants::cm;
0465
0466 localPos(0) = loct(0);
0467 localPos(1) = loct(1);
0468 }
0469
0470 if (m_verbosity > 2)
0471 {
0472 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Cluster " << cluskey << " cluster global after mover: " << global << std::endl;
0473 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - stored: cluster local X " << cluster->getLocalX() << " cluster local Y " << cluster->getLocalY() << std::endl;
0474
0475 const Acts::Vector2 localTest = tGeometry->getLocalCoords(cluskey, cluster);
0476 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - localTest from getLocalCoords: " << localTest << std::endl;
0477 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - new from inverse transform of cluster global after mover: " << std::endl;
0478
0479 const Acts::Vector3 globalTest = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localTest*Acts::UnitConstants::cm, normal);
0480 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from localTest: " << Acts::Vector3(globalTest/Acts::UnitConstants::cm) << std::endl;
0481
0482 const Acts::Vector3 globalNew = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localPos*Acts::UnitConstants::cm, normal);
0483 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from new local: " << Acts::Vector3(globalNew/Acts::UnitConstants::cm) << std::endl;
0484 }
0485
0486 Acts::ActsVector<2> loc;
0487 loc[Acts::eBoundLoc0] = localPos(0) * Acts::UnitConstants::cm;
0488 loc[Acts::eBoundLoc1] = localPos(1) * Acts::UnitConstants::cm;
0489 std::array<Acts::BoundIndices, 2> indices =
0490 {Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc1};
0491
0492 Acts::ActsSquareMatrix<2> cov = Acts::ActsSquareMatrix<2>::Zero();
0493
0494 double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]);
0495 auto para_errors = _ClusErrPara.get_clusterv5_modified_error(cluster, clusRadius, cluskey);
0496 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = para_errors.first * Acts::UnitConstants::cm2;
0497 cov(Acts::eBoundLoc0, Acts::eBoundLoc1) = 0;
0498 cov(Acts::eBoundLoc1, Acts::eBoundLoc0) = 0;
0499 cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = para_errors.second * Acts::UnitConstants::cm2;
0500
0501 ActsSourceLink::Index index = measurements.size();
0502
0503 SourceLink sl(surf->geometryId(), index, cluskey);
0504 Acts::SourceLink actsSL{sl};
0505 Acts::Measurement<Acts::BoundIndices, 2> meas(actsSL, indices, loc, cov);
0506 if (m_verbosity > 3)
0507 {
0508 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - source link " << sl.index() << ", loc : "
0509 << loc.transpose() << std::endl
0510 << ", cov : " << cov.transpose() << std::endl
0511 << " geo id " << sl.geometryId() << std::endl;
0512 std::cout << "Surface : " << std::endl;
0513 surf.get()->toStream(tGeometry->geometry().getGeoContext(), std::cout);
0514 std::cout << std::endl;
0515 std::cout << "Cluster error " << cluster->getRPhiError() << " , " << cluster->getZError() << std::endl;
0516 std::cout << "For key " << cluskey << " with local pos " << std::endl
0517 << localPos(0) << ", " << localPos(1)
0518 << std::endl;
0519 }
0520
0521 sourcelinks.push_back(actsSL);
0522 measurements.push_back(meas);
0523 }
0524
0525 SLTrackTimer.stop();
0526 auto SLTime = SLTrackTimer.get_accumulated_time();
0527
0528 if (m_verbosity > 1)
0529 {
0530 std::cout << "PHMakeSourceLinks::getSourceLinksClusterMover - ActsTrkFitter Source Links generation time: "
0531 << SLTime << std::endl;
0532 }
0533 return sourcelinks;
0534 }