File indexing completed on 2025-08-06 08:18:29
0001 #include "PHCosmicsTrkFitter.h"
0002 #include "MakeSourceLinks.h"
0003
0004
0005 #include <trackbase/Calibrator.h>
0006 #include <trackbase/ClusterErrorPara.h>
0007 #include <trackbase/InttDefs.h>
0008 #include <trackbase/MvtxDefs.h>
0009 #include <trackbase/TpcDefs.h>
0010 #include <trackbase/TrackFitUtils.h>
0011 #include <trackbase/TrkrCluster.h>
0012 #include <trackbase/TrkrClusterContainer.h>
0013
0014 #include <trackbase_historic/ActsTransformations.h>
0015 #include <trackbase_historic/SvtxAlignmentStateMap_v1.h>
0016 #include <trackbase_historic/SvtxTrackMap_v2.h>
0017 #include <trackbase_historic/SvtxTrackState_v1.h>
0018 #include <trackbase_historic/SvtxTrack_v4.h>
0019 #include <trackbase_historic/TrackSeed.h>
0020 #include <trackbase_historic/TrackSeedContainer.h>
0021 #include <trackbase_historic/TrackSeedHelper.h>
0022
0023 #include <g4detectors/PHG4TpcCylinderGeomContainer.h>
0024
0025 #include <micromegas/MicromegasDefs.h>
0026
0027 #include <fun4all/Fun4AllReturnCodes.h>
0028 #include <phool/PHCompositeNode.h>
0029 #include <phool/PHDataNode.h>
0030 #include <phool/PHNode.h>
0031 #include <phool/PHNodeIterator.h>
0032 #include <phool/PHObject.h>
0033 #include <phool/PHTimer.h>
0034 #include <phool/getClass.h>
0035 #include <phool/phool.h>
0036
0037 #include <tpc/TpcDistortionCorrectionContainer.h>
0038
0039 #include <Acts/EventData/MultiTrajectory.hpp>
0040 #include <Acts/EventData/MultiTrajectoryHelpers.hpp>
0041 #include <Acts/EventData/TrackParameters.hpp>
0042 #include <Acts/Surfaces/PerigeeSurface.hpp>
0043 #include <Acts/Surfaces/PlaneSurface.hpp>
0044 #include <Acts/Surfaces/Surface.hpp>
0045 #include <Acts/TrackFitting/GainMatrixSmoother.hpp>
0046 #include <Acts/TrackFitting/GainMatrixUpdater.hpp>
0047
0048 #include <TTree.h>
0049 #include <TFile.h>
0050 #include <TVector3.h>
0051
0052 #include <cmath>
0053 #include <iostream>
0054 #include <vector>
0055
0056 namespace
0057 {
0058
0059 inline bool is_valid(const Acts::Vector3& vec)
0060 {
0061 return !(std::isnan(vec.x()) || std::isnan(vec.y()) || std::isnan(vec.z()));
0062 }
0063 template <class T>
0064 inline T square(const T& x)
0065 {
0066 return x * x;
0067 }
0068
0069
0070 template <class T>
0071 T radius(const T& x, const T& y)
0072 {
0073 return std::sqrt(square(x) + square(y));
0074 }
0075
0076 }
0077
0078 #include <trackbase/alignmentTransformationContainer.h>
0079 #include <Eigen/Dense>
0080 #include <Eigen/Geometry>
0081
0082 PHCosmicsTrkFitter::PHCosmicsTrkFitter(const std::string& name)
0083 : SubsysReco(name)
0084 , m_trajectories(nullptr)
0085 {
0086 }
0087
0088 int PHCosmicsTrkFitter::InitRun(PHCompositeNode* topNode)
0089 {
0090 if (Verbosity() > 1)
0091 {
0092 std::cout << "Setup PHCosmicsTrkFitter" << std::endl;
0093 }
0094
0095 if (createNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
0096 {
0097 return Fun4AllReturnCodes::ABORTEVENT;
0098 }
0099
0100 if (getNodes(topNode) != Fun4AllReturnCodes::EVENT_OK)
0101 {
0102 return Fun4AllReturnCodes::ABORTEVENT;
0103 }
0104
0105
0106 m_alignStates.loadNodes(topNode);
0107 m_alignStates.verbosity(Verbosity());
0108 m_alignStates.fieldMap(m_fieldMap);
0109
0110
0111 std::istringstream stringline(m_fieldMap);
0112 stringline >> fieldstrength;
0113 if (!stringline.fail())
0114 {
0115 m_ConstField = true;
0116 }
0117
0118 m_fitCfg.fit = ActsTrackFittingAlgorithm::makeKalmanFitterFunction(
0119 m_tGeometry->geometry().tGeometry,
0120 m_tGeometry->geometry().magField);
0121
0122 m_outlierFinder.verbosity = Verbosity();
0123 std::map<long unsigned int, float> chi2Cuts;
0124 chi2Cuts.insert(std::make_pair(10, 4));
0125 chi2Cuts.insert(std::make_pair(12, 4));
0126 chi2Cuts.insert(std::make_pair(14, 9));
0127 chi2Cuts.insert(std::make_pair(16, 4));
0128 m_outlierFinder.chi2Cuts = chi2Cuts;
0129 if (m_useOutlierFinder)
0130 {
0131 m_fitCfg.fit->outlierFinder(m_outlierFinder);
0132 }
0133
0134 _tpccellgeo = findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
0135
0136 if (m_actsEvaluator)
0137 {
0138 m_evaluator = std::make_unique<ActsEvaluator>(m_evalname);
0139 m_evaluator->Init(topNode);
0140 m_evaluator->verbosity(Verbosity());
0141 }
0142
0143 if (m_seedClusAnalysis)
0144 {
0145 m_outfile = new TFile(m_evalname.c_str(), "RECREATE");
0146 m_tree = new TTree("seedclustree", "Tree with cosmic seeds and their clusters");
0147 makeBranches();
0148 }
0149
0150 if (Verbosity() > 1)
0151 {
0152 std::cout << "Finish PHCosmicsTrkFitter Setup" << std::endl;
0153 }
0154
0155 return Fun4AllReturnCodes::EVENT_OK;
0156 }
0157
0158 int PHCosmicsTrkFitter::process_event(PHCompositeNode* topNode)
0159 {
0160 auto logLevel = Acts::Logging::FATAL;
0161
0162 if (m_actsEvaluator)
0163 {
0164 m_evaluator->next_event(topNode);
0165 }
0166
0167 if (Verbosity() > 1)
0168 {
0169 std::cout << PHWHERE << "Events processed: " << m_event << std::endl;
0170 std::cout << "Start PHCosmicsTrkFitter::process_event" << std::endl;
0171 if (Verbosity() > 30)
0172 {
0173 logLevel = Acts::Logging::VERBOSE;
0174 }
0175 }
0176
0177
0178
0179 if (m_actsEvaluator)
0180 {
0181
0182
0183 m_seedTracks->clear();
0184 for (const auto& [key, track] : *m_trackMap)
0185 {
0186 m_seedTracks->insert(track);
0187 }
0188 }
0189
0190 loopTracks(logLevel);
0191
0192
0193 if (Verbosity() > 0)
0194 {
0195 std::cout << " SvtxTrackMap size is now " << m_trackMap->size()
0196 << std::endl;
0197 }
0198
0199 m_event++;
0200 return Fun4AllReturnCodes::EVENT_OK;
0201 }
0202
0203 int PHCosmicsTrkFitter::ResetEvent(PHCompositeNode* )
0204 {
0205 if (Verbosity() > 1)
0206 {
0207 std::cout << "Reset PHCosmicsTrkFitter" << std::endl;
0208 }
0209
0210 m_trajectories->clear();
0211
0212 return Fun4AllReturnCodes::EVENT_OK;
0213 }
0214
0215 int PHCosmicsTrkFitter::End(PHCompositeNode* )
0216 {
0217 if (m_actsEvaluator)
0218 {
0219 m_evaluator->End();
0220 }
0221 if (m_seedClusAnalysis)
0222 {
0223 m_outfile->cd();
0224 m_tree->Write();
0225 m_outfile->Close();
0226 }
0227 if (Verbosity() > 0)
0228 {
0229 std::cout << "The Acts track fitter succeeded " << m_nGoodFits
0230 << " times and had " << m_nBadFits
0231 << " fits return an error" << std::endl;
0232 std::cout << "There were " << m_nLongSeeds << " long seeds" << std::endl;
0233 std::cout << "Finished PHCosmicsTrkFitter" << std::endl;
0234 }
0235 return Fun4AllReturnCodes::EVENT_OK;
0236 }
0237
0238 void PHCosmicsTrkFitter::loopTracks(Acts::Logging::Level logLevel)
0239 {
0240 auto logger = Acts::getDefaultLogger("PHCosmicsTrkFitter", logLevel);
0241
0242 if (Verbosity() > 0)
0243 {
0244 std::cout << " seed map size " << m_seedMap->size() << std::endl;
0245 }
0246
0247 for (auto track : *m_seedMap)
0248 {
0249 if (!track)
0250 {
0251 continue;
0252 }
0253
0254 unsigned int tpcid = track->get_tpc_seed_index();
0255 unsigned int siid = track->get_silicon_seed_index();
0256
0257
0258 auto siseed = m_siliconSeeds->get(siid);
0259 short crossing = 0;
0260
0261 auto tpcseed = m_tpcSeeds->get(tpcid);
0262 if (Verbosity() > 1)
0263 {
0264 std::cout << "TPC id " << tpcid << std::endl;
0265 std::cout << "Silicon id " << siid << std::endl;
0266 }
0267
0268
0269 if (!tpcseed)
0270 {
0271 continue;
0272 }
0273
0274 if (Verbosity() > 1)
0275 {
0276 const auto position = TrackSeedHelper::get_xyz(tpcseed);
0277 std::cout << " tpc seed position is (x,y,z) = " << position.x() << " " << position.y() << " " << position.z() << std::endl;
0278 }
0279
0280 ActsTrackFittingAlgorithm::MeasurementContainer measurements;
0281
0282 SourceLinkVec sourceLinks;
0283
0284 MakeSourceLinks makeSourceLinks;
0285 makeSourceLinks.initialize(_tpccellgeo);
0286 makeSourceLinks.setVerbosity(Verbosity());
0287 makeSourceLinks.set_pp_mode(false);
0288
0289 makeSourceLinks.resetTransientTransformMap(
0290 m_alignmentTransformationMapTransient,
0291 m_transient_id_set,
0292 m_tGeometry);
0293
0294 if (siseed)
0295 {
0296
0297 sourceLinks = makeSourceLinks.getSourceLinks(
0298 siseed,
0299 measurements,
0300 m_clusterContainer,
0301 m_tGeometry,
0302 m_globalPositionWrapper,
0303 m_alignmentTransformationMapTransient,
0304 m_transient_id_set,
0305 crossing);
0306 }
0307
0308
0309 const auto tpcSourceLinks = makeSourceLinks.getSourceLinks(
0310 tpcseed,
0311 measurements,
0312 m_clusterContainer,
0313 m_tGeometry,
0314 m_globalPositionWrapper,
0315 m_alignmentTransformationMapTransient,
0316 m_transient_id_set,
0317 crossing);
0318
0319 sourceLinks.insert(sourceLinks.end(), tpcSourceLinks.begin(), tpcSourceLinks.end());
0320
0321 if (sourceLinks.size() < 5)
0322 {
0323 continue;
0324 }
0325 int charge = 0;
0326 float cosmicslope = 0;
0327
0328 getCharge(tpcseed, charge, cosmicslope);
0329
0330
0331 m_transient_geocontext = m_alignmentTransformationMapTransient;
0332
0333 {
0334
0335
0336 TrackSeedHelper::position_map_t positions;
0337 for( auto key_iter = tpcseed->begin_cluster_keys(); key_iter != tpcseed->end_cluster_keys(); ++key_iter )
0338 {
0339 const auto& key(*key_iter);
0340 positions.emplace(key, m_tGeometry->getGlobalPosition( key, m_clusterContainer->findCluster(key)));
0341 }
0342
0343 TrackSeedHelper::circleFitByTaubin(tpcseed, positions, 0, 58);
0344 }
0345
0346 float tpcR = fabs(1. / tpcseed->get_qOverR());
0347 float tpcx = tpcseed->get_X0();
0348 float tpcy = tpcseed->get_Y0();
0349
0350 const auto intersect =
0351 TrackFitUtils::circle_circle_intersection(m_vertexRadius,
0352 tpcR, tpcx, tpcy);
0353 float intx, inty;
0354
0355 if (std::get<1>(intersect) > std::get<3>(intersect))
0356 {
0357 intx = std::get<0>(intersect);
0358 inty = std::get<1>(intersect);
0359 }
0360 else
0361 {
0362 intx = std::get<2>(intersect);
0363 inty = std::get<3>(intersect);
0364 }
0365 std::vector<TrkrDefs::cluskey> keys;
0366 std::vector<Acts::Vector3> clusPos;
0367 std::copy(tpcseed->begin_cluster_keys(), tpcseed->end_cluster_keys(), std::back_inserter(keys));
0368 TrackFitUtils::getTrackletClusters(m_tGeometry, m_clusterContainer,
0369 clusPos, keys);
0370 TrackFitUtils::position_vector_t xypoints, rzpoints;
0371 for (auto& pos : clusPos)
0372 {
0373 float clusr = radius(pos.x(), pos.y());
0374 if (pos.y() < 0)
0375 {
0376 clusr *= -1;
0377 }
0378
0379
0380 if (fabs(clusr) > 80 || fabs(clusr) < 30)
0381 {
0382 continue;
0383 }
0384 xypoints.push_back(std::make_pair(pos.x(), pos.y()));
0385 rzpoints.push_back(std::make_pair(pos.z(), clusr));
0386 }
0387
0388 auto rzparams = TrackFitUtils::line_fit(rzpoints);
0389 float fulllineintz = std::get<1>(rzparams);
0390 float fulllineslope = std::get<0>(rzparams);
0391
0392 float slope = tpcseed->get_slope();
0393 float intz = m_vertexRadius * slope + tpcseed->get_Z0();
0394
0395 Acts::Vector3 inter(intx, inty, intz);
0396
0397 std::vector<float> tpcparams{tpcR, tpcx, tpcy, tpcseed->get_slope(),
0398 tpcseed->get_Z0()};
0399 auto tangent = TrackFitUtils::get_helix_tangent(tpcparams,
0400 inter);
0401
0402 auto tan = tangent.second;
0403 auto pca = tangent.first;
0404
0405 float p;
0406 if (m_ConstField)
0407 {
0408 p = cosh(tpcseed->get_eta()) * fabs(1. / tpcseed->get_qOverR()) * (0.3 / 100) * fieldstrength;
0409 }
0410 else
0411 {
0412 p = tpcseed->get_p();
0413 }
0414
0415 tan *= p;
0416
0417
0418
0419
0420
0421
0422 float theta = std::atan(fulllineslope);
0423
0424 if (theta < 0)
0425 {
0426 theta += M_PI;
0427 }
0428 float pz = std::cos(theta) * p;
0429 if (fulllineslope < 0)
0430 {
0431 pz = fabs(pz);
0432 }
0433 else
0434 {
0435 pz = fabs(pz) * -1;
0436 }
0437 Acts::Vector3 momentum = Acts::Vector3::Zero();
0438
0439 if (!m_zeroField)
0440 {
0441 momentum.x() = charge < 0 ? tan.x() : tan.x() * -1;
0442 momentum.y() = charge < 0 ? tan.y() : tan.y() * -1;
0443 }
0444 else
0445 {
0446 auto xyparams = TrackFitUtils::line_fit(xypoints);
0447 float fulllineslopexy = std::get<0>(xyparams);
0448 if (fulllineslopexy < 0)
0449 {
0450 momentum.x() = fabs(tan.x());
0451 }
0452 else
0453 {
0454 momentum.x() = fabs(tan.x()) * -1;
0455 }
0456 momentum.y() = fabs(tan.y()) * -1;
0457 }
0458
0459 momentum.z() = pz;
0460 Acts::Vector3 position(pca.x(), pca.y(),
0461 (m_vertexRadius - fulllineintz) / fulllineslope);
0462
0463 position *= Acts::UnitConstants::cm;
0464 if (!is_valid(momentum))
0465 {
0466 continue;
0467 }
0468
0469 auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
0470 position);
0471 auto actsFourPos = Acts::Vector4(position(0), position(1),
0472 position(2),
0473 10 * Acts::UnitConstants::ns);
0474
0475 if (sourceLinks.size() > 20)
0476 {
0477 m_nLongSeeds++;
0478 }
0479 Acts::BoundSquareMatrix cov = setDefaultCovariance();
0480 if (m_seedClusAnalysis)
0481 {
0482 clearVectors();
0483 m_seed = tpcid;
0484 m_R = tpcR;
0485 m_X0 = tpcx;
0486 m_Y0 = tpcy;
0487 m_Z0 = fulllineintz;
0488 m_slope = fulllineslope;
0489 m_pcax = position(0);
0490 m_pcay = position(1);
0491 m_pcaz = position(2);
0492 m_px = momentum(0);
0493 m_py = momentum(1);
0494 m_pz = momentum(2);
0495 m_charge = charge;
0496 fillVectors(siseed, tpcseed);
0497 m_tree->Fill();
0498 }
0499
0500 auto seed = ActsTrackFittingAlgorithm::TrackParameters::create(
0501 pSurface,
0502 m_transient_geocontext,
0503 actsFourPos,
0504 momentum,
0505 charge / momentum.norm(),
0506 cov,
0507 Acts::ParticleHypothesis::muon(),
0508 100 * Acts::UnitConstants::cm);
0509 if (!seed.ok())
0510 {
0511 std::cout << "Could not create track params, skipping track" << std::endl;
0512 continue;
0513 }
0514
0515 if (Verbosity() > 0)
0516 {
0517 std::cout << "Source link size " << sourceLinks.size() << std::endl;
0518 printTrackSeed(seed.value());
0519 }
0520
0521
0522 Acts::PropagatorPlainOptions ppPlainOptions;
0523
0524 auto calibptr = std::make_unique<Calibrator>();
0525 CalibratorAdapter calibrator{*calibptr, measurements};
0526
0527 auto magcontext = m_tGeometry->geometry().magFieldContext;
0528 auto calibcontext = m_tGeometry->geometry().calibContext;
0529
0530 ActsTrackFittingAlgorithm::GeneralFitterOptions
0531 kfOptions{
0532 m_transient_geocontext,
0533 magcontext,
0534 calibcontext,
0535 &(*pSurface),
0536 ppPlainOptions};
0537
0538 auto trackContainer =
0539 std::make_shared<Acts::VectorTrackContainer>();
0540 auto trackStateContainer =
0541 std::make_shared<Acts::VectorMultiTrajectory>();
0542 ActsTrackFittingAlgorithm::TrackContainer
0543 tracks(trackContainer, trackStateContainer);
0544 auto result = fitTrack(sourceLinks, seed.value(), kfOptions,
0545 calibrator, tracks);
0546
0547
0548 if (result.ok())
0549 {
0550 SvtxTrack_v4 newTrack;
0551 newTrack.set_tpc_seed(tpcseed);
0552 newTrack.set_crossing(crossing);
0553 newTrack.set_silicon_seed(siseed);
0554
0555 unsigned int trid = m_trackMap->size();
0556 newTrack.set_id(trid);
0557
0558 if (getTrackFitResult(result, track, &newTrack, tracks, measurements))
0559 {
0560 m_trackMap->insertWithKey(&newTrack, trid);
0561 }
0562 m_nGoodFits++;
0563 }
0564 else
0565 {
0566 m_nBadFits++;
0567 if (Verbosity() > 1)
0568 {
0569 std::cout << "Track fit failed for track " << m_seedMap->find(track)
0570 << " with Acts error message "
0571 << result.error() << ", " << result.error().message()
0572 << std::endl;
0573 }
0574 }
0575 }
0576
0577 return;
0578 }
0579
0580 bool PHCosmicsTrkFitter::getTrackFitResult(FitResult& fitOutput,
0581 TrackSeed* seed, SvtxTrack* track,
0582 ActsTrackFittingAlgorithm::TrackContainer& tracks,
0583 const ActsTrackFittingAlgorithm::MeasurementContainer& measurements)
0584 {
0585
0586
0587 auto& outtrack = fitOutput.value();
0588 std::vector<Acts::MultiTrajectoryTraits::IndexType> trackTips;
0589 trackTips.reserve(1);
0590 trackTips.emplace_back(outtrack.tipIndex());
0591 Trajectory::IndexedParameters indexedParams;
0592
0593 indexedParams.emplace(std::pair{outtrack.tipIndex(),
0594 ActsExamples::TrackParameters{outtrack.referenceSurface().getSharedPtr(),
0595 outtrack.parameters(), outtrack.covariance(), outtrack.particleHypothesis()}});
0596
0597 if (Verbosity() > 2)
0598 {
0599 std::cout << "Fitted parameters for track" << std::endl;
0600 std::cout << " position : " << outtrack.referenceSurface().localToGlobal(m_transient_geocontext, Acts::Vector2(outtrack.loc0(), outtrack.loc1()), Acts::Vector3(1, 1, 1)).transpose()
0601
0602 << std::endl;
0603
0604 int otcharge = outtrack.qOverP() > 0 ? 1 : -1;
0605 std::cout << "charge: " << otcharge << std::endl;
0606 std::cout << " momentum : " << outtrack.momentum().transpose()
0607 << std::endl;
0608 std::cout << "For trackTip == " << outtrack.tipIndex() << std::endl;
0609 }
0610
0611 Trajectory trajectory(tracks.trackStateContainer(),
0612 trackTips, indexedParams);
0613
0614 m_trajectories->insert(std::make_pair(track->get_id(), trajectory));
0615
0616
0617
0618 updateSvtxTrack(trackTips, indexedParams, tracks, track);
0619
0620 if (m_commissioning)
0621 {
0622 if (track->get_silicon_seed() && track->get_tpc_seed())
0623 {
0624 m_alignStates.fillAlignmentStateMap(tracks, trackTips,
0625 track, measurements);
0626 }
0627 }
0628
0629 if (m_actsEvaluator)
0630 {
0631 m_evaluator->evaluateTrackFit(tracks, trackTips, indexedParams, track,
0632 seed, measurements);
0633 }
0634
0635 return true;
0636 }
0637
0638 inline ActsTrackFittingAlgorithm::TrackFitterResult PHCosmicsTrkFitter::fitTrack(
0639 const std::vector<Acts::SourceLink>& sourceLinks,
0640 const ActsTrackFittingAlgorithm::TrackParameters& seed,
0641 const ActsTrackFittingAlgorithm::GeneralFitterOptions& kfOptions,
0642 const CalibratorAdapter& calibrator,
0643 ActsTrackFittingAlgorithm::TrackContainer& tracks)
0644 {
0645 return (*m_fitCfg.fit)(sourceLinks, seed, kfOptions, calibrator, tracks);
0646 }
0647
0648 void PHCosmicsTrkFitter::updateSvtxTrack(
0649 std::vector<Acts::MultiTrajectoryTraits::IndexType>& tips,
0650 Trajectory::IndexedParameters& paramsMap,
0651 ActsTrackFittingAlgorithm::TrackContainer& tracks,
0652 SvtxTrack* track)
0653 {
0654 const auto& mj = tracks.trackStateContainer();
0655
0656
0657 auto& trackTip = tips.front();
0658
0659 if (Verbosity() > 2)
0660 {
0661 std::cout << "Identify (proto) track before updating with acts results " << std::endl;
0662 track->identify();
0663 }
0664
0665
0666
0667 float pathlength = 0.0;
0668 SvtxTrackState_v1 out(pathlength);
0669 out.set_x(0.0);
0670 out.set_y(0.0);
0671 out.set_z(0.0);
0672 track->insert_state(&out);
0673
0674 auto trajState =
0675 Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip);
0676
0677 const auto& params = paramsMap.find(trackTip)->second;
0678
0679
0680 track->set_x(params.position(m_transient_geocontext)(0) / Acts::UnitConstants::cm);
0681 track->set_y(params.position(m_transient_geocontext)(1) / Acts::UnitConstants::cm);
0682 track->set_z(params.position(m_transient_geocontext)(2) / Acts::UnitConstants::cm);
0683
0684 track->set_px(params.momentum()(0));
0685 track->set_py(params.momentum()(1));
0686 track->set_pz(params.momentum()(2));
0687
0688 track->set_charge(params.charge());
0689 track->set_chisq(trajState.chi2Sum);
0690 track->set_ndf(trajState.NDF);
0691
0692 ActsTransformations rotater;
0693 rotater.setVerbosity(Verbosity());
0694
0695 if (params.covariance())
0696 {
0697 auto rotatedCov = rotater.rotateActsCovToSvtxTrack(params);
0698
0699 for (int i = 0; i < 6; i++)
0700 {
0701 for (int j = 0; j < 6; j++)
0702 {
0703 track->set_error(i, j, rotatedCov(i, j));
0704 }
0705 }
0706 }
0707
0708
0709
0710
0711 if (m_fillSvtxTrackStates)
0712 {
0713 rotater.fillSvtxTrackStates(mj, trackTip, track,
0714 m_transient_geocontext);
0715 }
0716
0717 if (Verbosity() > 2)
0718 {
0719 std::cout << " Identify fitted track after updating track states:"
0720 << std::endl;
0721 track->identify();
0722 }
0723
0724 return;
0725 }
0726
0727 Acts::BoundSquareMatrix PHCosmicsTrkFitter::setDefaultCovariance() const
0728 {
0729 Acts::BoundSquareMatrix cov = Acts::BoundSquareMatrix::Zero();
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740 double sigmaD0 = 300 * Acts::UnitConstants::um;
0741 double sigmaZ0 = 300 * Acts::UnitConstants::um;
0742
0743 double sigmaPhi = 1 * Acts::UnitConstants::degree;
0744 double sigmaTheta = 1 * Acts::UnitConstants::degree;
0745 double sigmaT = 1. * Acts::UnitConstants::ns;
0746
0747 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = sigmaD0 * sigmaD0;
0748 cov(Acts::eBoundLoc1, Acts::eBoundLoc1) = sigmaZ0 * sigmaZ0;
0749 cov(Acts::eBoundTime, Acts::eBoundTime) = sigmaT * sigmaT;
0750 cov(Acts::eBoundPhi, Acts::eBoundPhi) = sigmaPhi * sigmaPhi;
0751 cov(Acts::eBoundTheta, Acts::eBoundTheta) = sigmaTheta * sigmaTheta;
0752
0753 cov(Acts::eBoundQOverP, Acts::eBoundQOverP) = 0.0001;
0754
0755 return cov;
0756 }
0757
0758 void PHCosmicsTrkFitter::printTrackSeed(const ActsTrackFittingAlgorithm::TrackParameters& seed) const
0759 {
0760 std::cout
0761 << PHWHERE
0762 << " Processing proto track:"
0763 << std::endl;
0764
0765 std::cout
0766 << "position: " << seed.position(m_transient_geocontext).transpose()
0767 << std::endl
0768 << "momentum: " << seed.momentum().transpose()
0769 << std::endl;
0770
0771 std::cout << "charge : " << seed.charge() << std::endl;
0772 std::cout << "absolutemom : " << seed.absoluteMomentum() << std::endl;
0773 }
0774
0775 int PHCosmicsTrkFitter::createNodes(PHCompositeNode* topNode)
0776 {
0777 PHNodeIterator iter(topNode);
0778
0779 PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
0780
0781 if (!dstNode)
0782 {
0783 std::cerr << "DST node is missing, quitting" << std::endl;
0784 throw std::runtime_error("Failed to find DST node in PHCosmicsTrkFitter::createNodes");
0785 }
0786
0787 PHNodeIterator dstIter(topNode);
0788 PHCompositeNode* svtxNode = dynamic_cast<PHCompositeNode*>(dstIter.findFirst("PHCompositeNode", "SVTX"));
0789
0790 if (!svtxNode)
0791 {
0792 svtxNode = new PHCompositeNode("SVTX");
0793 dstNode->addNode(svtxNode);
0794 }
0795
0796 m_trajectories = findNode::getClass<std::map<const unsigned int, Trajectory>>(topNode, "ActsTrajectories");
0797 if (!m_trajectories)
0798 {
0799 m_trajectories = new std::map<const unsigned int, Trajectory>;
0800 auto node =
0801 new PHDataNode<std::map<const unsigned int, Trajectory>>(m_trajectories, "ActsTrajectories");
0802 svtxNode->addNode(node);
0803 }
0804
0805 m_trackMap = findNode::getClass<SvtxTrackMap>(topNode, _track_map_name);
0806
0807 if (!m_trackMap)
0808 {
0809 m_trackMap = new SvtxTrackMap_v2;
0810 PHIODataNode<PHObject>* node = new PHIODataNode<PHObject>(m_trackMap, _track_map_name, "PHObject");
0811 svtxNode->addNode(node);
0812 }
0813
0814 m_alignmentStateMap = findNode::getClass<SvtxAlignmentStateMap>(topNode, "SvtxAlignmentStateMap");
0815 if (!m_alignmentStateMap)
0816 {
0817 m_alignmentStateMap = new SvtxAlignmentStateMap_v1;
0818 auto node = new PHDataNode<SvtxAlignmentStateMap>(m_alignmentStateMap, "SvtxAlignmentStateMap", "PHObject");
0819 svtxNode->addNode(node);
0820 }
0821
0822 m_alignmentTransformationMapTransient = findNode::getClass<alignmentTransformationContainer>(topNode, "alignmentTransformationContainerTransient");
0823 if (!m_alignmentTransformationMapTransient)
0824 {
0825 std::cout << PHWHERE << "alignmentTransformationContainerTransient not on node tree. Bailing"
0826 << std::endl;
0827 return Fun4AllReturnCodes::ABORTEVENT;
0828 }
0829
0830 if (m_actsEvaluator)
0831 {
0832 m_seedTracks = findNode::getClass<SvtxTrackMap>(topNode, _seed_track_map_name);
0833
0834 if (!m_seedTracks)
0835 {
0836 m_seedTracks = new SvtxTrackMap_v2;
0837
0838 PHIODataNode<PHObject>* seedNode =
0839 new PHIODataNode<PHObject>(m_seedTracks, _seed_track_map_name, "PHObject");
0840 svtxNode->addNode(seedNode);
0841 }
0842 }
0843
0844 return Fun4AllReturnCodes::EVENT_OK;
0845 }
0846
0847 int PHCosmicsTrkFitter::getNodes(PHCompositeNode* topNode)
0848 {
0849
0850 m_tpcSeeds = findNode::getClass<TrackSeedContainer>(topNode, "TpcTrackSeedContainer");
0851 if (!m_tpcSeeds)
0852 {
0853 std::cout << PHWHERE << "TpcTrackSeedContainer not on node tree. Bailing"
0854 << std::endl;
0855 return Fun4AllReturnCodes::ABORTEVENT;
0856 }
0857
0858
0859 m_siliconSeeds = findNode::getClass<TrackSeedContainer>(topNode, "SiliconTrackSeedContainer");
0860 if (!m_siliconSeeds)
0861 {
0862 std::cout << PHWHERE << "SiliconTrackSeedContainer not on node tree. Bailing"
0863 << std::endl;
0864 return Fun4AllReturnCodes::ABORTEVENT;
0865 }
0866
0867
0868 m_clusterContainer = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
0869 if (!m_clusterContainer)
0870 {
0871 std::cout << PHWHERE
0872 << "No trkr cluster container, exiting." << std::endl;
0873 return Fun4AllReturnCodes::ABORTEVENT;
0874 }
0875
0876
0877 m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0878 if (!m_tGeometry)
0879 {
0880 std::cout << "ActsGeometry not on node tree. Exiting."
0881 << std::endl;
0882
0883 return Fun4AllReturnCodes::ABORTEVENT;
0884 }
0885
0886
0887 m_seedMap = findNode::getClass<TrackSeedContainer>(topNode, "SvtxTrackSeedContainer");
0888 if (!m_seedMap)
0889 {
0890 std::cout << "No Svtx seed map on node tree. Exiting."
0891 << std::endl;
0892 return Fun4AllReturnCodes::ABORTEVENT;
0893 }
0894
0895
0896 m_globalPositionWrapper.loadNodes(topNode);
0897
0898 return Fun4AllReturnCodes::EVENT_OK;
0899 }
0900
0901 void PHCosmicsTrkFitter::makeBranches()
0902 {
0903 m_tree->Branch("seed", &m_seed, "m_seed/I");
0904 m_tree->Branch("event", &m_event, "m_event/I");
0905 m_tree->Branch("R", &m_R, "m_R/F");
0906 m_tree->Branch("X0", &m_X0, "m_X0/F");
0907 m_tree->Branch("Y0", &m_Y0, "m_Y0/F");
0908 m_tree->Branch("Z0", &m_Z0, "m_Z0/F");
0909 m_tree->Branch("slope", &m_slope, "m_slope/F");
0910 m_tree->Branch("pcax", &m_pcax, "m_pcax/F");
0911 m_tree->Branch("pcay", &m_pcay, "m_pcay/F");
0912 m_tree->Branch("pcaz", &m_pcaz, "m_pcaz/F");
0913 m_tree->Branch("px", &m_px, "m_px/F");
0914 m_tree->Branch("py", &m_py, "m_py/F");
0915 m_tree->Branch("pz", &m_pz, "m_pz/F");
0916 m_tree->Branch("charge", &m_charge, "m_charge/I");
0917 m_tree->Branch("nmaps", &m_nmaps, "m_nmaps/I");
0918 m_tree->Branch("nintt", &m_nintt, "m_nintt/I");
0919 m_tree->Branch("ntpc", &m_ntpc, "m_ntpc/I");
0920 m_tree->Branch("nmm", &m_nmm, "m_nmm/I");
0921 m_tree->Branch("locx", &m_locx);
0922 m_tree->Branch("locy", &m_locy);
0923 m_tree->Branch("x", &m_x);
0924 m_tree->Branch("y", &m_y);
0925 m_tree->Branch("z", &m_z);
0926 m_tree->Branch("r", &m_r);
0927 m_tree->Branch("layer", &m_layer);
0928 m_tree->Branch("phi", &m_phi);
0929 m_tree->Branch("eta", &m_eta);
0930 m_tree->Branch("phisize", &m_phisize);
0931 m_tree->Branch("zsize", &m_zsize);
0932 m_tree->Branch("ephi", &m_ephi);
0933 m_tree->Branch("ez", &m_ez);
0934 }
0935 void PHCosmicsTrkFitter::fillVectors(TrackSeed* tpcseed, TrackSeed* siseed)
0936 {
0937 for (auto seed : {tpcseed, siseed})
0938 {
0939 if (!seed)
0940 {
0941 continue;
0942 }
0943
0944 for (auto it = seed->begin_cluster_keys(); it != seed->end_cluster_keys();
0945 ++it)
0946 {
0947 auto key = *it;
0948 auto cluster = m_clusterContainer->findCluster(key);
0949 m_locx.push_back(cluster->getLocalX());
0950 float ly = cluster->getLocalY();
0951 if (TrkrDefs::getTrkrId(key) == TrkrDefs::TrkrId::tpcId)
0952 {
0953 double drift_velocity = m_tGeometry->get_drift_velocity();
0954 double zdriftlength = cluster->getLocalY() * drift_velocity;
0955 double surfCenterZ = 52.89;
0956 double zloc = surfCenterZ - zdriftlength;
0957 unsigned int side = TpcDefs::getSide(key);
0958 if (side == 0)
0959 {
0960 zloc = -zloc;
0961 }
0962 ly = zloc * 10;
0963 }
0964 m_locy.push_back(ly);
0965 auto glob = m_tGeometry->getGlobalPosition(key, cluster);
0966 m_x.push_back(glob.x());
0967 m_y.push_back(glob.y());
0968 m_z.push_back(glob.z());
0969 float r = std::sqrt(glob.x() * glob.x() + glob.y() * glob.y());
0970 m_r.push_back(r);
0971 TVector3 globt(glob.x(), glob.y(), glob.z());
0972 m_phi.push_back(globt.Phi());
0973 m_eta.push_back(globt.Eta());
0974 m_phisize.push_back(cluster->getPhiSize());
0975 m_zsize.push_back(cluster->getZSize());
0976 auto para_errors =
0977 m_clusErrPara.get_clusterv5_modified_error(cluster, r, key);
0978
0979 m_ephi.push_back(std::sqrt(para_errors.first));
0980 m_ez.push_back(std::sqrt(para_errors.second));
0981 }
0982 }
0983 }
0984 void PHCosmicsTrkFitter::clearVectors()
0985 {
0986 m_locx.clear();
0987 m_locy.clear();
0988 m_x.clear();
0989 m_y.clear();
0990 m_z.clear();
0991 m_layer.clear();
0992 m_r.clear();
0993 m_phi.clear();
0994 m_eta.clear();
0995 m_phisize.clear();
0996 m_zsize.clear();
0997 m_ephi.clear();
0998 m_ez.clear();
0999 }
1000
1001 void PHCosmicsTrkFitter::getCharge(
1002 TrackSeed* track,
1003
1004
1005
1006
1007 int& charge,
1008 float& cosmicslope)
1009 {
1010 Acts::GeometryContext transient_geocontext;
1011 transient_geocontext = m_alignmentTransformationMapTransient;
1012
1013 std::vector<Acts::Vector3> global_vec;
1014
1015 for (auto clusIter = track->begin_cluster_keys();
1016 clusIter != track->end_cluster_keys();
1017 ++clusIter)
1018 {
1019 auto key = *clusIter;
1020 auto cluster = m_clusterContainer->findCluster(key);
1021 if (!cluster)
1022 {
1023 std::cout << "MakeSourceLinks::getCharge: Failed to get cluster with key " << key << " for track seed" << std::endl;
1024 continue;
1025 }
1026
1027 auto surf = m_tGeometry->maps().getSurface(key, cluster);
1028 if (!surf)
1029 {
1030 continue;
1031 }
1032
1033
1034 Acts::Vector2 local = m_tGeometry->getLocalCoords(key, cluster);
1035 Acts::Vector3 glob = surf->localToGlobal(transient_geocontext,
1036 local * Acts::UnitConstants::cm,
1037 Acts::Vector3(1, 1, 1));
1038 glob /= Acts::UnitConstants::cm;
1039
1040 global_vec.push_back(glob);
1041 }
1042
1043 Acts::Vector3 globalMostOuter(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN());
1044 Acts::Vector3 globalSecondMostOuter(0, 999999, 0);
1045 float largestR = 0;
1046
1047 for (auto& i : global_vec)
1048 {
1049 Acts::Vector3 global = i;
1050
1051 float r = radius(global.x(), global.y());
1052
1053
1054 if (r > largestR && global.y() > 0)
1055 {
1056 globalMostOuter = i;
1057 largestR = r;
1058 }
1059 }
1060
1061
1062 float maxdr = std::numeric_limits<float>::max();
1063 for (auto& i : global_vec)
1064 {
1065 if (i.y() < 0)
1066 {
1067 continue;
1068 }
1069
1070 float dr = std::sqrt(square(globalMostOuter.x()) + square(globalMostOuter.y())) - std::sqrt(square(i.x()) + square(i.y()));
1071
1072
1073 if (dr < maxdr && dr > 10)
1074 {
1075 maxdr = dr;
1076 globalSecondMostOuter = i;
1077 }
1078 }
1079
1080
1081
1082 Acts::Vector3 vertex(0, m_vertexRadius, 0);
1083 globalMostOuter -= vertex;
1084 globalSecondMostOuter -= vertex;
1085
1086 const auto firstphi = atan2(globalMostOuter.y(), globalMostOuter.x());
1087 const auto secondphi = atan2(globalSecondMostOuter.y(),
1088 globalSecondMostOuter.x());
1089 auto dphi = secondphi - firstphi;
1090
1091 if (dphi > M_PI)
1092 {
1093 dphi = 2. * M_PI - dphi;
1094 }
1095 if (dphi < -M_PI)
1096 {
1097 dphi = 2 * M_PI + dphi;
1098 }
1099
1100 if (dphi > 0)
1101 {
1102 charge = -1;
1103 }
1104 else
1105 {
1106 charge = 1;
1107 }
1108
1109 float r1 = std::sqrt(square(globalMostOuter.x()) + square(globalMostOuter.y()));
1110 float r2 = std::sqrt(square(globalSecondMostOuter.x()) + square(globalSecondMostOuter.y()));
1111 float z1 = globalMostOuter.z();
1112 float z2 = globalSecondMostOuter.z();
1113 cosmicslope = (r2 - r1) / (z2 - z1);
1114
1115 return;
1116 }