File indexing completed on 2025-12-17 09:20:57
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/PHG4TpcGeomContainer.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(PHG4TpcGeomContainer* 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.contains(TrkrDefs::getLayer(cluskey)))
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
0411
0412 if (m_ignoreLayer.contains(TrkrDefs::getLayer(cluskey)))
0413 {
0414 if (m_verbosity > 3)
0415 {
0416 std::cout << PHWHERE << "skipping cluster in layer "
0417 << (unsigned int) TrkrDefs::getLayer(cluskey) << std::endl;
0418 }
0419 continue;
0420 }
0421
0422 auto cluster = clusterContainer->findCluster(cluskey);
0423 Surface surf = tGeometry->maps().getSurface(cluskey, cluster);
0424 if(std::isnan(global.x()) || std::isnan(global.y()))
0425 {
0426 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - invalid position"
0427 << " key: " << cluskey
0428 << " layer: " << (int)TrkrDefs::getLayer(cluskey)
0429 << " position: " << global
0430 << std::endl;
0431 }
0432
0433
0434 auto trkrid = TrkrDefs::getTrkrId(cluskey);
0435 if (trkrid == TrkrDefs::tpcId)
0436 {
0437 TrkrDefs::hitsetkey hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(cluskey);
0438 TrkrDefs::subsurfkey new_subsurfkey = 0;
0439 surf = tGeometry->get_tpc_surface_from_coords(hitsetkey, global, new_subsurfkey);
0440 }
0441
0442 if (!surf)
0443 {
0444 if(m_verbosity > 2) { std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Failed to find surface for cluskey " << cluskey << std::endl; }
0445 continue;
0446 }
0447
0448
0449 Acts::Vector2 localPos;
0450 global *= Acts::UnitConstants::cm;
0451
0452 Acts::Vector3 normal = surf->normal(tGeometry->geometry().getGeoContext(),Acts::Vector3(1,1,1), Acts::Vector3(1,1,1));
0453 auto local = surf->globalToLocal(tGeometry->geometry().getGeoContext(), global, normal);
0454
0455 if (local.ok())
0456 {
0457 localPos = local.value() / Acts::UnitConstants::cm;
0458 }
0459 else
0460 {
0461 if(m_verbosity > 2) { std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Taking manual calculation for global to local " << std::endl; }
0462
0463
0464
0465 Acts::Vector3 loct = surf->transform(tGeometry->geometry().getGeoContext()).inverse() * global ;
0466 loct /= Acts::UnitConstants::cm;
0467
0468 localPos(0) = loct(0);
0469 localPos(1) = loct(1);
0470 }
0471
0472 if (m_verbosity > 2)
0473 {
0474 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - Cluster " << cluskey << " cluster global after mover: " << global << std::endl;
0475 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - stored: cluster local X " << cluster->getLocalX() << " cluster local Y " << cluster->getLocalY() << std::endl;
0476
0477 const Acts::Vector2 localTest = tGeometry->getLocalCoords(cluskey, cluster);
0478 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - localTest from getLocalCoords: " << localTest << std::endl;
0479 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - new from inverse transform of cluster global after mover: " << std::endl;
0480
0481 const Acts::Vector3 globalTest = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localTest*Acts::UnitConstants::cm, normal);
0482 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from localTest: " << Acts::Vector3(globalTest/Acts::UnitConstants::cm) << std::endl;
0483
0484 const Acts::Vector3 globalNew = surf->localToGlobal(tGeometry->geometry().getGeoContext(), localPos*Acts::UnitConstants::cm, normal);
0485 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - global from new local: " << Acts::Vector3(globalNew/Acts::UnitConstants::cm) << std::endl;
0486 }
0487
0488 Acts::ActsVector<2> loc;
0489 loc[Acts::eBoundLoc0] = localPos(0) * Acts::UnitConstants::cm;
0490 loc[Acts::eBoundLoc1] = localPos(1) * Acts::UnitConstants::cm;
0491 std::array<Acts::BoundIndices, 2> indices =
0492 {Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc1};
0493
0494 Acts::ActsSquareMatrix<2> cov = Acts::ActsSquareMatrix<2>::Zero();
0495
0496 double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]);
0497 auto para_errors = _ClusErrPara.get_clusterv5_modified_error(cluster, clusRadius, cluskey);
0498 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = para_errors.first * Acts::UnitConstants::cm2;
0499 cov(Acts::eBoundLoc0, Acts::eBoundLoc1) = 0;
0500 cov(Acts::eBoundLoc1, Acts::eBoundLoc0) = 0;
0501 cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = para_errors.second * Acts::UnitConstants::cm2;
0502
0503 ActsSourceLink::Index index = measurements.size();
0504
0505 SourceLink sl(surf->geometryId(), index, cluskey);
0506 Acts::SourceLink actsSL{sl};
0507 Acts::Measurement<Acts::BoundIndices, 2> meas(actsSL, indices, loc, cov);
0508 if (m_verbosity > 3)
0509 {
0510 std::cout << "MakeSourceLinks::getSourceLinksClusterMover - source link " << sl.index() << ", loc : "
0511 << loc.transpose() << std::endl
0512 << ", cov : " << cov.transpose() << std::endl
0513 << " geo id " << sl.geometryId() << std::endl;
0514 std::cout << "Surface : " << std::endl;
0515 surf.get()->toStream(tGeometry->geometry().getGeoContext(), std::cout);
0516 std::cout << std::endl;
0517 std::cout << "Cluster error " << cluster->getRPhiError() << " , " << cluster->getZError() << std::endl;
0518 std::cout << "For key " << cluskey << " with local pos " << std::endl
0519 << localPos(0) << ", " << localPos(1)
0520 << std::endl;
0521 }
0522
0523 sourcelinks.push_back(actsSL);
0524 measurements.push_back(meas);
0525 }
0526
0527 SLTrackTimer.stop();
0528 auto SLTime = SLTrackTimer.get_accumulated_time();
0529
0530 if (m_verbosity > 1)
0531 {
0532 std::cout << "PHMakeSourceLinks::getSourceLinksClusterMover - ActsTrkFitter Source Links generation time: "
0533 << SLTime << std::endl;
0534 }
0535 return sourcelinks;
0536 }